设计自定义的Filter.docx

上传人:b****7 文档编号:24008898 上传时间:2023-05-23 格式:DOCX 页数:15 大小:21.06KB
下载 相关 举报
设计自定义的Filter.docx_第1页
第1页 / 共15页
设计自定义的Filter.docx_第2页
第2页 / 共15页
设计自定义的Filter.docx_第3页
第3页 / 共15页
设计自定义的Filter.docx_第4页
第4页 / 共15页
设计自定义的Filter.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

设计自定义的Filter.docx

《设计自定义的Filter.docx》由会员分享,可在线阅读,更多相关《设计自定义的Filter.docx(15页珍藏版)》请在冰豆网上搜索。

设计自定义的Filter.docx

设计自定义的Filter

如何设计自定义的transformfilter(转)

对于DIrectShow的初学者而言,最大的困难莫过于尝试设计自定义的filter。

设计自定义的transformfilter是困难的

因为首先filter是一种dll(后缀名为.ax)而编写dll工程需要一定的VC基础所以建议先补充一点dll的知识

其次dll的注册,GUID的生成和工程的配置都很麻烦。

再次网上缺乏现成的transformfilter的例子。

DirectShow给的源码比如NULLINPLACE和CONTRAST都太复杂,都带有对话框和属性页,不适合初学者,而且这些例子没有一个涉及到图像格式的转换,而transformfilter最大的公用就是媒体类型的转换,因此这些例子不适用

作为一个初学者,我深深受到这些问题的困扰,经过刻苦钻研终于走出了这个泥潭,豁然开朗。

于是把它记录下来,希望可以对其他人有帮助,也作为对08年的一个小结。

我的例子是设计一个transformfilter把YUY216bit的媒体转化为RGB2424bit的类型。

原因是我的摄像头只支持YUY216bit这种格式,我想得到位图。

顺便学习一下Filter的设计

以下为具体步骤:

一配置开发环境

  1.VC中在Tools->Options->Directories设置好DirectXSDK的头文件和库文件路径   

  2.编译了基类源码,生成strmbasd.lib(debug版),strmbase.lib(release版)

  3.VC向导新建一个win32DLL(empty)工程

  4.Setting->Link->Outputfilename:

YUV2RGBfilter.ax

  5.Setting->Link加入strmbasd.libwinmm.libquartz.libvfw32.lib  (注意路径)

  6.定义一个同名.def文件,加入到工程,内容如下:

         

       LIBRARYYUV2RGBfilter.ax

       EXPORTS

          DllMain             PRIVATE  

          DllGetClassObject   PRIVATE

          DllCanUnloadNow     PRIVATE

          DllRegisterServer   PRIVATE

          DllUnregisterServerPRIVATE

  7.建立一个类YUV2RGBfilter建立他的cpp文件和h文件

  

  8.在YUV2RGBfilter.cpp中定义DLL的入口函数及注册  放在cpp文件的最后

//

//DllEntryPoint

//

extern"C"BOOLWINAPIDllEntryPoint(HINSTANCE,ULONG,LPVOID);

BOOLAPIENTRYDllMain(HANDLEhModule,

                     DWORDdwReason,

                     LPVOIDlpReserved)

{

returnDllEntryPoint((HINSTANCE)(hModule),dwReason,lpReserved);

}

////////////////////////////////////////////////////////////////////////

//

//Exportedentrypointsforregistrationandunregistration

//(inthiscasetheyonlycallthroughtodefaultimplementations).

//

////////////////////////////////////////////////////////////////////////

STDAPIDllRegisterServer()

{

   returnAMovieDllRegisterServer2(TRUE);

}

STDAPIDllUnregisterServer()

{

    returnAMovieDllRegisterServer2(FALSE);

}

  9.cpp文件中要包含的头文件

#include

#include

#include

#include

#if(1100>_MSC_VER)

#include

#endif

#include"Y2Ruids.h"        //ourownpublicguids

#include"YUV2RGBfilter.h"

  

二开发Filter

  1.生成GUID(命令行模式下运行guidgen工具)为他建立一个文件Y2Ruids.h单独引用

#include

//YUV2toRGB24FilterObject

