为客户提供的视频播放的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();

}

DirectX:在graph自动连线中加入自定义filter(graph中遍历filter)的更多相关文章

  1. java中配置自定义拦截器中exclude-mapping path是什么意思?

    <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/>//过滤全部请求 & ...

  2. ASP.NET Core中显示自定义错误页面-增强版

    之前的博文 ASP.NET Core中显示自定义错误页面 中的方法是在项目中硬编码实现的,当有多个项目时,就会造成不同项目之间的重复代码,不可取. 在这篇博文中改用middleware实现,并且放在独 ...

  3. DirectX:在graph自己主动连线中增加自己定义filter(graph中遍历filter)

    为客户提供的视频播放的filter的測试程序中,採用正向手动连接的方式(http://blog.csdn.net/mao0514/article/details/40535791).因为不同的视频压缩 ...

  4. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二)

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第七章:在Direct3D中绘制(二) 代码工程地址: https:/ ...

  5. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第六章:在Direct3D中绘制

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第六章:在Direct3D中绘制 代码工程地址: https://gi ...

  6. TensorFlow中的Session、Graph、operation、tensor

    TensorFlow中的Session.Graph.operation.tensor

  7. 【Azure Developer】使用Microsoft Graph API 如何批量创建用户,用户属性中需要包含自定义字段(如:Store_code,Store_name等)

    Microsoft Graph 是 Microsoft 365 中通往数据和智能的网关. 它提供统一的可编程模型,可用于访问 Microsoft 365.Windows 10 和企业移动性 + 安全性 ...

  8. SQL点滴9—SQL Server中的事务处理以及SSIS中的内建事务

    原文:SQL点滴9-SQL Server中的事务处理以及SSIS中的内建事务 我们可以把SSIS中的整个package包含在一个事务中,但是如果在package的执行过程中有一个表需要锁定应该怎么处理 ...

  9. HALCON中的算子大全(中英对照)

    HALCON中的算子大全(中英对照) Chapter 1 :Classification1.1 Gaussian-Mixture-Models1.add_sample_class_gmm功能:把一个训 ...

随机推荐

  1. MySQL笔记-union

    union语法 select ... union [all | distinct] selct ... union用于把来自多个select语句的结果组合在一个结果集中. 两次查询的列表必须相同,否则 ...

  2. Linux下查看CPU、内存和硬盘信息命令

    一.查看cpu信息 cat /proc/cpuinfo 相同physical id 的记录是属于同一个CPU的,对应于多核的信息. 二.查看内存的信息 cat /proc/meminfo 三.查看硬盘 ...

  3. POJ 1681 Painter's Problem [高斯消元XOR]

    同上题 需要判断无解 需要求最小按几次,正确做法是枚举自由元的所有取值来遍历变量的所有取值取合法的最小值,然而听说数据太弱自由元全0就可以就水过去吧.... #include <iostream ...

  4. vue2.0父子组件之间通信

    父组件是通过props属性给子组件通信的来看下代码: 父组件: <parent> <child :child-com="content"></chil ...

  5. Asp.Net Core MailKit 完美附件(中文名、长文件名)

    最近在使用MailKit组件发送邮件,看了一些博客其实还是蛮简单的,但是发送附件的时候却产生了不小的问题,附件的中文名字是乱码的,或者附件的名字过长就会无效,附件的名字在QQ邮箱中会变成类似 tcmi ...

  6. [实例]JAVA生成字母+随机数字并生成文件

    package com.ishow.control.code; import java.io.*; import java.text.SimpleDateFormat; import java.uti ...

  7. php+redis 学习 四 队列

    <?php /** * redis实战 * * 利用列表list实现简单队列 * * @example php cache.php */ header('content-type:text/ht ...

  8. NoSQLBooster for MongoDB的基本使用

    连接 File -> Quik Connect ( Ctrl + Shift + N ) 或 Connect -> From URI 填入 mongodb://username:passw ...

  9. centos 7 双网卡建网桥脚本实现

    #!/bin/bash interface1=`ls /sys/class/net|grep en|awk 'NR==1{print}'` interface2=`ls /sys/class/net| ...

  10. 在Linux/Centos下用wondershaper限速

    wondershaper是国外人开发的一款在Linux内核下基于TC工具的对整块网卡的限度工具,虽然有很久没有更新了,但是测试老版本在Centos6.3上依然可以使用. 首先下载wondershape ...