一個寫作機會,順便看了一下 DirectShow 發現它.. 太強大了... 但覺得還是自己用 PIN 連接較好用,雖有點不方便,但 DEBUG 容易。 CODE 很簡單。我用最簡單的幾個 Filter 寫了一個 AVI PLAYER.. 利用 DirectX 所提供的 GraphEdit 來做出自己要的 Filter Model 在依照其來建立連接。 PS: 弟沒有使用任何的 Avi Decoder 所以只能解基本的 AVI 格式及音樂。 1. pGraphBuilder->Render(OutPin); & RenderFile() 都會自動建立起一些基本的 Filter。 2. 善用 GraphEdit 中的 "Connect Remote Graph Filter" 功能,會得到很多答案的。 void Test(char *File) { WCHAR *wfile; int length; IGraphBuilder *pGraphBuilder; IEnumFilters *pEnum; IBaseFilter *pSource; IBaseFilter *pAviSplitter; IBaseFilter *pVideoRenderer; IBaseFilter *pSound; IMediaControl *pMediaControl; IMediaEvent *pMediaEvent; IVideoWindow *pVideoWindow; IMediaSeeking *pSeek; IMediaFilter *pMediaFilter; IEnumPins *EnumPins; IPin *OutPin; IPin *InPin; ULONG fetched; PIN_INFO pinfo; HRESULT hr; FILTER_INFO FilterInfo; char szName[256]; CoInitialize( NULL ); // create graph CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraphBuilder); length = strlen(File)+1; wfile = new WCHAR[length]; MultiByteToWideChar(CP_ACP, 0, File, -1, wfile, length); // find the SourceFilter from RenderFile created /*pGraphBuilder->EnumFilters(&pEnum); (编辑者:此句可能有误) while(pEnum->Next(1, &pSource, &fetched) == S_OK) { pSource->QueryFilterInfo(&FilterInfo); WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName, -1, szName, 256, 0, 0); FilterInfo.pGraph->Release(); if(strstr(szName, "avi") != NULL) break; pSource->Release(); } pEnum->Release(); // create filter CoCreateInstance(CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSource); CoCreateInstance(CLSID_AviSplitter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pAviSplitter); CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVideoRenderer); IFileSourceFilter* FileSource=NULL; pSource->QueryInterface(IID_IFileSourceFilter, (void**)&FileSource); FileSource->Load(wfile, NULL); FileSource->Release(); // Add filter to graph pGraphBuilder->AddFilter(pSource, L"MM_FileSource"); pGraphBuilder->AddFilter(pAviSplitter, L"MM_AviSplitter"); pGraphBuilder->AddFilter(pVideoRenderer, L"MM_VideoRenderer"); // find source output pSource->EnumPins(&EnumPins); EnumPins->Reset(); EnumPins->Next(1, &OutPin, &fetched); EnumPins->Release(); // set the GraphBuilder output pin //pGraphBuilder->Render(OutPin); // find the Avisplitter input pAviSplitter->EnumPins(&EnumPins); EnumPins->Reset(); EnumPins->Next(1, &InPin, &fetched); InPin->QueryPinInfo(&pinfo); pinfo.pFilter->Release(); while(pinfo.dir != PINDIR_INPUT) { InPin->Release(); EnumPins->Next(1, &InPin, &fetched); InPin->QueryPinInfo(&pinfo); pinfo.pFilter->Release(); } EnumPins->Release(); // connect input & output pin pGraphBuilder->Connect(OutPin, InPin); InPin->Release(); OutPin->Release(); // find the Avisplitter output pin pAviSplitter->EnumPins(&EnumPins); EnumPins->Reset(); EnumPins->Next(1, &OutPin, &fetched); OutPin->QueryPinInfo(&pinfo); pinfo.pFilter->Release(); while(pinfo.dir != PINDIR_OUTPUT) { OutPin->Release(); EnumPins->Next(1, &OutPin, &fetched); OutPin->QueryPinInfo(&pinfo); pinfo.pFilter->Release(); } EnumPins->Release(); // find the VideoRenderer input pin pVideoRenderer->EnumPins(&EnumPins); EnumPins->Reset(); EnumPins->Next(1, &InPin, &fetched); EnumPins->Release(); // connect pGraphBuilder->Connect(OutPin, InPin); InPin->Release(); OutPin->Release(); pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl); pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&pMediaEvent); pGraphBuilder->QueryInterface(IID_IVideoWindow, (void **)&pVideoWindow); RECT rc; HWND hwnd = m_hWnd; GetClientRect(hwnd, &rc); pVideoWindow->put_Owner((OAHWND)hwnd); pVideoWindow->put_WindowStyle(WS_CHILD); pVideoWindow->put_Left(0); pVideoWindow->put_Top(0); pVideoWindow->put_Width(rc.right - rc.left); pVideoWindow->put_Height(rc.bottom - rc.top); pVideoWindow->put_Visible(OATRUE); hr = AddGraphToRot(pGraphBuilder, &g_dwGraphRegister); if (FAILED(hr)) { g_dwGraphRegister = 0; } pMediaControl->Run(); long evCode; pMediaEvent->WaitForCompletion(INFINITE, &evCode); pMediaControl->Stop(); pVideoWindow->put_Visible(OAFALSE); pVideoWindow->put_Owner(NULL); pVideoWindow->Release(); pMediaEvent->Release(); pMediaControl->Release(); if (g_dwGraphRegister) RemoveGraphFromRot(g_dwGraphRegister); pSource->Release(); pAviSplitter->Release(); pVideoRenderer->Release(); pGraphBuilder->Release(); CoUninitialize(); } 就像前面說的,因為 RenderFile 會自動建立 Filter 因此更簡單的方法是都不建 Filter。 void Test(char *File) { WCHAR *wfile; int length; IGraphBuilder *pGraphBuilder; IEnumFilters *pEnum; IBaseFilter *pSource; IBaseFilter *pSound; IMediaControl *pMediaControl; IMediaEvent *pMediaEvent; IVideoWindow *pVideoWindow; IEnumPins *EnumPins; IPin *OutPin; IPin *InPin; ULONG fetched; PIN_INFO pinfo; HRESULT hr; FILTER_INFO FilterInfo; char szName[256]; CoInitialize( NULL ); // create graph CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraphBuilder); length = strlen(File)+1; wfile = new WCHAR[length]; MultiByteToWideChar(CP_ACP, 0, File, -1, wfile, length); // load file source and create some filter by itself // include the follow filter will auto created // Source, AviSplitter, VideoRenderer, SoundRenderer hr = pGraphBuilder->RenderFile(wfile, NULL); // find the SourceFilter from RenderFile created pGraphBuilder->EnumFilters(&pEnum); while(pEnum->Next(1, &pSource, &fetched) == S_OK) { pSource->QueryFilterInfo(&FilterInfo); WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName, -1, szName, 256, 0, 0); FilterInfo.pGraph->Release(); if(strstr(szName, "avi") != NULL) break; pSource->Release(); } pEnum->Release(); // find the SoundFilter pGraphBuilder->EnumFilters(&pEnum); while(pEnum->Next(1, &pSound, &fetched) == S_OK) { pSound->QueryFilterInfo(&FilterInfo); WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName, -1, szName, 256, 0, 0); FilterInfo.pGraph->Release(); if(strstr(szName, "Sound") != NULL) break; pSound->Release(); } pEnum->Release(); // find the sound input pin pSound->EnumPins(&EnumPins); EnumPins->Reset(); EnumPins->Next(1, &InPin, &fetched); EnumPins->Release(); // disconnect the sound renderer pin pGraphBuilder->Disconnect(InPin); InPin->Release(); pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl); pGraphBuilder->QueryInterface(IID_IMediaEvent, (void **)&pMediaEvent); pGraphBuilder->QueryInterface(IID_IVideoWindow, (void **)&pVideoWindow); pVideoWindow->put_Caption((BSTR)"123"); pMediaControl->Run(); long evCode; pMediaEvent->WaitForCompletion(INFINITE, &evCode); pVideoWindow->put_Visible(OAFALSE); pVideoWindow->put_Owner(NULL); pVideoWindow->Release(); pMediaEvent->Release(); pMediaControl->Release(); pGraphBuilder->Release(); CoUninitialize(); } |