//{F91FC8FD-B1A6-49b0-A308-D6EDEAF405DA}

DEFINE_GUID(CLSID_YUV2toRGB24,

0xf91fc8fd,0xb1a6,0x49b0,0xa3,0x8,0xd6,0xed,0xea,0xf4,0x5,0xda);

      

  2.构造CYUV2RGBfilter类继承自CTransformFilter   写在TransformFilter.h中

//----------------------------------------------------------------------------

//ClassdefinitionsofCYUV2RGBfilter

//----------------------------------------------------------------------------

//

//

classCYUV2RGBfilter:

publicCTransformFilter

{

   public:

       staticCUnknown*WINAPICreateInstance(LPUNKNOWNpunk,HRESULT*phr);

       STDMETHODIMPNonDelegatingQueryInterface(REFIIDriid,void**ppv);

  

       DECLARE_IUNKNOWN;

//overridepurevirtualfunction

       HRESULTCheckInputType(constCMediaType*mtIn);

       HRESULTCheckTransform(constCMediaType*mtIn,constCMediaType*mtOut);

       HRESULTDecideBufferSize(IMemAllocator*pAlloc,ALLOCATOR_PROPERTIES*pProp);

       HRESULTGetMediaType(intiPosition,CMediaType*pMediaType);

       HRESULTTransform(IMediaSample*pIn,IMediaSample*pOut);

   private:

       //Constructor

       CYUV2RGBfilter(TCHAR*tszName,LPUNKNOWNpunk,HRESULT*phr);

  //memberfunction

  VOIDChangeFormat(AM_MEDIA_TYPE*pAdjustedType);

  DWORDConvertYUV2toRGB(BYTE*yuv,BYTE*rgb,DWORDdsize);

   //membervariable

  constlongm_lBufferRequest;

       CCritSecm_Y2RLock;    //Toserialiseaccess.

};

  3.按格式改写构造函数

       //

//CNullInPlace:

:

Constructor

//

CYUV2RGBfilter:

:

CYUV2RGBfilter(TCHAR*tszName,LPUNKNOWNpunk,HRESULT*phr):

   CTransformFilter(tszName,punk,CLSID_YUV2toRGB24),

   m_lBufferRequest

(1)

{

ASSERT(tszName);

   ASSERT(phr);

   

}//CYUV2RGBfilter

  4.改写CTransformFilter五个纯虚函数(最重要的地方)

       HRESULTCheckInputType(constCMediaType*mtIn);

       HRESULTCheckTransform(constCMediaType*mtIn,constCMediaType*mtOut);

       HRESULTDecideBufferSize(IMemAllocator*pAlloc,ALLOCATOR_PROPERTIES*pProp);

       HRESULTGetMediaType(intiPosition,CMediaType*pMediaType);

       HRESULTTransform(IMediaSample*pIn,IMediaSample*pOut);

  5.设计自己的私有函数完成一定的功能

  6.注册Filter信息

      

//注册信息

//setupdata

constAMOVIESETUP_MEDIATYPE

sudPinTypes=  {&MEDIATYPE_Video               //clsMajorType

               ,&MEDIASUBTYPE_NULL};      //clsMinorType

constAMOVIESETUP_PIN

psudPins[]={{L"Input"           //strName

              ,FALSE              //bRendered

              ,FALSE              //bOutput

              ,FALSE              //bZero

              ,FALSE              //bMany

              ,&CLSID_NULL        //clsConnectsToFilter

              ,L"Output"          //strConnectsToPin

              ,1                  //nTypes

              ,&sudPinTypes}     //lpTypes

            ,{L"Output"          //strName

              ,FALSE              //bRendered

              ,TRUE               //bOutput

              ,FALSE              //bZero

              ,FALSE              //bMany

              ,&CLSID_NULL        //clsConnectsToFilter

              ,L"Input"           //strConnectsToPin

              ,1                  //nTypes

              ,&sudPinTypes}};  //lpTypes

constAMOVIESETUP_FILTER

sudYUV2RGB={&CLSID_YUV2toRGB24                //clsID

           ,L"YUV2RGB"               //strName

           ,MERIT_DO_NOT_USE               //dwMerit

           ,2                              //nPins

           ,psudPins};                    //lpPin

