DirectShow基础编程 最简单transform filter 编写步骤

目标编写一个transform filter,功能是对图像进行翻转。

一、选择基类

从CBaseFilter派生出三个用于编写transform filter的类,分别是:CTransformFilter 、CTransInPlaceFilter 和CVideoTransformFilter ,三个基类的区别可以看MSDN的说明,我们选择CTransformFilter类。

选择好基类,我们就创建一个空的DLL工程,添加三个文件,分别是:FlipFilter.h、FlipFilter.cpp和FlipFilter.def。

二、声明Filter类

在FlipFilter.h中添加下列代码声明

[cpp] view plaincopyprint?

  1. #include <streams.h>
  2. extern "C" const GUID CLSID_FlipFilter;
  3. class CFlipFilter : public CTransformFilter
  4. {
  5. private:
  6. CFlipFilter(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr);
  7. public:
  8. static CUnknown * WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr);
  9. HRESULT CheckInputType(const CMediaType *mtIn);
  10. HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);
  11. HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut);
  12. HRESULT DecideBufferSize(IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop);
  13. HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut);
  14. };

三、媒体类型协商

这一步是Filter的pin在连接的时候必须进行的步骤,主要重载三个函数:

1、HRESULT CheckInputType(const CMediaType *mtIn);

[cpp] view plaincopyprint?

  1. HRESULT CFlipFilter::CheckInputType(const CMediaType *mtIn)
  2. {
  3. if (mtIn->majortype != MEDIATYPE_Video ||
  4. mtIn->subtype != MEDIASUBTYPE_RGB24 ||
  5. mtIn->formattype != FORMAT_VideoInfo )
  6. {
  7. return VFW_E_TYPE_NOT_ACCEPTED;
  8. }
  9. VIDEOINFO* pvi = (VIDEOINFO*)mtIn->Format();
  10. if (pvi->bmiHeader.biBitCount != 24)
  11. {
  12. return VFW_E_TYPE_NOT_ACCEPTED;
  13. }
  14. return S_OK;
  15. }

CTransformFilter使用CTransformInputPin类作为输入pin,CTransformInputPin::CheckMediaType(const CMediaType* pmt)中调用m_pTransformFilter->CheckInputType(pmt);因此我们可以简单的认为CheckInputType就是输入pin的CheckMediaType。这样设计的是为了不需要重新定义输入pin类,只需要定义Filter类,简化编写Transform filter的步骤,另外的几个接口也是这样的一个设计原理。

2、HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);

[cpp] view plaincopyprint?

  1. HRESULT CFlipFilter::GetMediaType(int iPosition, CMediaType *pMediaType)
  2. {
  3. if (m_pInput->IsConnected() == FALSE) {
  4. return E_UNEXPECTED;
  5. }
  6. if (iPosition < 0) {
  7. return E_INVALIDARG;
  8. }
  9. if (iPosition > 0) {
  10. return VFW_S_NO_MORE_ITEMS;
  11. }
  12. CheckPointer(pMediaType,E_POINTER);
  13. *pMediaType = m_pInput->CurrentMediaType();
  14. return NOERROR;
  15. }

同样的,这个函数也是为输入pin所写。

3、HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut);

[cpp] view plaincopyprint?

  1. HRESULT CFlipFilter::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
  2. {
  3. if (*mtIn == *mtOut)
  4. {
  5. return NOERROR;
  6. }
  7. return E_FAIL;
  8. }

这个函数是输出pin调用。CTransformOutputPin::CheckMediaType(const CMediaType* pmtOut)中调用m_pTransformFilter->CheckTransform。

四、协商分配器的属性,决定数据的属性

[cpp] view plaincopyprint?

  1. HRESULT CFlipFilter::DecideBufferSize(IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop)
  2. {
  3. if (m_pInput->IsConnected() == FALSE) {
  4. return E_UNEXPECTED;
  5. }
  6. CheckPointer(pAllocator,E_POINTER);
  7. CheckPointer(pprop,E_POINTER);
  8. HRESULT hr = NOERROR;
  9. pprop->cBuffers = 1;
  10. pprop->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();
  11. ASSERT(pprop->cbBuffer);
  12. ALLOCATOR_PROPERTIES Actual;
  13. hr = pAllocator->SetProperties(pprop,&Actual);
  14. if (FAILED(hr)) {
  15. return hr;
  16. }
  17. ASSERT( Actual.cBuffers == 1 );
  18. if (pprop->cBuffers > Actual.cBuffers ||
  19. pprop->cbBuffer > Actual.cbBuffer) {
  20. return E_FAIL;
  21. }
  22. return NOERROR;
  23. }

这个函数由CTransformOutputPin::DecideBufferSize调用。

五、实现数据转换

