设计自定义的Filter

上传人:jin****ng 文档编号:124584721 上传时间:2022-07-25 格式:DOC 页数:18 大小:89KB
返回 下载 相关 举报
设计自定义的Filter_第1页
第1页 / 共18页
设计自定义的Filter_第2页
第2页 / 共18页
设计自定义的Filter_第3页
第3页 / 共18页
亲,该文档总共18页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
如何设计自定义的transform filter(转)对于DlrectShow的初学者而言,最大的困难莫过于尝试设计自定义的filter。设计自定义的transform filter是困难的因为 首先filter是一种dll (后缀名为.ax)而编写dll工程需要一定的VC基础 所以建议先补 充一点dll的知识其次dll的注册,GUID的生成和工程的配置都很麻烦。再次 网上缺乏现成的transform filter的例子。DirectShow给的源码比如NULLINPLACE和CONTRAST都太复杂,都带有对话框和属性页,不适合初学者,而且这些例子没有一个涉及 到图像格式的转换,而transform filter最大的公用就是媒体类型的转换,因此这些例子不适用 作为一个初学者,我深深受到这些问题的困扰,经过刻苦钻研终于走出了这个泥潭,豁然开朗。 于是把它记录下来,希望可以对其他人有帮助,也作为对08年的一个小结。我的例子是设计一个transform filter把YUY2 16bit的媒体转化为RGB24 24bit的类型。原因是我的摄像头只支持YUY2 16bit这种格式,我想得到位图。顺便学习一下Filter的设计 以下为具体步骤:一配置开发环境1. VC中在Tools-Options-Directories设置好DirectX SDK的头文件和库文件路径2. 编译了基类源码,生成 strmbasd.lib (debug 版),strmbase.lib(release 版)3. VC向导新建一个Win32 DLL(empty)工程牛 Setting-Link-Output file name: YUV2RGBfilter.ax5. Setting-Link 力口入 strmbasd.lib winmm.lib quartz.lib vfw32.lib (注意路径)6. 定义一个同名.def文件,加入到工程,内容如下:LIBRARY YUV2RGBfilter.axEXPORTSDllMainPRIVATEDllGetClassObject PRIVATEDllCanUnloadNow PRIVATEDllRegisterServer PRIVATEDllUnregisterServer PRIVATE7建立一个类YUV2RGBfilter建立他的cpp文件和h文件&在YUV2RGBfilter.cpp中定义DLL的入口函数及注册 放在cpp文件的最后/ DllEntryPoint/extern C BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);BOOL APIENTRY DllMain(HANDLE hModule,DWORD dwReason,LPVOID lpReserved)return DllEntryPoint(HINSTANCE)(hModule), dwReason, lpReserved);/ Exported entry points for registration and unregistration/ (in this case they only call through to default implementations)./STDAPI DllRegisterServer()return AMovieDllRegisterServer2( TRUE );STDAPI DllUnregisterServer()return AMovieDllRegisterServer2( FALSE );9. cpp文件中要包含的头文件#include #include #include #include #if (1100 _MSC_VER)#include #endif#include Y2Ruids.h / our own public guids#include YUV2RGBfilter.h二开发 Filter1.生成GUID(命令行模式下运行guidgen工具)为他建立一个文件Y2Ruids.h单独引用#include / YUV2toRGB24 Filter Object/ F91FC8FD-B1A6-49bo-A3o8-D6EDEAF4O5DADEFINE_GUID(CLSID_YUV2toRGB24,oxf91fc8fd, oxb1a6, 0x49b。,oxa3, 0x8, oxd6, oxed, oxea, oxf4, 0x5, oxda);2.构造 CYUV2RGBfilter 类 继承自 CTransformFilter 写在 TransformFilter.h 中/ Class definitions of CYUV2RGBfilter/class CYUV2RGBfilter : public CTransformFilterpublic:static CUnknown * WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr);STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void * ppv);DECLARE_IUNKNOWN;/ override pure virtual functionHRESULT CheckInputType(const CMediaType *mtIn);HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut);HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES*pProp);HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut);private:/ConstructorCYUV2RGBfilter(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr);/ member functionVOID ChangeFormat(AM_MEDIA_TYPE* pAdjustedType);DWORD ConvertYUV2toRGB(BYTE* yuv, BYTE* rgb, DWORD dsize);/ member variableconst long m_lBufferRequest;CCritSec m_Y2RLock; / To serialise access.;3. 按格式改写构造函数/ CNullInPlace:Constructor/CYUV2RGBfilter:CYUV2RGBfilter(TCHAR *tszName,LPUNKNOWN punk,HRESULT *phr):CTransformFilter(tszName, punk, CLSID_YUV2toRGB24),m_lBufferRequest(1)ASSERT(tszName);ASSERT(phr); / CYUV2RGBfilter牛 改写CTransformFilter五个纯虚函数(最重要的地方)HRESULT CheckInputType(const CMediaType *mtIn);HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut);HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES*pProp);HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut);5. 设计自己的私有函数完成一定的功能6. 注册Filter信息/注册信息 /setup dataconst AMOVIESETUP MEDIATYPEsudPinTypes = & MEDIATYPE_Video/ clsMajorType,& MEDIASUBTYPE_NULL ;/ clsMinorTypeconst AMOVIESETUP_PINpsudPins = LInput/ strName,FALSE/ bRendered,FALSE/ bOutput,FALSE/ bZero,FALSE/ bMany,&CLSID_NULL / clsConnectsToFilter,LOutput/ strConnectsToPin,1/ nTypes,&sudPinTypes / lpTypes, LOutput/ strName,FALSE/ bRendered,TRUE/ bOutput,FALSE/ bZero,FALSE/ bMany,&CLSID_NULL / clsConnectsToFilter,LInput/ strConnectsToPin,1/ nTypes,&sudPinTypes ;/ lpTypesconst AMOVIESETUP_FILTERsudYUV2RGB = &CLSID_YUV2toRGB24/ clsID,LYUV2RGB/ strName,MERIT_DO_NOT_USE/ dwMerit/ nPins,psudPins ;/ lpPin/ Needed for the Createlnstance mechanism/CFactoryTemplate g_Templatesi = LYUV2RGB,&CLSID_YUV2toRGB24,CYUV2RGBfilter:CreateInstance,NULL,&sudYUV2RGB ;int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templateso);编译成功后生成GrayFilter.ax命令行运行regsvr32 GrayFilter.ax注册即可 不用反复注册,只用注册一次,如若修改只需将重 新编译的.ax覆盖原来的就行了调试最好在graphEdit中经行比较方便。以上就是设计一个filter的总体步骤。三下面就关键点五个重载的纯虚函数做详细介绍。这才是最关键的地方。HRESULT CheckInputType(const CMediaType *mtIn);HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut);HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES*pProp);HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut);这五个函数全部是都纯虚函数,是CTransformFilter为我们提供的接口,必须重载他们才能实 例化。初学者最大的困扰莫过于,是谁调用了这些函数。这些函数调用的时候实参是从哪来的。我一开 始就被这些问题困扰。其实DX的帮助文档里就讲的很清楚了只是我一开始没认真看; ChecklnputType是由tranformfiltr的输入pin调用的用来检查本Filter的输入媒体是否合法; CheckTransform是由tranformfiltr的输出pin调用的用来检查本filter的输出是否和合法; GetMediaType是有由tranformfiltr的输出pin调用的用来获取该输出端口支持的媒体格式供下 游filter的枚举DecideBufferSize是由tranformfiltr的输出pin调用的来确定buffer的数量和大小上游filter通过调用filter上输入pin上的IMemInputPin:Receive方法,将sample传递到filter, filter 调用 CTransformFilter:Transform 方法来处理数据整个过程就是输入pin调用CheckInputType来筛选上游过来的媒体类型,如果可以接受 就有输出pin通GetMediaType来枚举输出媒体类型,进一步通过输出pin的CheckTransform来找到与输入媒 体类型相融合的输出媒 体类型并选中。在通过DecideBufferSize确定输出buffer的属性,所有 的检查和筛选通过以后就可以连接了,并通过tranform将输入pin上的sample传个输出pin 输出媒体的类型是由GetMediaType来确定的,只要媒体类型对应了就可以成功连接但是数据 的传送还是要通过transform来实现。理论上对于没有压缩的视频,一个sample就是一帧的 数据,可以精确的量化处理。要实现输出pin上媒体格式的转化 就必须在在GetMediaType函数中修改新的媒体格式,然后 在checkTransform中确认 输出的媒体格式是不是期望的输出。例如 要将YUY2 16bit的媒体 格式改为RGB8 8bit的媒体格式就要做如下修改:在 GetMediaType 中CheckPointer(pMediaType,E_POINTER);VIDEOINFO vih;memset(&vih, 0, sizeof(vih);vih.bmiHeader.biCompression =0;vih.bmiHeader.biBitCount = 8;vih.bmiHeader.biSize = 40;vih.bmiHeader.biWidth=640;vih.bmiHeader.biHeight=480;vih.bmiHeader.biPlanes=1;vih.bmiHeader.biSizelmage = 307200;vih.bmiHeader.biClrlmportant =0;vih.bmiHeader.biClrUsed=256;/alter the palletefor (UINT i=0; iSetType(&MEDIATYPE_Video);pMediaType-SetFormatType(&FO RMAT_VideoInfo); pMediaType-SetFormat(BYTE*)&vih, sizeof(vih);pMediaType-SetSubtype(&MEDIASUBTYPE_RGB8);pMediaType-SetSampleSize07200);return NOERROR;然后在checkTransform中确认是否是期望的输出BITMAPINFOHEADER *pNewType = HEADER(mtOut-Format();if (pNewType-biPlanes=1)& (pNewType-biBitCount=8)& (pNewType-biWidth=640)& (pNewType-biHeight=48o)& (pNewType-biClrUsed=256)& (pNewType-biSizeImage=3O72OO)return S_OK;我的实现过程如下/ GetMediaType/ I support one type, namely the type of the input pin/ We must be connected to support the single output type/HRESULT CYUV2RGBfilter:GetMediaType(int iPosition, CMediaType *pMediaType)/ Is the input pin connectedif(m_pInput-IsConnected() = FALSE)return E_UNEXPECTED;/ This should never happenif(iPosition 0)return VFW_S_NO_MORE_ITEMS;CheckPointer(pMediaType,E_POINTER);if (iPosition = 0)HRESULT hr = m_pInput-ConnectionMediaType(pMediaType);if (FAILED(hr)return hr;/ make some appropriate changeASSERT(pMediaType-formattype = FORMAT_VideoInfo); pMediaType-subtype = MEDIASUBTYPE_RGB24; VIDEOINFOHEADER *pVih = reinterpret_cast(pMediaType-pbFormat); pVih-bmiHeader.biCompression = 0;pVih-bmiHeader.biSizeImage = DIBSIZE(pVih-bmiHeader); pVih-bmiHeader.biBitCount = 24;pVih-bmiHeader.biHeight = 480; pVih-bmiHeader.biWidth = 640; return S_OK; / GetMediaType/ CheckInputType / Check the input type is OK, return an error otherwise /HRESULT CYUV2RGBfilter:CheckInputType(const CMediaType *mtln) CheckPointer(mtIn,E_POINTER);/ Check this is a VIDEOINFO typeif(*mtIn-FormatType() != FORMAT_VideoInfo)return E_INVALIDARG;if(IsEqualGUID(*mtIn-Type(), MEDIATYPE_Video) &(IsEqualGUID(*mtIn-Subtype(), MEDIASUBTYPE_YUY2)VIDEOINFO *pvi = (VIDEOINFO *) mtIn-Format();if (pvi-bmiHeader.biBitCount = 16)&( pvi-bmiHeader.biCompression=o)return S_OK;elsereturn FALSE;elsereturn FALSE; / CheckInputType/ CheckTransform / To be able to transform the formats must be compatible/mtln YUV2 i6bit/mtOut RGB24 24bitHRESULT CYUV2RGBfilter:CheckTransform(const CMediaType *mtln, const CMediaType*mtOut)CheckPointer(mtIn,E_POINTER);CheckPointer(mtOut,E_POINTER);HRESULT hr;if(FAILED(hr = CheckInputType(mtIn)return hr;/ format must be a VIDEOINFOHEADERif(*mtOut-FormatType() != FORMAT_VideoInfo)|(mtOut-cbFormatsubtype!=MEDIASUBTYPE_RGB24)return E_INVALIDARG;BITMAPINFOHEADER *pBmiOut = HEADER(mtOut-pbFormat);if (pBmiOut-biPlanes!=1)|(pBmiOut-biBitCount!=24)|(pBmiOut-biCompression!=o)|(pBmiOut-biWidth!=64o)|(pBmiOut-biHeight!=48o)return E_INVALIDARG;return S_OK;/ CheckTransformHRESULT CYUV2RGBfilter:DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)CheckPointer(pAlloc,E_POINTER);CheckPointer(pProperties,E_POINTER);/ Is the input pin connectedif(m_pInput-IsConnected() = FALSE)return E_UNEXPECTED;HRESULT hr = NOERROR;pProperties-cBuffers = 1;pProperties-cbBuffer = m_pInput-CurrentMediaType().GetSampleSize()*2; /output isdouble of the input samplesASSERT(pProperties-cbBuffer);/ If we dont have fixed sized samples we must guess some sizeif(!m_pInput-CurrentMediaType().bFixedSizeSamples)if(pProperties-cbBuffer cbBuffer = 100000;/ Ask the allocator to reserve us some sample memory, NOTE the function/ can succeed (that is return NOERROR) but still not have allocated the/ memory that we requested, so we must check we got whatever we wantedALLOCATOR_PROPERTIES Actual;hr = pAlloc-SetProperties(pProperties,&Actual);if(FAILED(hr)return hr;ASSERT(Actual.cBuffers = 1);if(pProperties-cBuffers Actual.cBuffers |pProperties-cbBuffer Actual.cbBuffer)return E_FAIL;return NOERROR; / DecideBufferSize/ Transform/ Copy the input sample into the output sample /HRESULT CYUV2RGBfilter:Transform(IMediaSample *pln, IMediaSample *pOut) CheckPointer(pIn,E_POINTER);CheckPointer(pOut,E_POINTER);/ Copy the sample dataBYTE *pSourceBuffer, *pDestBuffer;long lSourceSize = pIn-GetActualDataLength();long lDestSize = (long)(lSourceSize*1.5);pIn-GetPointer(&pSourceBuffer);pOut-GetPointer(&pDestBuffer);/change dataConvertYUV2toRGB(pSourceBuffer,pDestBuffer,lSourceSize);/memset(pDestBuffer,1OO,lDestSize);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);/ Copy the Sync point propertyHRESULT hr = pIn-IsSyncPoint(); if(hr = S_OK)pOut-SetSyncPoint(TRUE);else if(hr = S_FALSE)pOut-SetSyncPoint(FALSE);else / an unexpected error has occured. return E_UNEXPECTED;/AM_MEDIA_TYPE* pMediaType; pIn-GetMediaType(&pMediaType);ChangeFormat(pMediaType);/ Copy the media type pOut-SetMediaType(pMediaType);/ Copy the preroll propertyhr = pIn-IsPreroll();if(hr = S_OK)pOut-SetPreroll(TRUE);else if(hr = S_FALSE)pOut-SetPreroll(FALSE);else / an unexpected error has occured.return E_UNEXPECTED;/ Copy the discontinuity propertyhr = pIn-IsDiscontinuity();if(hr = S_OK)pOut-SetDiscontinuity(TRUE);else if(hr = S_FALSE)pOut-SetDiscontinuity(FALSE);else / an unexpected error has occured.return E_UNEXPECTED;/ Copy the actual data lengthKASSERT(long)lDestSize GetSize();pOut-SetActualDataLength(lDestSize);return S_OK; / Transform经过这些步骤就能得到符合功能要求的transform filter同时经过以上步骤也能对filter开发有个大体的了解
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 活动策划


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!