//

//NeededfortheCreateInstancemechanism

//

CFactoryTemplateg_Templates[1]=

   {  {L"YUV2RGB"

       ,&CLSID_YUV2toRGB24

       ,CYUV2RGBfilter:

:

CreateInstance

       ,NULL

       ,&sudYUV2RGB}

   };

intg_cTemplates=sizeof(g_Templates)/sizeof(g_Templates[0]);

编译成功后生成GrayFilter.ax

命令行运行regsvr32GrayFilter.ax注册即可不用反复注册,只用注册一次,如若修改只需将重新编译的.ax覆盖原来的就行了

调试最好在graphEdit中经行比较方便。

以上就是设计一个filter的总体步骤。

三下面就关键点五个重载的纯虚函数做详细介绍。

这才是最关键的地方。

       HRESULTCheckInputType(constCMediaType*mtIn);

       HRESULTCheckTransform(constCMediaType*mtIn,constCMediaType*mtOut);

       HRESULTDecideBufferSize(IMemAllocator*pAlloc,ALLOCATOR_PROPERTIES*pProp);

       HRESULTGetMediaType(intiPosition,CMediaType*pMediaType);

       HRESULTTransform(IMediaSample*pIn,IMediaSample*pOut);

这五个函数全部是都纯虚函数,是CTransformFilter为我们提供的接口,必须重载他们才能实例化。

初学者最大的困扰莫过于,是谁调用了这些函数。

这些函数调用的时候实参是从哪来的。

我一开始就被这些问题困扰。

其实DX的帮助文档里就讲的很清楚了只是我一开始没认真看;

CheckInputType是由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中确认输出的媒体格式是不是期望的输出。

例如要将YUY216bit的媒体格式改为RGB88bit的媒体格式就要做如下修改:

在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.biSizeImage    =  307200;  

  vih.bmiHeader.biClrImportant=  0;  

     vih.bmiHeader.biClrUsed  =  256;

//alterthepallete

  for(UINTi=0;i<256;i++)

  {

   vih.bmiColors[i].rgbBlue=(BYTE)i;

   vih.bmiColors[i].rgbRed=(BYTE)i;

   vih.bmiColors[i].rgbGreen=(BYTE)i;

   vih.bmiColors[i].rgbReserved=(BYTE)0;

   }

  pMediaType->SetType(&MEDIATYPE_Video);  

  pMediaType->SetFormatType(&FORMAT_VideoInfo);  

  pMediaType->SetFormat((BYTE*)&vih,sizeof(vih));  

  pMediaType->SetSubtype(&MEDIASUBTYPE_RGB8);  

  pMediaType->SetSampleSize(307200);

returnNOERROR;

然后在checkTransform中确认是否是期望的输出

  BITMAPINFOHEADER*pNewType=HEADER(mtOut->Format());

  if((pNewType->biPlanes==1)

   &&(pNewType->biBitCount==8)

   &&(pNewType->biWidth==640)

   &&(pNewType->biHeight==480)

   &&(pNewType->biClrUsed==256)

   &&(pNewType->biSizeImage==307200))

  {

   returnS_OK;

  }

我的实现过程如下

//GetMediaType

//

//Isupportonetype,namelythetypeoftheinputpin

//Wemustbeconnectedtosupportthesingleoutputtype

//

HRESULTCYUV2RGBfilter:

:

GetMediaType(intiPosition,CMediaType*pMediaType)

{

   //Istheinputpinconnected

   if(m_pInput->IsConnected()==FALSE)

   {

       returnE_UNEXPECTED;

   }

   //Thisshouldneverhappen

   if(iPosition<0)

   {

       returnE_INVALIDARG;

   }

   //Dowehavemoreitemstooffer

   if(iPosition>0)

   {

       returnVFW_S_NO_MORE_ITEMS;

   }

   CheckPointer(pMediaType,E_POINTER);

if(iPosition==0)

{

  HRESULThr=m_pInput->ConnectionMediaType(pMediaType);

  if(FAILED(hr))

  {

   returnhr;

  }

}

//makesomeappropriatechange

ASSERT(pMediaType->formattype==FORMAT_VideoInf

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 视频讲堂

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1