目标编写一个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发展的时间表

    Java发展的时间表. (版本号 名称 中文名 发布日期) JDK 1.1.4 Sparkler 宝石 1997-09-12 JDK 1.1.5 Pumpkin 南瓜 1997-12-13 JDK 1 ...

  2. MySQL JDBC事务处理、封装JDBC工具类

    MySQL数据库学习笔记(十)----JDBC事务处理.封装JDBC工具类 一.JDBC事务处理: 我们已经知道,事务的概念即:所有的操作要么同时成功,要么同时失败.在MySQL中提供了Commit. ...

  3. 日志收集之kafka

    日志收集之kafka http://www.jianshu.com/p/f78b773ddde5 一.介绍 Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 以时间复杂度为O(1 ...

  4. sql server数据库保存图片或者其他小文件

    原文:sql server数据库保存图片或者其他小文件 测试用sql server数据库保存图片或者其他小文件. 文件流字段用varbinary类型. static void Main() { App ...

  5. HDU1300DP

    /* HDU1300 DP 特定n饰品种类 每个饰品的两个数据.amount[i]代表数量.price[i]代表单位价格 购买珠宝时要满足下面购买规则: 单独买:每种珠宝要加上数量10 合并买:能够把 ...

  6. Unity3D ITween!

    percentage +=0.001f; iTween.PutOnPath(gameObject,path,percentage); //You can cause the object to ori ...

  7. hdu2102(bfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2102 分析:bfs求最短时间到达'P'点,不过本题有好几个trick,我都踩到了,自己还是太嫩了... ...

  8. MFC中模态对话框和非模态对话框的差别

    在MFC中有模态对话框和非模态对话框,那这两种有什么差别呢. 又都是用于什么场合呢. 首先,要弄清楚2种对话框是怎样创建的. 然后要弄清楚2种对话框有什么差别,可能从表面上看,模态会堵塞主对话框.可原 ...

  9. Unobtrusive Ajax

    ASP.NET MVC之Unobtrusive Ajax(五)   前言 这一节我们来讲讲Unobtrusive中的Ajax提交,大部分情况下我们是利用JQuery来进行Ajax请求,当然利用JQue ...

  10. 第一个Python程序的Hello Python,竟然有问题

    print 'hello python' 运行时显示:SyntaxError: invalid syntax 解决办法: 这应该是版本的问题,Python2的话直接就可以输出,但是到了Python3需 ...