DirectShow基础编程 最简单transform filter 编写步骤
目标编写一个transform filter,功能是对图像进行翻转。
一、选择基类
从CBaseFilter派生出三个用于编写transform filter的类,各自是:CTransformFilter 、CTransInPlaceFilter 和CVideoTransformFilter ,三个基类的差别能够看MSDN的说明,我们选择CTransformFilter类。
选择好基类,我们就创建一个空的DLLproject,加入三个文件,各自是:FlipFilter.h、FlipFilter.cpp和FlipFilter.def。
二、声明Filter类
在FlipFilter.h中加入下列代码声明
- #include <streams.h>
- extern "C" const GUID CLSID_FlipFilter;
- class CFlipFilter : public CTransformFilter
- {
- private:
- CFlipFilter(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr);
- public:
- static CUnknown * WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr);
- HRESULT CheckInputType(const CMediaType *mtIn);
- HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);
- HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut);
- HRESULT DecideBufferSize(IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop);
- HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut);
- };
三、媒体类型协商
这一步是Filter的pin在连接的时候必须进行的步骤。主要重载三个函数:
1、HRESULT CheckInputType(const CMediaType *mtIn);
- HRESULT CFlipFilter::CheckInputType(const CMediaType *mtIn)
- {
- if (mtIn->majortype != MEDIATYPE_Video ||
- mtIn->subtype != MEDIASUBTYPE_RGB24 ||
- mtIn->formattype != FORMAT_VideoInfo )
- {
- return VFW_E_TYPE_NOT_ACCEPTED;
- }
- VIDEOINFO* pvi = (VIDEOINFO*)mtIn->Format();
- if (pvi->bmiHeader.biBitCount != 24)
- {
- return VFW_E_TYPE_NOT_ACCEPTED;
- }
- return S_OK;
- }
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);
- HRESULT CFlipFilter::GetMediaType(int iPosition, CMediaType *pMediaType)
- {
- if (m_pInput->IsConnected() == FALSE) {
- return E_UNEXPECTED;
- }
- if (iPosition < 0) {
- return E_INVALIDARG;
- }
- if (iPosition > 0) {
- return VFW_S_NO_MORE_ITEMS;
- }
- CheckPointer(pMediaType,E_POINTER);
- *pMediaType = m_pInput->CurrentMediaType();
- return NOERROR;
- }
相同的,这个函数也是为输入pin所写。
3、HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut);
- HRESULT CFlipFilter::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
- {
- if (*mtIn == *mtOut)
- {
- return NOERROR;
- }
- return E_FAIL;
- }
这个函数是输出pin调用。CTransformOutputPin::CheckMediaType(const CMediaType* pmtOut)中调用m_pTransformFilter->CheckTransform。
四、协商分配器的属性。决定数据的属性
- HRESULT CFlipFilter::DecideBufferSize(IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop)
- {
- if (m_pInput->IsConnected() == FALSE) {
- return E_UNEXPECTED;
- }
- CheckPointer(pAllocator,E_POINTER);
- CheckPointer(pprop,E_POINTER);
- HRESULT hr = NOERROR;
- pprop->cBuffers = 1;
- pprop->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();
- ASSERT(pprop->cbBuffer);
- ALLOCATOR_PROPERTIES Actual;
- hr = pAllocator->SetProperties(pprop,&Actual);
- if (FAILED(hr)) {
- return hr;
- }
- ASSERT( Actual.cBuffers == 1 );
- if (pprop->cBuffers > Actual.cBuffers ||
- pprop->cbBuffer > Actual.cbBuffer) {
- return E_FAIL;
- }
- return NOERROR;
- }
这个函数由CTransformOutputPin::DecideBufferSize调用。
五、实现数据转换
- HRESULT CFlipFilter::Transform(IMediaSample *pIn, IMediaSample *pOut)
- {
- CheckPointer(pIn,E_POINTER);
- CheckPointer(pOut,E_POINTER);
- BYTE *pSourceBuffer, *pDestBuffer;
- long lSourceSize = pIn->GetActualDataLength();
- pIn->GetPointer(&pSourceBuffer);
- pOut->GetPointer(&pDestBuffer);
- //翻转图像
- CMediaType pMediaType1 = m_pInput->CurrentMediaType();
- VIDEOINFOHEADER* pvi = (VIDEOINFOHEADER*)pMediaType1.pbFormat;
- int nWidth = WIDTHBYTES(pvi->bmiHeader.biWidth * pvi->bmiHeader.biBitCount);
- for (int i = 0; i < pvi->bmiHeader.biHeight; i ++)
- {
- CopyMemory((PVOID) (pDestBuffer + nWidth * i),
- (PVOID) (pSourceBuffer + nWidth * (pvi->bmiHeader.biHeight - i - 1)),
- nWidth);
- }
- REFERENCE_TIME TimeStart, TimeEnd;
- if(NOERROR == pIn->GetTime(&TimeStart, &TimeEnd))
- {
- pOut->SetTime(&TimeStart, &TimeEnd);
- }
- LONGLONG MediaStart, MediaEnd;
- if(pIn->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR)
- {
- pOut->SetMediaTime(&MediaStart,&MediaEnd);
- }
- HRESULT hr = pIn->IsSyncPoint();
- if(hr == S_OK)
- {
- pOut->SetSyncPoint(TRUE);
- }
- else if(hr == S_FALSE)
- {
- pOut->SetSyncPoint(FALSE);
- }
- else
- {
- return E_UNEXPECTED;
- }
- hr = pIn->IsPreroll();
- if(hr == S_OK)
- {
- pOut->SetPreroll(TRUE);
- }
- else if(hr == S_FALSE)
- {
- pOut->SetPreroll(FALSE);
- }
- else
- {
- return E_UNEXPECTED;
- }
- hr = pIn->IsDiscontinuity();
- if(hr == S_OK)
- {
- pOut->SetDiscontinuity(TRUE);
- }
- else if(hr == S_FALSE)
- {
- pOut->SetDiscontinuity(FALSE);
- }
- else
- {
- return E_UNEXPECTED;
- }
- long lDataLength = pIn->GetActualDataLength();
- pOut->SetActualDataLength(lDataLength);
- return NOERROR;
- }
六、加入COM信息,使DLL成为filter
1、创建filter实例。这是标准格式
- CUnknown* CFlipFilter::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
- {
- ASSERT(phr);
- CFlipFilter *pNewObject = new CFlipFilter(NAME("FlipFilter"), punk, phr);
- if (pNewObject == NULL) {
- if (phr)
- *phr = E_OUTOFMEMORY;
- }
- return pNewObject;
- }
2、声明工厂类模版
- const AMOVIESETUP_MEDIATYPE sudInputPinTypes =
- {
- &MEDIATYPE_Video,
- &MEDIASUBTYPE_NULL
- };
- const AMOVIESETUP_MEDIATYPE sudOutputPinTypes =
- {
- &MEDIATYPE_Video,
- &MEDIASUBTYPE_NULL
- };
- const AMOVIESETUP_PIN sudpPins[] =
- {
- { L"Input",
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- &CLSID_NULL,
- NULL,
- 1,
- &sudInputPinTypes
- },
- { L"Output",
- FALSE,
- TRUE,
- FALSE,
- FALSE,
- &CLSID_NULL,
- NULL,
- 1,
- &sudOutputPinTypes
- }
- };
- const AMOVIESETUP_FILTER sudFlipFilter =
- {
- &CLSID_FlipFilter,
- L"FlipFilter",
- MERIT_DO_NOT_USE,
- 2,
- sudpPins
- };
- CFactoryTemplate g_Templates[] = {
- { L"FlipFilter"
- , &CLSID_FlipFilter
- , CFlipFilter::CreateInstance
- , NULL
- , &sudFlipFilter }
- };
- int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
- REGFILTER2 rf2FilterReg = {
- 1,
- MERIT_DO_NOT_USE,
- 2,
- sudpPins
- };
3、注冊和注销filter,DLL的全局入口
- BOOL APIENTRY DllMain(HANDLE hModule,
- DWORD dwReason,
- LPVOID lpReserved)
- {
- return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
- }
- STDAPI DllRegisterServer()
- {
- return AMovieDllRegisterServer2( TRUE );
- }
- STDAPI DllUnregisterServer()
- {
- return AMovieDllRegisterServer2( FALSE );
- }
Filter编写完毕。
DirectShow基础编程 最简单transform filter 编写步骤的更多相关文章
- 简单的TSQL基础编程格式,存储过程,视图
这里简单整理一下数据库简单的编程,变量定义,赋值,分支语句和循环(这里以Sqlserver),以及存储过程格式 首先是变量定义,赋值,分支语句 --======TSQL数据库基础编程,定义变量,赋值, ...
- Hadoop 综合揭秘——MapReduce 基础编程(介绍 Combine、Partitioner、WritableComparable、WritableComparator 使用方式)
前言 本文主要介绍 MapReduce 的原理及开发,讲解如何利用 Combine.Partitioner.WritableComparator等组件对数据进行排序筛选聚合分组的功能.由于文章是针对开 ...
- MQ java 基础编程
MQ java 基础编程 编写人:邬文俊 编写时间 : 2006-2-16 联系邮件 : wenjunwu430@gmail.com 前言 通过 2 个多星期对 MQ 学习,在 partner 丁 & ...
- 【Linux基础总结】Shell 基础编程
Shell 基础编程 重启虚拟机遇到磁盘损坏如何解决 Shell编程中变量的声明.引用及作用域 Shell程序 概述 以文件形式存放批量的Linux命令集合,该文件能够被Shell解释执行,这种文件就 ...
- ARM Cortex-M嵌入式C基础编程(下)
ARM Cortex-M嵌入式C基础编程(下) ARM Cortex-M Embedded C Fundamentals/Tutorial -Aviral Mittal Load Region Vs ...
- ARM Cortex-M嵌入式C基础编程(上)
ARM Cortex-M嵌入式C基础编程(上) ARM Cortex-M Embedded C Fundamentals/Tutorial -Aviral Mittal 此技术是关于从编写简单的嵌入式 ...
- 异步编程系列第04章 编写Async方法
p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提 ...
- 【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单
一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两 ...
- JS基础(超级简单)
1 JS基础(超级简单) 1.1 数据类型 1.1.1 基本类型: 1) Number:特别注意:NaN的检测方法:Nan!=NaN;或者使用isNaN方法 2) ...
随机推荐
- 如何高效地向Redis插入大量的数据(转)
最近有个哥们在群里问,有一个日志,里面存的是IP地址(一行一个),如何将这些IP快速导入到Redis中. 我刚开始的建议是Shell+redis客户端. 今天,查看Redis官档,发现文档的首页部分( ...
- 警惕!iPhone 6即将上市 诈骗邮件已现身网络
随着iPhone 6即将上市,各路小道消息已经開始满天飞.就在近几日,一些记者还收到了假的iPhone 6将要上市的通知邮件.趋势科技也收到了几封,下面是样本之中的一个: (垃圾邮件样本) 不清楚iP ...
- bzoj2301(莫比乌斯反演+分块)
传送门:2301: [HAOI2011]Problem b 题意:对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y ...
- Domain Model(领域模型)
Domain Model(领域模型) 上一篇:<DDD 领域驱动设计-如何 DDD?> 开源地址:https://github.com/yuezhongxin/CNBlogs.Apply. ...
- hdu2159(二维完全背包)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2159 题意:打怪,还有最后一级,忍耐度有限m,问在杀怪数量上限为s的情况下能否获取n经验而通关,且忍耐 ...
- bzoj 3519: [Zjoi2014] 消棋子 题解
[序言]在大家怀疑的眼光下,我做了一个中午和半个下午.调了一个晚上的题目总算A了! [原题] 消棋子是一个有趣的游戏.游戏在一个r * c的棋盘上进行.棋盘的每一个格 子.要么是空,要么是一种颜色的棋 ...
- jquery关于表格隐藏和显示问题
1. 关于指定表格指定列隐藏显示 $(":checkbox[name*=month]").each(function(){ if(!$(this).attr("check ...
- Jersey框架二:Jersey对JSON的支持
Jersey系列文章: Jersey框架一:Jersey RESTful WebService框架简介 Jersey框架二:Jersey对JSON的支持 Jersey框架三:Jersey对HTTPS的 ...
- hdu3974(线段树+dfs)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3974 题意:给定点的上下级关系,规定如果给i分配任务a,那么他的所有下属.都停下手上的工作,开始做a. ...
- el表达式 分页提交 中文乱码
el表达式 分页提交 中文乱码 网上找了很多资料,没能解决我的问题.并不是说网上的那些资料不好.而是不适用于我的问题吧. 看看的的问题: 原始页面 单击下一页 , 乱码. 引起的原因则是因为自己的js ...