项目记录:MPEG-DASH整理2

项目记录:MPEG-DASH整理2

这一篇主要是介绍DASH封装 (如何生成DASH媒体内容)

以及 关于DASh实现的一些软件与程序库,重点会看 libdash

DASH媒体内容的生成

  • DASH(Dynamic Adaptive Streaming over HTTP)即自适应流媒体传输,典型的系统框图如下:

img

  • 在服务器端提前存好同一内容的不同码率、不同分辨率的多个分片以及相应的描述文件MPD,客户端在播放时即可以根据自身性能以及网络环境选择最适宜的版本。更多详细的内容可以参见MPEG组织出台的标准,标准号ISO/IEC 23009-1。
  • 如何在服务器端生成对应的媒体内容和相应的MPD文件呢?
    1. 输入
    2. 编码
    3. 分片
    4. 生成MPD

内容生成器

  • MP4Box

  • FFMPEG

    等等


DASH实现

服务器

客户端和程序库

  • 参考Wiki百科;

  • libdash

    libdash是bitmovin公司开源的一个DASH库,完整实现了DASH协议,可以在Github上获取其代码。

Libdash

  • 从Github下载了 2.2版本的进行研究.libdash作为一个库提供给SamplePlayer调用.

SamplePlayer

SamplePlayer是一个 Dash客户端.

主要三个类:

  • SDLRenderer : 使用SDL进行渲染显示;
  • DASHReceiver :调用Libdash负责下载媒体文件;
  • LibavDecoder : 调用FFMPEG作为解码工具;

程序按 观察者模式 进行设计.

具体细节:

[mian函数]

int main(int argc, char *argv[])
{
	
    SDLRenderer     *renderer = new SDLRenderer();	  // 创建一个SDLRender类对象
	DASHReceiver    *receiver = new DASHReceiver(30); // Init a DASHReceiver with a buffer size of 30 Segments

	//receiver->Init("http://127.0.0.1/cuc_ieschool_2s.mpd");
	receiver->Init("http://127.0.0.1/1.mpd");

	// 通过 DASHReceiver实例receiver的数据 创建 一个LibavDecoder的实例decoder
    LibavDecoder *decoder = new LibavDecoder(receiver);

	// 将SDLRenderer的实例renderer注册为LibavDecoder的观察者
    decoder->attachVideoObserver(renderer);
    decoder->setFrameRate(30);
	
	// !!!
    decoder->init();
    
    bool eos = false;

    while(!renderer->isQuitKeyPressed() && !eos)
	{
        eos = !decoder->decode(); // 解码和通知渲染!!!

		renderer->processEvents(); // 处理SDL的按键事件
    }

    decoder->stop();
    return 0;
}

[ 自适应下载逻辑 ]

namespace sampleplayer
{
    namespace input
    {
        class DASHReceiver : public IDataReceiver
        {
            public:
                DASHReceiver            (uint32_t maxcapacity);
                virtual ~DASHReceiver   ();

                bool Init   (std::string mpdurl);

                virtual int IORead (uint8_t *buf, int buf_size);

            private:
                dash::IDASHManager  *manager; //manager解析url返回一个mpd给 this->mpd
                dash::mpd::IMPD     *mpd;
                MediaObjectBuffer   *buffer;

                int                 count;
                uint32_t            maxcapacity;
                AdaptationLogic     *logic;
                THREAD_HANDLE       bufferingThread;

                /* Thread that does the buffering of segments */
				static void* DoBuffering(void *receiver);
				
        };
    }
}

[ DASHReceiver 类中 ]

  • dash::IDASHManager *manager; 复杂解析给定mpd_url返回一个mpd给 dash::mpd::IMPD *mpd;

  • MediaObjectBuffer *buffer; 其实完成一个队列的功能,复杂管理下载的数据

    namespace sampleplayer
    {
        namespace input
        {
            class MediaObjectBuffer
            {
                public:
                    MediaObjectBuffer             (uint32_t maxcapacity);
                    virtual ~MediaObjectBuffer    ();
    
                    void            Push    (MediaObject *media);
                    MediaObject*    Front   ();
                    void            Pop     ();
                    void            SetEOS  (bool value);
                    uint32_t        Length  ();
    
                private:
                    std::queue<MediaObject *>   mediaobjects;
                    bool                        eos;
                    uint32_t                    maxcapacity;
                    mutable CRITICAL_SECTION    monitorMutex;
                    mutable CONDITION_VARIABLE  full;
                    mutable CONDITION_VARIABLE  empty;
            };
        }
    }
    
  • AdaptationLogic *logic; 负责控制下载逻辑.下载的逻辑与控制可以在进行修改

  • static void* DoBuffering(void *receiver); 这是一个线程,主要就是负责下载,将下载的 MediaObject *media 放进MediaObjectBuffer *buffer; 队列中.

参考文档

  1. 自适应流媒体传输(一)——DASH媒体内容的生成
  2. Nginx 搭建DASH服务器
  3. LibDash代码解析

猜你喜欢

转载自blog.csdn.net/qjh5606/article/details/84787967