如何使用DirectShow播放一個文件。

  本文的目的是給出DirectShow編程的樣式。這是一個簡單的控制檯應用程序,用來播放一個音頻或視頻文件。程序只有幾行,但是它示範了DirectShow編程的某些能力。
  如<DirectShow應用程序編程介紹>所寫,一個DirectShow應用程序運行的基本步驟爲:
1、創建一個篩選器表管理器的實例
2、使用篩選器表管理器生成一個篩選器表
3、運行表,使數據在篩選器中流動。
 
  調用CoIntitialize來初始化COM庫

HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
    // 在這裏添加錯誤處理代碼(Omitted for clarity.)
}

  爲了簡單化,此例子忽略了返回值,但是您最好在方法調用中檢查HRESULT的值。
 
  下面,調用CoCreateInstance來創建篩選器表管理器:

IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
    CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

   如上所示,類標識(CLSID)爲CLSID_FilterGraph。篩選器表管理器由一個進程內的DLL提供,所以執行上下文是 CLSCTX_INPROC_SERVER。DirectShow支持自由自由線程處理模式,因此您也可以使用COINIT_MULTITHREADED 標誌調用CoInitializeEx。
  對CoCreateInstance的調用返回IGraphBuilder接口,它主要包含了生成篩選器表的方法。此例中用到的另兩個接口爲:
  • IMediaControl,作用是控制流。它包含了停止和啓動表的方法
  • IMediaEvent,它包含的方法是從篩選器表管理器中得到事件。在此例中,此接口用來等待播放的結束。

  這兩個接口都是出現在篩選器表管理器中。可以使用返回的IGraphBuilder指針來查詢。

IMediaControl *pControl;
IMediaEvent   *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

  現在您可以生成篩選器表了。要播放文件,可以調用下列方法:
 
hr = pGraph->RenderFile(L"C://Example.avi", NULL);
  IGraphBuilder::RenderFile方法生成一個篩選器表,用以播放指定的文件。第一個參數是文件名稱,用一個寬字符(2字節)字符串表示。第二個參數是保留參數,必須爲NULL。

  如果指定的文件不存在,或文件格式無法,此方法將失敗。如果方法調用成功,篩選器還原器就做好播放的準備了。要運行表,調用IMediaControl::Run方法。

hr = pControl->Run();

  當篩選器運行時,數據從篩選器中移出,並以視頻和音頻的方式還原出來。播放會啓動另一個線程。您可以調用IMediaEvent::WaitForCompletion方法。

long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);


  當應用程序結束時,將釋放接口指針並關閉COM庫。

pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
 
代碼範例

  這裏列出了本文介紹的例子的完整代碼:
#include <dshow.h>
void main(void)
{
    IGraphBuilder *pGraph = NULL;
    IMediaControl *pControl = NULL;
    IMediaEvent   *pEvent = NULL;
    // 初始化COM庫
    HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
        printf("ERROR - Could not initialize COM library");
        return;
    }
    // 創建篩選器表管理器,並查詢接口
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
                        IID_IGraphBuilder, (void **)&pGraph);
    if (FAILED(hr))
    {
        printf("ERROR - Could not create the Filter Graph Manager.");
        return;
    }
    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
    // 創建表。重點:將字符串改爲您系統上的文件名稱
    hr = pGraph->RenderFile(L"C://Example.avi", NULL);
    if (SUCCEEDED(hr))
    {
        // 運行表
        hr = pControl->Run();
        if (SUCCEEDED(hr))
        {
            // 等待結束
            long evCode;
            pEvent->WaitForCompletion(INFINITE, &evCode);
            // 注意:在實際應用程序中不要使用INFINITE
            // 因爲它對應用程序的阻塞很不確定
        }
    }
    pControl->Release();
    pEvent->Release();
    pGraph->Release();
    CoUninitialize();
}
 
  此方法將阻塞,直到文件播放完畢,或超出了指定的時間。INFINITE值是指應用程序將阻塞到文件播放完。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章