[cpp] view plaincopyprint?

  1. HRESULT CFlipFilter::Transform(IMediaSample *pIn, IMediaSample *pOut)
  2. {
  3. CheckPointer(pIn,E_POINTER);
  4. CheckPointer(pOut,E_POINTER);
  5. BYTE *pSourceBuffer, *pDestBuffer;
  6. long lSourceSize = pIn->GetActualDataLength();
  7. pIn->GetPointer(&pSourceBuffer);
  8. pOut->GetPointer(&pDestBuffer);
  9. //翻转图像
  10. CMediaType pMediaType1 = m_pInput->CurrentMediaType();
  11. VIDEOINFOHEADER* pvi = (VIDEOINFOHEADER*)pMediaType1.pbFormat;
  12. int nWidth = WIDTHBYTES(pvi->bmiHeader.biWidth * pvi->bmiHeader.biBitCount);
  13. for (int i = 0; i < pvi->bmiHeader.biHeight; i ++)
  14. {
  15. CopyMemory((PVOID) (pDestBuffer + nWidth * i),
  16. (PVOID) (pSourceBuffer + nWidth * (pvi->bmiHeader.biHeight - i - 1)),
  17. nWidth);
  18. }
  19. REFERENCE_TIME TimeStart, TimeEnd;
  20. if(NOERROR == pIn->GetTime(&TimeStart, &TimeEnd))
  21. {
  22. pOut->SetTime(&TimeStart, &TimeEnd);
  23. }
  24. LONGLONG MediaStart, MediaEnd;
  25. if(pIn->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR)
  26. {
  27. pOut->SetMediaTime(&MediaStart,&MediaEnd);
  28. }
  29. HRESULT hr = pIn->IsSyncPoint();
  30. if(hr == S_OK)
  31. {
  32. pOut->SetSyncPoint(TRUE);
  33. }
  34. else if(hr == S_FALSE)
  35. {
  36. pOut->SetSyncPoint(FALSE);
  37. }
  38. else
  39. {
  40. return E_UNEXPECTED;
  41. }
  42. hr = pIn->IsPreroll();
  43. if(hr == S_OK)
  44. {
  45. pOut->SetPreroll(TRUE);
  46. }
  47. else if(hr == S_FALSE)
  48. {
  49. pOut->SetPreroll(FALSE);
  50. }
  51. else
  52. {
  53. return E_UNEXPECTED;
  54. }
  55. hr = pIn->IsDiscontinuity();
  56. if(hr == S_OK)
  57. {
  58. pOut->SetDiscontinuity(TRUE);
  59. }
  60. else if(hr == S_FALSE)
  61. {
  62. pOut->SetDiscontinuity(FALSE);
  63. }
  64. else
  65. {
  66. return E_UNEXPECTED;
  67. }
  68. long lDataLength = pIn->GetActualDataLength();
  69. pOut->SetActualDataLength(lDataLength);
  70. return NOERROR;
  71. }

六、添加COM信息,使DLL成为filter

1、创建filter实例,这是标准格式

[cpp] view plaincopyprint?

  1. CUnknown* CFlipFilter::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
  2. {
  3. ASSERT(phr);
  4. CFlipFilter *pNewObject = new CFlipFilter(NAME("FlipFilter"), punk, phr);
  5. if (pNewObject == NULL) {
  6. if (phr)
  7. *phr = E_OUTOFMEMORY;
  8. }
  9. return pNewObject;
  10. }

2、声明工厂类模版

[cpp] view plaincopyprint?

  1. const AMOVIESETUP_MEDIATYPE sudInputPinTypes =
  2. {
  3. &MEDIATYPE_Video,
  4. &MEDIASUBTYPE_NULL
  5. };
  6. const AMOVIESETUP_MEDIATYPE sudOutputPinTypes =
  7. {
  8. &MEDIATYPE_Video,
  9. &MEDIASUBTYPE_NULL
  10. };
  11. const AMOVIESETUP_PIN sudpPins[] =
  12. {
  13. { L"Input",
  14. FALSE,
  15. FALSE,
  16. FALSE,
  17. FALSE,
  18. &CLSID_NULL,
  19. NULL,
  20. 1,
  21. &sudInputPinTypes
  22. },
  23. { L"Output",
  24. FALSE,
  25. TRUE,
  26. FALSE,
  27. FALSE,
  28. &CLSID_NULL,
  29. NULL,
  30. 1,
  31. &sudOutputPinTypes
  32. }
  33. };
  34. const AMOVIESETUP_FILTER sudFlipFilter =
  35. {
  36. &CLSID_FlipFilter,
  37. L"FlipFilter",
  38. MERIT_DO_NOT_USE,
  39. 2,
  40. sudpPins
  41. };
  42. CFactoryTemplate g_Templates[] = {
  43. { L"FlipFilter"
  44. , &CLSID_FlipFilter
  45. , CFlipFilter::CreateInstance
  46. , NULL
  47. , &sudFlipFilter }
  48. };
  49. int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
  50. REGFILTER2 rf2FilterReg = {
  51. 1,
  52. MERIT_DO_NOT_USE,
  53. 2,
  54. sudpPins
  55. };

3、注册和注销filter,DLL的全局入口

