程序员人生 网站导航

DirectX:在graph自动连线中加入自定义filter(graph中遍历filter)

栏目:互联网时间:2014-11-05 08:14:44

     为客户提供的视频播放的filter的测试程序中,采取正向手动连接的方式(http://blog.csdn.net/mao0514/article/details/40535791),由于不同的视频紧缩格式,致使这类方式的缺点是不能及时的播放任意的视频文件。现在,采取在自动连线的graph中添加自己的filter:

进程以下:

1. 构建自动连线graph;

2. 在graph中查找render filter;

3.在renderf ilter上查找输入m_r_in_pin的上位连接m_n_out_pin

4. 断开render pin和上位连接pin

5.加入自定义filter,获得输入输出m_my_in_pin,m_my_out_pin

6.连接pin:m_n_out_pin-->m_my_in_pin,m_my_out_pin->m_r_in_pin

7.run

待完善:目前的程序在找到Render filtre后,没有判断输入的类型,目前仅支持RGB32的输入,如果是yuv的是另外1个filter

IGraphBuilder *pigb = NULL; IMediaControl *pimc = NULL; IMediaEventEx *pimex = NULL; IVideoWindow *pivw = NULL; IMediaSeeking *pims = NULL; ICaptureGraphBuilder2 * g_pCaptureBuilder = NULL; //graph中枚举所有的filter HRESULT FindFilterInterface( IGraphBuilder *pGraph, // Pointer to the Filter Graph Manager. REFGUID iid, // IID of the interface to retrieve. void **ppUnk) // Receives the interface pointer. { if (!pGraph || !ppUnk) return E_POINTER; HRESULT hr = E_FAIL; IEnumFilters *pEnum = NULL; IBaseFilter *pF = NULL; if (FAILED(pGraph->EnumFilters(&pEnum))) { return E_FAIL; } // Query every filter for the interface. while (S_OK == pEnum->Next(1, &pF, 0)) { hr = pF->QueryInterface(iid, ppUnk); pF->Release(); if (SUCCEEDED(hr)) { FILTER_INFO *fin=new FILTER_INFO(); hr = pF->QueryFilterInfo(fin); ////////wchar --->char char *m_char; int len= WideCharToMultiByte(CP_ACP,0,fin->achName,wcslen(fin->achName),NULL,0,NULL,NULL); m_char=new char[len+1]; WideCharToMultiByte(CP_ACP,0,fin->achName,wcslen(fin->achName),m_char,len,NULL,NULL); m_char[len]=''; MessageBox(NULL,m_char,"",NULL);//显示当前查到的filter的名称 if (strstr(m_char,"Render")!=NULL) {//枚举graph中的filter,查找到Render filter break; } //////// } } pEnum->Release(); return hr; } void CTestDlg::OnButton1() { HRESULT hr; //构建graph CoInitialize(NULL); hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pigb); hr = CoCreateInstance (CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **) &g_pCaptureBuilder); pigb->QueryInterface(IID_IMediaControl, (void **)&pimc); pigb->QueryInterface(IID_IMediaEventEx, (void **)&pimex); pigb->QueryInterface(IID_IMediaSeeking, (void **)&pims); pigb->QueryInterface(IID_IVideoWindow, (void **)&pivw); hr = g_pCaptureBuilder->SetFiltergraph(pigb); //构建graph //打开视频文件jpg,bmp,avi,mpg....../////////////////////////// CString strFilename;// CFileDialog openBox(TRUE,NULL,"",OFN_HIDEREADONLY,"bmp(*.bmp)|*.bmp|jpg(*.jpg)|*.jpg|avi(*.avi)|*.avi|mpg(*.mpg)|*.mpg|ALLFiles(*.*)|*.*||",NULL); openBox.m_ofn.lpstrTitle="打开数据文件"; INT_PTR nResult = openBox.DoModal(); // 如果文件打开则准备播放 if (nResult == IDOK) { strFilename=openBox.GetPathName(); } else { return; } strFilename.ReleaseBuffer(); //cstring 转 LPCSTR USES_CONVERSION; LPWSTR pwStr=new wchar_t[strFilename.GetLength()+1]; wcscpy(pwStr,T2W((LPCTSTR)strFilename)); ////////////////////////////////////////////////////////////////////// hr = pigb->RenderFile(pwStr, NULL);// #if 1 //////找到Render filter 并获得Render filter的输入pin IBaseFilter *pRenderFilter; hr = FindFilterInterface(pigb,IID_IBaseFilter,(void **)&pRenderFilter); hr = pigb->AddFilter(pRenderFilter,L"ffdshow Video Render "); IPin *pIn_Render = 0; hr = g_pCaptureBuilder->FindPin(pRenderFilter,PINDIR_INPUT,NULL,NULL,FALSE,0,&pIn_Render); if(FAILED(hr)) { MessageBox("err10"); } #endif #if 1 //////查询Render的上1个filter IEnumFilters *pEnum = NULL; IPin *pPinNext = 0; hr = pigb->EnumFilters(&pEnum); //IBaseFilter *pF; // Pointer to some filter. IBaseFilter *pUpstream = NULL; PIN_DIRECTION ThisPinDir; hr = pIn_Render->QueryDirection(&ThisPinDir); if (SUCCEEDED(hr)) { if (ThisPinDir==PINDIR_INPUT) { hr = pIn_Render->ConnectedTo(&pPinNext); if (SUCCEEDED(hr)) { // Get the filter that owns that pin. PIN_INFO PinInfo; hr = pPinNext->QueryPinInfo(&PinInfo); pPinNext->Release(); if (FAILED(hr) || (PinInfo.pFilter == NULL)) { MessageBox("err GetNextFilter3"); } pUpstream = PinInfo.pFilter; // Client must release. } else { MessageBox("err GetNextFilter4"); } } else { MessageBox("err GetNextFilter1"); } } else { MessageBox("err GetNextFilter2"); } #endif #if 1 ///// 添加自定义殊效filter /////////////////////////////////////////////// IBaseFilter *peffect;//--⑻71E-AB91661A4EF7 const GUID CLSID_EFFECT={0x8b498501, 0x1218, 0x11cf,{ 0xad, 0xc4, 0x0, 0xa0, 0xd1, 0x0, 0x4, 0x1b}}; hr = CoCreateInstance(CLSID_EFFECT,NULL,CLSCTX_ALL,IID_IBaseFilter,(void **)&peffect); hr = pigb->AddFilter(peffect,L"Image effect "); IPin *pIn_peffect = 0; IPin *pOut_peffect = 0; hr = g_pCaptureBuilder->FindPin(peffect,PINDIR_INPUT,NULL,NULL,FALSE,0,&pIn_peffect); if(FAILED(hr)) { MessageBox("err11"); } hr = g_pCaptureBuilder->FindPin(peffect,PINDIR_OUTPUT,NULL,NULL,FALSE,0,&pOut_peffect); if(FAILED(hr)) { MessageBox("err12"); } peffect->Release(); #endif //断开以获得自动连接 pPinNext->Disconnect(); pIn_Render->Disconnect(); #if 1 //重新连接 hr = pigb->Connect(pPinNext, pIn_peffect); if(FAILED(hr)) { MessageBox("err19"); } hr = pigb->Connect(pOut_peffect, pIn_Render); if(FAILED(hr)) { MessageBox("err20"); } #endif //设置显示区域 HWND m_hwndScreen = m_Screen.GetSafeHwnd(); RECT rc; hr = pivw->put_Owner((OAHWND)m_hwndScreen); hr = pivw->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN); m_Screen.GetClientRect(&rc); hr = pivw->SetWindowPosition(0, 0, (rc.right), (rc.bottom)); //播放 hr = pimc->Run(); }


------分隔线----------------------------
------分隔线----------------------------

最新技术推荐