【視訊處理工程】6、使用Lav Filter手動建立Filter Graph並播放視訊檔案
在前面的這篇博文中,我們開始利用的手動建立Filter Graph,已經完成了Splitter Source Filter和Audio/Video Decoder的建立和連結。接下來需要做的是渲染解碼完成的音視訊資料,分別由Audio Render和Video Render完成。音訊渲染器較為簡單也很少會出問題,我們主要討論視訊渲染器的問題。
DirectShow所提供的視訊渲染器種類有多種,如Video Renderer(已不常用)、VMR-7、VMR-9、EVR等。MSDN的文件講了各種視訊渲染器的相關知識。其中提到了“在vista之後的windows版本中,如果硬體支援應使用EVR”,既然已經是win 7了,那自然是首選EVR了。這部分的程式碼如下:
int _tmain(int argc, _TCHAR* argv[]) { //...... hr = AddFilterByCLSID(pGraph,CLSID_LavSplitter_Source,L"Lav Splitter Source",&pLavSplitterSource); hr = pLavSplitterSource->QueryInterface(IID_IFileSourceFilter,(void **)&pFileSourceFilter); hr = pFileSourceFilter->Load(fileName,NULL);//必須loadfile後才能檢索pin hr = AddFilterByCLSID(pGraph,CLSID_LavVideoDecoder,L"Lav Video Decoder",&pLavVideoDecoder); hr = ConnectFilters(pGraph,pLavSplitterSource,pLavVideoDecoder); hr = AddFilterByCLSID(pGraph,CLSID_LavAudioDecoder,L"Lav Audio Decoder",&pLavAudioDecoder); hr = ConnectFilters(pGraph,pLavSplitterSource,pLavAudioDecoder); hr = AddFilterByCLSID(pGraph,CLSID_EnhancedVideoRenderer,L"Enhanced Video Renderer",&pRenderer); hr = ConnectFilters(pGraph,pLavVideoDecoder,pRenderer); hr = AddFilterByCLSID(pGraph,CLSID_AudioRender,L"Audio render",&pAudioRender); hr = ConnectFilters(pGraph,pLavAudioDecoder,pAudioRender); //...... }
Build工程後執行,使用GraphStudioNext檢視生成的Filter Graph,可以看到音視訊渲染器都已經成功加入了,如下圖所示:
但是我們發現一個問題,電影已經正常播放,但是隻有聲音卻沒有影象,這是為何?
通過搜尋得知,DirectShow的渲染器定義了兩種模式:視窗模式和非視窗模式。視窗模式下,視訊渲染器會自動生成一個視訊播放視窗,渲染完成的畫面會顯示在這個視訊視窗中;當然我們可以獲取這個視窗的控制代碼進行下一步操作比如講該視窗置於我們自定義的應用視窗下加以控制。非視窗模式下,視訊渲染器需要指定一個視訊輸出視窗,將資料渲染在該視窗中。在這兩種模式中,Video Renderer只支援視窗模式,VMR-7/9支援兩種模式,預設為視窗模式。而在
既然不支援,那我們就換掉,改為使用VMR-9進行繪製。方法很簡單,在新增EVR元件的語句中將CLSID_EnhancedVideoRenderer改為CLSID_VideoMixingRenderer9就可以了。
編譯連結執行,檢視Filter Graph,如下圖:
播放畫面:
至此,我們已經成功地把一部主流格式的電影檔案通過手動建立Filter Graph的方式播放出來了,也對DirectShow的基本概念有了一定的瞭解。接下來還將繼續進一步深入研究與其相關的更多內容。
下載該demo點這裡