1)directshow初識(2009.12.05)
建立DirectShow應用程式步驟:
第一步,首先,需要調用CoInitialize來作初始化,然後調用CoCreateInstance建立Filter Graph Manager:
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
return;
}
IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
類別識別項(CLSID)是CLSID_FilterGraph。Filter Graph Manager由進程內DLL(in-process DLL)提供,因此參數3,dwClsContext的值為CLSCTX_INPROC_SERVER。由於DirectShow運行自由線程模式(free-threading model),所以你同樣可以使用COINIT_MULTITHREADED參數來調用CoInitializeEx
PS:HRESULT 是一種簡單的資料類型,通常被屬性和 ATL 用作傳回值。
下表說明各種不同的值。標頭檔 winerror.h 中包含更多的值。
名稱 說明 值
S_OK 操作成功 0x00000000
E_UNEXPECTED 意外的失敗 0x8000FFFF
E_NOTIMPL 未實現 0x80004001
E_OUTOFMEMORY 未能分配所需的記憶體 0x8007000E
E_INVALIDARG 一個或多個參數無效 0x80070057
E_NOINTERFACE 不支援此介面 0x80004002
E_POINTER 無效指標 0x80004003
E_HANDLE 無效控制代碼 0x80070006
E_ABORT 操作已中止 0x80004004
E_FAIL 未指定的失敗 0x80004005
E_ACCESSDENIED 一般的訪問被拒絕錯誤 0x80070005
不能簡單地把傳回值與 S_OK 和 S_FALSE 比較,而要用 SUCCEEDED 和 FAILED 宏進行判斷。
第二步,建立filter graph
調用CoCreateInstance得到的IGraphBuilder介面包含了大部分建立filter graph的方法。在這個例子中還需要另外兩個介面:IMediaControl和IMediaEvent。IMediaControl控制資料流,它包含開啟和停止graph的方法;IMediaEvent包含從Filter Graph Manager擷取事件的方法,在這個例子中,這個介面用來得到回放結束事件。所有這些介面由Filter Graph Manager提供,使用得到的IGraphBuiler介面指標來查詢得到。
IMediaControl *pControl;
IMediaEvent *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
第三步,建立filter graph
對於檔案回放只需要一個簡單的調用:
hr = pGraph->RenderFile(L"C://Example.avi", NULL);
IGraphBuilder::RenderFile方法建立了一個能夠播放指定檔案的filter graph,事實上,原本需要做的一些如建立filter執行個體及將這些filter串連起來的工作,都由這個方法自動完成了,如果是視頻檔案,這個filter graph看起來應該是這個樣子:
->[如果是縮格式,這裡是個解碼器]->[Video Renderer]
要開始回放,調用IMediaControl::Run方法:
hr = pControl->Run();
當filter graph運行時,資料經過各個filter最後回放為視頻或音頻。回放發生在一個單獨的線程中。你可以通過調用IMediaEvent::WaitForCompletion方法來等待回放的結束:
long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);
上面這個方法在播放期間被阻塞,直至播放結束或逾時。
當應用程式結束時,需要釋放介面指標並關閉COM庫:
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
建立簡單的directshow播放程式過程的完整代碼如下所示:
#include <dshow.h>
void main(void)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return;
}
// Create the filter graph manager and query for interfaces.
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);
// Build the graph. IMPORTANT: Change this string to a file on your system.
hr = pGraph->RenderFile(L"C://Example.avi", NULL);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
}
PS:
1.這裡所使用的fiter graph manag構建graph filter採用igraphbuilder::renderfile方法構建一個完成的檔案回放graph
2.該程式只支援.avi格式視頻播放,只有播放直至結束的回放功能。
二 VS2005 C++ 項目添加“依賴”、“庫目錄”和“包含目錄”2009-12-08
1. 添加編譯所需要(依賴)的 lib 檔案
“項目->屬性->配置屬性->連接器->輸入->附加依賴項”裡填寫“winsock.lib”,多個 lib 以空格隔開。
(等同於“#pragma comment(lib, "winsock.lib") ”語句)
2. 添加庫(Libs)檔案目錄
方法 1“項目->屬性->配置屬性->連接器->常規->附加庫目錄”
方法 2:[菜單]“工具->選項->項目和解決方案->C++ 目錄”,選擇對應平台,然後添加所需“庫檔案”目錄
3. 添加包含(include)檔案目錄
方法 1:[方案總管]“項目->屬性->配置屬性->C/C++->常規->附加元件封裝含目錄”
方法 2:[菜單]“工具->選項->項目和解決方案->C++ 目錄”,選擇對應平台,然後添加所需“包括檔案”目錄