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

为客户提供的视频播放的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的是另外一个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]='\0';
               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的上一个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;//---871E-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();

}
上一篇:linux的终端,网络虚拟终端,伪终端(转)


下一篇:Json 查看Json的插件