Directshow 視頻捕捉 三

如何捕捉視頻流並保存到文件(Capture video to File)

1 將視頻流保存到AVI文件


AVI Mux filter接收從capture pin過來的視頻流,然後將其打包成AVI流。音頻流也可以連接到AVI Mux Filter上,這樣mux filter就將視頻流和視頻流合成AVI流。File writer將AVI流寫入到文件中。
可以像下面這樣構建graph圖

Cpp代碼  收藏代碼
  1. IBaseFilter *pMux;  
  2. hr = pBuild->SetOutputFileName(&MEDIASUBTYPE_Avi,            //Specifies AVI for the target file  
  3.                                 L"C:\\Example.avi",             //File name  
  4.                                &pMux,                                   //Receives a pointer to the mux  
  5.                                NULL);       //(Optional)Receives a pointer to the file sink  

 

 

第一個參數表明文件的類型,這裏表明是AVI,第二個參數是制定文件的名稱。對於AVI文件,SetOutputFileName函數會創建一個AVI mux Filter 和一個 File writer Filter ,並且將兩個filter添加到graph圖中,在這個函數中,通過File Writer Filter 請求IFileSinkFilter接口,然後調用IFileSinkFilter::SetFileName方法,設置文件的名稱。然後將兩個filter連接起來。第三個參數返回一個指向 AVI Mux的指針,同時,它也通過第四個參數返回一個IFileSinkFilter參數,如果你不需要這個參數,你可以將這個參數設置成NULL。
然後,你應該調用下面的函數將capture filter 和AVI Mux連接起來。

Cpp代碼  收藏代碼
  1. hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE,         //Pin category  
  2.                           &MEDIATYPE_Video,         //Media type  
  3.                           pCap,         //Capture filter  
  4.                           NULL,         //Intermediate filter(optional)  
  5.                           pMux);         //Mux or file sink filter  
  6. //Release the mux filter  
  7. pMux->Release();  

 

 

第5個參數就是使用的上面函數返回的pMux指針。
當捕捉音頻的時候,媒體類型要設置爲MEDIATYPE_Audio,如果你從兩個不同的設備捕捉視頻和音頻,你最好將音頻設置成主流,這樣可以防止兩個數據流間drift,因爲avi mux filter爲同步音頻,會調整視頻的播放速度的。爲了設置master 流,調用IConfigAviMux::SetMasterStream方法,可以採用如下的代碼:

Cpp代碼  收藏代碼
  1. IConfigAviMux *pConfigMux = NULL;  
  2. hr = pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux);  
  3. if(SUCCEEDED(hr))  
  4. {  
  5.     pConfigMux->SetMasterStream(1);  
  6.     pConfigMux->Release();  
  7. }  

 

 

SetMasterStream的參數指的是數據流的數目,這個是由調用RenderStream的次序決定的。例如,如果你調用RenderStream首先用於視頻流,然後是音頻,那麼視頻流就是0,音頻流就是1。
添加編碼filter

Cpp代碼  收藏代碼
  1. IBaseFilter *pEncoder;  
  2. //Add it to the filter graph  
  3. pGraph->AddFilter(pEncoder, L"Encode");  
  4. //Render the stream  
  5. hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,   
  6.                           pCap, pEncoder, pMux);  
  7. pEncoder->Release();  

 

 

2 將視頻流保存成wmv格式的文件


爲了將視頻流保存成並編碼成windows media video (WMV)格式的文件,將capture pin連到WM ASF Writer filter。

構建graph圖最簡單的方法就是將在ICaptureGraphBuilder2::SetOutputFileName方法中指定MEDIASUBTYPE_Asf的filter。如下

Cpp代碼  收藏代碼
  1. IBaseFilter *pASFWriter = 0;  
  2. hr = pBuild->SetOutputFileName(&MEDIASUBTYPE_Asf,        //Create a windows media file  
  3.                                L"C:\\VidCap.wmv",               //File name  
  4.                                &pASFWriter,             //Receives a pointer to the filter  
  5.                                NULL);               //Receives an IFileSinkFilter interface pointer(optional)  

 

 

參數MEDIASUBTYPE_Asf 告訴graph builder,要使用wm asf writer作爲文件接收器,於是,pbuild 就創建這個filter,將其添加到graph圖中,然後調用IFileSinkFilter::SetFileName來設置輸出文件的名字。第三個參數用來返回一個ASF writer指針,第四個參數用來返回文件的指針。


在將任何pin連接到WM ASF Writer之前,一定要對WM ASF Writer進行一下設置,你可以同過WM ASF Writer的IConfigAsfWriter接口指針來進行設置。

Cpp代碼  收藏代碼
  1. IConfigAsfWriter *pConfig = 0;  
  2. hr = pASFWriter->QueryInterface(IID_IConfigAsfWriter, (void**)&pConfig);  
  3. if(SUCCEEDED(hr))  
  4. {  
  5.     //Configure the ASF Writer filter  
  6.     pConfig->Release();  
  7. }  

 

 

然後調用ICaptureGraphBuilder2::RenderStream將capture Filter 和 ASF writer連接起來:

Cpp代碼  收藏代碼
  1. hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE,         //Capture pin  
  2.                           &MEDIATYPE_Video,             //Video. Use MEDIATYPE_Audio for audio  
  3.                           pCap,         //Pointer to the capture filter  
  4.                           0,   
  5.                           pASFWriter);      //Pointer to the sink filter(ASF Filter)  

 

3保存成自定義的文件格式
如果你想將文件保存成自己的格式,你必須有自己的 file writer。看下面的代碼:

Cpp代碼  收藏代碼
  1. IBaseFilter *pMux = 0;  
  2. IFileSinkFilter *pSink = 0;  
  3. hr = pBuild->SetOutputFileName(&CLSID_MyCustomMuxFilter,     //開發自己的Filter  
  4.                                L"C:\\VidCap.avi", &pMux, &pSink);  

 

 

 

4如何將視頻流保存進多個文件
當你將視頻流保存進一個文件後,如果你想開始保存第二個文件,這時,你應該首先將graph停止,然後通過IFileSinkFilter::SetFileName改變 File Writer 的文件名稱。注意,IFileSinkFilter指針你可以在SetOutputFileName時通過第四個參數返回的。
看看保存多個文件的代碼:

Cpp代碼  收藏代碼
  1. IBaseFilter *pMux = 0;  
  2. IFileSinkFilter *pSink = 0;  
  3. hr = pBuild->SetOutputFileName(&MEDIASUBTYPE_Avi,   
  4.                                L"C:\\YourFileName.avi", &pMux, &pSink);  
  5. if(SUCCEEDED(hr))  
  6. {  
  7.     hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,  
  8.                                                 pCap, NULL, pMux);  
  9.     if(SUCCEEDED(hr))  
  10.     {  
  11.         pControl->Run();  
  12.         pControl->Stop();  
  13.         //Change the file name and run the graph again  
  14.         pSink->SetFileName(L"YourFileName02.avi", 0);  
  15.         pControl->Run();  
  16.     }  
  17.   
  18.     pMux->Release();  
  19.     pSink->Release();  
  20. }  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章