目标编写一个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. 我经历的IT公司面试及离职感受(转)

    毕业后几年一直待在广州,觉得这是一个比较生活化及务实的城市,其互联网公司和相应的投融资环境都不如北深上活跃,大大小小的面试也有几十个,有点规模的公司应该都面试过了,面试一般会见到主力技术人员,技术主管 ...

  2. syslog-ng 3.4.3 发布,强烈建议升级 - 开源中国社区

    syslog-ng 3.4.3 发布,强烈建议升级 - 开源中国社区 syslog-ng 3.4.3 发布,强烈建议升级    oschina 发布于: 2013年08月16日 (2评)    分享到 ...

  3. android--手机桌面添加网址链接图标(解决方式)

    这样的做法最普遍最简单: 1.新建一个android空项目: 2.在drawable文件夹下加入图标文件,如icon.png:在values文件夹下的strings.xml文件里添加名称.如websi ...

  4. linux内核笔记-内核同步

    linux内核就相当于不断对请求进行响应的服务器,这些请求可能来自CPU,可能来自发出中断的外部设备.我们将内核看作两种请求的侍者. (1)老板提出请求,侍者如果空闲,为老板服务.(系统调用或异常) ...

  5. hdu1160(最长上升子序列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1160 题意:给定一些小猫的属性:体重和速度.然后求某些猫顺序的排列,使得体重上升,速度下降,这样的排列 ...

  6. hyper-v 报错 0x80070569

    在Windows8.1Pro版使用过程中,突然出现HYPER-V无法创建虚拟机.显示错误为: 登录失败:未授予用户在此计算机上的请求登录类型.(0x80070569). 回顾起近期通过组策略增强了系统 ...

  7. 如何做程序猿SOHO它定购家庭赚外快?

    做为一名程序猿.我想大多数人除了平时削尖了脑袋研究各种各样的技术之外. ArticleId=28404183" width="1" height="1" ...

  8. 谈Web应用系统的可维护性

           每一个软件开发人员都十分清楚, 当软件构建得越来越复杂时, 可维护性就成了一个很突出的问题. 如何在构造软件系统的过程中始终保持可控制的可维护性呢?          一. 整体组织   ...

  9. 编程算法 - 字典分词 代码(C)

    字典分词 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 给定字典, 给定一句话, 进行分词. 使用深度遍历(DFS)的方法. 使用一个參数string ...

  10. Knockout应用开发指南 第七章:Mapping插件

    原文:Knockout应用开发指南 第七章:Mapping插件 Mapping插件 Knockout设计成允许你使用任何JavaScript对象作为view model.必须view model的一些 ...