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

一、选择基类

从CBaseFilter派生出三个用于编写transform filter的类,各自是:CTransformFilter 、CTransInPlaceFilter 和CVideoTransformFilter ,三个基类的差别能够看MSDN的说明,我们选择CTransformFilter类。

选择好基类,我们就创建一个空的DLLproject,加入三个文件,各自是:FlipFilter.h、FlipFilter.cpp和FlipFilter.def。

二、声明Filter类

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

  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);

  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);

  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);

  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。

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

  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调用。

五、实现数据转换

  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实例。这是标准格式

  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、声明工厂类模版

  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的全局入口

  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编写完毕。

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

  1. 简单的TSQL基础编程格式,存储过程,视图

    这里简单整理一下数据库简单的编程,变量定义,赋值,分支语句和循环(这里以Sqlserver),以及存储过程格式 首先是变量定义,赋值,分支语句 --======TSQL数据库基础编程,定义变量,赋值, ...

  2. Hadoop 综合揭秘——MapReduce 基础编程(介绍 Combine、Partitioner、WritableComparable、WritableComparator 使用方式)

    前言 本文主要介绍 MapReduce 的原理及开发,讲解如何利用 Combine.Partitioner.WritableComparator等组件对数据进行排序筛选聚合分组的功能.由于文章是针对开 ...

  3. MQ java 基础编程

    MQ java 基础编程 编写人:邬文俊 编写时间 : 2006-2-16 联系邮件 : wenjunwu430@gmail.com 前言 通过 2 个多星期对 MQ 学习,在 partner 丁 & ...

  4. 【Linux基础总结】Shell 基础编程

    Shell 基础编程 重启虚拟机遇到磁盘损坏如何解决 Shell编程中变量的声明.引用及作用域 Shell程序 概述 以文件形式存放批量的Linux命令集合,该文件能够被Shell解释执行,这种文件就 ...

  5. ARM Cortex-M嵌入式C基础编程(下)

    ARM Cortex-M嵌入式C基础编程(下) ARM Cortex-M Embedded C Fundamentals/Tutorial -Aviral Mittal Load Region Vs ...

  6. ARM Cortex-M嵌入式C基础编程(上)

    ARM Cortex-M嵌入式C基础编程(上) ARM Cortex-M Embedded C Fundamentals/Tutorial -Aviral Mittal 此技术是关于从编写简单的嵌入式 ...

  7. 异步编程系列第04章 编写Async方法

    p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提 ...

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

    一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两 ...

  9. JS基础(超级简单)

    1     JS基础(超级简单) 1.1 数据类型 1.1.1   基本类型: 1)        Number:特别注意:NaN的检测方法:Nan!=NaN;或者使用isNaN方法 2)       ...

随机推荐

  1. JAVA进阶----ThreadPoolExecutor机制(转)

    ThreadPoolExecutor机制 一.概述 1.ThreadPoolExecutor作为java.util.concurrent包对外提供基础实现,以内部线程池的形式对外提供管理任务执行,线程 ...

  2. Thrift搭建分布式微服务1

    Thrift搭建分布式微服务 一.Thrift是什么? 关于Thrift的基本介绍,参看张善友的文章Thrift简介. 二.为什么使用微服务? 在公司的高速发展过程中,随着业务的增长,子系统越来越多. ...

  3. uva 10003 Cutting Sticks(区间DP)

    题目连接:10003 - Cutting Sticks 题目大意:给出一个长l的木棍, 再给出n个要求切割的点,每次切割的代价是当前木棍的长度, 现在要求输出最小代价. 解题思路:区间DP, 每次查找 ...

  4. Hadoop Hive与Hbase关系 整合

    用hbase做数据库,但因为hbase没有类sql查询方式,所以操作和计算数据很不方便,于是整合hive,让hive支撑在hbase数据库层面 的 hql查询.hive也即 做数据仓库 1. 基于Ha ...

  5. 已知直线上的两点 A(x1, y1), B(x2, y2) 和另外一点 C(x0, y0),求C点到直线的距离。

    数学知识太差,一点点积累,高手勿喷. 1. 先求出AB向量 a = ( x2-x1, y2-y1 ) 2. 求AB向量的单位方向向量 b = √((x2-x1)^2 + (y2-y1)^2)) a1 ...

  6. 《Node.js In Action》笔记之流程控制

    转向Javascript后,开始学习了node.js,选择的第一本书是<Node.js in Action> 将近一个月时间,断断续续看完,选几个点做下笔记 1.实现串行化流程控制 var ...

  7. SWT入门-常用组件的使用(转)

    转自:http://www.cnblogs.com/kentyshang/archive/2007/08/16/858367.html swt的常用组件button ,text ,combo,list ...

  8. php截取等长UFT8中英文混合字串

    由于需要,想实现“php截取等长UFT8中英文混合字串”,可是网上找了很多代码不是有乱码就是不能实现等长(以一个中文长度为单位,两个英文字母算一个长度,如‘等长’长度为2,‘UTF8’长度也是2). ...

  9. cocos2d-x-3.0新建工程以及移植其他平台

    本文来自:http://www.zaojiahua.com/cocos2d-x-3-0.html 有将近俩个礼拜没有研究cocos2dx了,博主最近刷了些ACM的水题,越做感觉越没意思,这哪是考编程啊 ...

  10. Exec l 中分列的作用