[cpp] view plaincopyprint?

  1. BOOL APIENTRY DllMain(HANDLE hModule,
  2. DWORD  dwReason,
  3. LPVOID lpReserved)
  4. {
  5. return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
  6. }
  7. STDAPI DllRegisterServer()
  8. {
  9. return AMovieDllRegisterServer2( TRUE );
  10. }
  11. STDAPI DllUnregisterServer()
  12. {
  13. return AMovieDllRegisterServer2( FALSE );
  14. }

Filter编写完成。

时间: 2024-11-08 07:27:40

DirectShow基础编程 最简单transform filter 编写步骤的相关文章

DirectShow基础编程 最简单的源Filter的编写步骤 (转)

转自: http://blog.csdn.net/bwmwm/article/details/5463852 1.创建一个空的Dll工程,添加5个空文件分别名为:MyOutputPin.h.MySourceFilter.h.MyOutputPin.cpp.MySourceFilter.cpp和MySourceFilter.def. 2.声明两个类,一个是Filter的实现类,一个是输出Pin的实现类,由于是最简单的源Filter,因此Filter只有一个输出Pin.实现的功能是从本地磁盘读取三个

DirectShow基础编程 源Filter CSource CSourceStream (转)

DirectShow是微软定义的一套接口集合,由不同的接口组成,例如:IBaseFilter,IPin.这些接口之间的关系形成了DirectShow的架构. DirectX SDK提供了一个C++的BaseClasses,是这些接口的实现.这些实现已经很成熟完善,因此我们不需要重新开发一套类库去实现DirctShow的接口,直接使用就可以. DirectShow编程就是Filter编程,根据功能实现不同的Filter.推模式的源Filter一般从CSource派生,在派生类中实现特殊的功能,而C

从简入难makefile文件编写,Linux C++编程,简单vi命令

 1.一个最基本的C++程序 2.第二个c++程序 3.第一个入门级别的简单的makefile 4.在makefile中定义变量. 5.编写makefile的依赖 如果start:标识后面的某个.o没有,则重新编译没有编译的那个文件 6.最终的makefile文件 总结:makefile是通过.o文件是否存在已经.cpp最后的修改时间来判断是否重新编译.o文件. 7.makefile不管理.h文件,它是编译器来进行管理的. vi: i在光标之前插入 a在光标后面插入 x删除后面的字符 dd删

简单的TSQL基础编程格式

这里简单整理一下数据库简单的编程,变量定义,赋值,分支语句和循环(这里以Sqlserver) 首先是变量定义,赋值,分支语句 --======TSQL数据库基础编程,定义变量,赋值,分支语句============ declare @a int;-----定义一个int类型变量,declare关键词,变量前要用@符号 declare @b int; select @a=5;--------给变量赋值,此处用的select赋值 set @b=2;-----------也可用set赋值 if @a>

MQ java 基础编程(一)

本文转自:http://www.blogjava.net/i369/articles/88035.html 编写人:邬文俊 编写时间 : 2006-2-16 联系邮件 : [email protected] 前言 通过 2 个多星期对 MQ 学习,在 partner 丁 & partner 武 的帮助下完成了该文档.该文档提供一个简单的例子,通过对该例子的讲解,你将知道: 1.         用 java 写客户端从 MQ Server 收发消息. 2.         MQ 作为 Websp

计算概论(A)/基础编程练习2(8题)/5:点和正方形的关系

1 #include<stdio.h> 2 #include<math.h> 3 int main() { 4 // 输入坐标 5 float x, y; 6 while(scanf("%f %f", &x, &y) != EOF) { 7 // 计算坐标点与原点的欧氏距离 8 float dist=sqrt(x*x+y*y); 9 10 /* 11 // 简单判断横坐标和纵坐标的截距abs(x).abs(y)和与原点距离dist 注意:abs(

【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单

一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就具体看看编译器到底在背后帮我们做了哪些复杂的工作的. 二.同步代码存在的问题 对于同步的代码,大家肯定都不陌生,因为我们平常写的代码大部分都是同步的,然而同步代码却存在一个很严重的问题,例如我们向一个Web服务器发出一个

关于shell脚本基础编程第四篇

shell脚本基础编程第四篇本章主要内容:函数 函数 function:             function 名称 { 命令 ; } 或 name () { 命令 ; }           定义 shell 函数.               创建一个以 NAME 为名的 shell 函数.当作为一个简单的命令启用时,           NAME 函数执行调用 shell 的上下文中的 COMMANDs 命令.当 NAME           被启用时,参数作为 $1...$n 被传递

JS基础(超级简单)

1     JS基础(超级简单) 1.1 数据类型 1.1.1   基本类型: 1)        Number:特别注意:NaN的检测方法:Nan!=NaN;或者使用isNaN方法 2)        string 3)        boolean 4)        null 5)        undefined 1.1.2   复杂类型 object:date,array,function 1.2 变量 var 变量名=值 变量的作用域:1.全局:以页面为单位.2局部:以函数为单位.