專案記錄:MPEG-DASH整理2
阿新 • • 發佈:2018-12-07
專案記錄:MPEG-DASH整理2
這一篇主要是介紹DASH封裝 (如何生成DASH媒體內容)
以及 關於DASh實現的一些軟體與程式庫,重點會看 libdash
DASH媒體內容的生成
- DASH(Dynamic Adaptive Streaming over HTTP)即自適應流媒體傳輸,典型的系統框圖如下:
- 在伺服器端提前存好同一內容的不同位元速率、不同解析度的多個分片以及相應的描述檔案MPD,客戶端在播放時即可以根據自身效能以及網路環境選擇最適宜的版本。更多詳細的內容可以參見MPEG組織出臺的標準,標準號ISO/IEC 23009-1。
- 如何在伺服器端生成對應的媒體內容和相應的MPD檔案呢?
- 輸入
- 編碼
- 分片
- 生成MPD
內容生成器
-
MP4Box
-
FFMPEG
等等
DASH實現
伺服器
- 將生成好的媒體內容和MPD檔案放到伺服器上;
- Nginx 搭建DASH伺服器
客戶端和程式庫
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;
佇列中.