DirectShow在视频处理方面的一些应用

DirectShow是微软提供的DirectX软件开发包中的一员,主要以处理流媒体数据为重点开发的一套windows下的编程接口,为了高效地处理音视频数据,它向应用提供了直接访问系统底层功能的接口,可以使应用直接控制从数据采集到数据演播的各个中间环节,如数据压缩和解压缩格式等。

DirectShow是以一种比较新的概念来操作媒体流运行的,他有点类似于计算机硬件的管脚Pin的概念,并且引进了滤波器Filter和流图Graph等原理。媒体流通过流图中的各个滤波器,最后到达输出界面,期间经过各个滤波器的转化和控制使最终数据达到一定的要求。通过DirectShow的基本接口,应用可以自行设计自己的各种滤波器完成数据在流动中的特殊处理需求,比如视频数据流的格式从MPEG到RGB的变换(解压缩)或象素格式从YUV到RGB的变换等。

(1) DirectShow的graph原理

Graph实际上是一个filters的容器,Dshow提供一个Graph控件(Com),应用可以用CoCreateInstance来建立一个graph对象。在Dshow中还有一个用于创建和操作Graph,这就是Builder对象,一般来讲,应用应该首先创建Builder对象,它是Dshow流控制的关键,Builder接口提供的方法包含了智能创建Graph中filters的能力,当未知媒体流格式时,使用Builder连接Filter时,将智能添加系统中的格式转换Filter到Graph的Filters链中产生目标格式的最佳转换链。

建立Builder和Graph后,将Graph加入到Builder中,便可以往Graph中添加指定的Filter了,一般系统中的Video设备是由设备枚举过程获得的,系统中的每一种视频驱动,都定义为一个视频设备(音频设备也是如此)。函数:

CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);

建立系统设备枚举器对象,其中:

ICreateDevEnum * pCreateDevEnum;//设备枚举器对象指针

GUIDIID_IcreateDevEnum//设备枚举器接口的GUID

ConstCLSCTX_INPROC_SERVER//被建立对象的进程特征

GUIDCLSID_SystemDeviceEnum//枚举器对象类的GUID

注意:GUID包含在Dshow头文件UUID.h中。

利用设备枚举对象列出系统中已经安装的设备,每一个设备类形成一个IEnumMoniker对象然后枚举该类设备在系统中的安装个数:

//建立视频输入设备枚举器

IEnumMoniker *pEm;

pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);

pEm是已经建立的视频设备枚举器,通过该对象枚举系统的视频设备。

IMoniker * pM;//枚举视频设备

pEm->Next(1, &pM, &cFetched), hr==S_OK)//获得一个Imoniker接口

Dshow通过设备的Imoniker接口操作系统中的设备。同样步骤可以获得系统中的音频设备,它们统称为系统的输入设备。(关于函数的参数定义可以查看VC的帮助)

Imoniker对象通过提供的BindToObject方法可以获得输入设备的Filter对象

pM –>BindToObject(0, 0, IID_IBaseFilter, (void**)&pVCap);

pVCap就是视频输入设备对象,利用QueryInterface函数可以获得特殊输入设备的接口对象(因为pVCap仅反映出一个基本的滤波器对象,因此不能反映一些特殊的方法,查询特殊接口需要知道接口的GUID,这可以通过设备购买时提供的资料获得,一般而言不需特殊接口功能,使用基本功能可以保证应用系统的兼容性和广泛可用性。

取得设备后将其加入到Graph中,然后使用智能连接的系统默认Render

pGraph->AddFilter(pVCap, NULL);

pBuilder->RenderStream( &PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,pACap,NULL,NULL);

就可以形成一条从输入开始到系统默认Render的视频播放filters链路了,启动这个链路,则可以在显示器上看到视频图象。当然还需要设置显示窗口的大小和位置。这个播放链路是建立在视频输入设备的Capture管脚上的,如果设备不存在Capture管脚,链路建立则不能成功,也可以将播放链路建立在Preview管脚上(PIN_CATEGORY_PREVIEW)。

这是一个USB小摄象头作为视频输入设备的滤波器播放链路,在指定显示窗口大小的情况下,可以播放视频数据流。Graph基本概念框图如下:

其中:Filter1..是应用自己加入的特殊Filter来进行视频数据流的特殊处理,比如嵌入字模,滚动视频和实时取图等,也可以进行视频数据的特殊压缩和解压缩处理。视频数据流以pSample缓冲的方式逐级经过各个filter,最后到达render进行显示处理,pSample是filter数据交换缓冲区指针,应用通过自己的filter改变pSample的数据达到改变视频流显示的目的。

(2) 建立和使用Filter

建立滤波器,就是建立一个滤波器对象类,并且输出一个接口方法组,根据滤波器的用途选择合适的父类,一般Dshow提供各种供选择的父类对象和接口,比如Graber用途的滤波器,可以直接抓取内存中的帧图象,比使用window API的cap类函数抓图要强很多。定义接口方法:

DECLARE_INTERFACE_(IGrabberIPP, IUnknown){

STDMETHOD(put_MediaType) (THIS_ CMediaType *pmt ) PURE;

/* [in]  */

// the media type selected

STDMETHOD(get_MediaType) (THIS_ CMediaType **pmt) PURE;

/* [out] */

// the media type selected

STDMETHOD(get_IPin) (THIS_ IPin **pPin ) PURE;         

/* [out] */

//the source pin

STDMETHOD(get_State) (THIS_ FILTER_STATE *state ) PURE;

/* [out] */

//the filter state

STDMETHOD(get_FilterIPin) (THIS_ int n,IPin **pPin ) PURE;

/*[in][out] */

// the in/out pin

STDMETHOD(get_ImageSize) (THIS_ long * outWidth, long * outHeight, long * outBitCount) PURE;

STDMETHOD(get_FrameSize) (THIS_long * outFrameSize) PURE;

STDMETHOD(get_BitmapInfoHeader) (THIS_ BITMAPINFOHEADER * outBitmapInfo) PURE;

STDMETHOD(get_Is16BitsRGB) (THIS_ long * outIsRGB565) PURE;

STDMETHOD(put_IsFieldPicture) (THIS_ BOOL inIsField) PURE;

STDMETHOD(Snapshot) (THIS_ BYTE * outBuffer, BOOL inIsSyncMode) PURE;

STDMETHOD(IsAsyncSnapshotFinished) (THIS_ BOOL * outFinished) PURE;

STDMETHOD(CancelAllPending) (THIS) PURE;

};

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

定义滤波器对象:

class CGrabberInPlace : public CtransInPlaceFilter, public IGrabberIPP

{……};

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

写一个滤波器对象和输出接口方法后,便可以用regsvr32注册滤波器到系统中,应用便可以使用该滤波器:

1、  用CoCreateInstance建立接口实例,使用基本滤波器对象类的GUID。

CoCreateInstance (

CLSID_GrabberInPlace,

NULL,

CLSCTX_INPROC_SERVER,

IID_IBaseFilter,

(void **)&pBf);

CLSID_GrabberInPlace//指定滤波器的类GUID,在你自己的滤波器中定义

IID_IbaseFilter//基本滤波器对象接口GUID,它是所有滤波器的父类

此时,你获得的是一个包含你自己的滤波器的基本滤波器指针(特殊的方法函数是不出现在该接口中的),当你需要使用特殊方法时,使用QueryInterface,查询得到特殊接口指针:

pBf->QueryInterface(IID_GrabberIPP, (void **)&pGf);

IID_GrabberIPP//特殊滤波器的接口GUID

PGf//特殊滤波器接口指针

使用pGf,就可以操作特殊滤波器处理视频数据。注意:在你编写自己的特殊滤波器方法时,需要精确了解滤波器父类各层对象的操作关系和方法,这样才能灵活的处理各种情况的发生,滤波器是系统应用层以下的系统程序,它的任何异常都可能导致系统的崩溃,因此在调试阶段应该仔细处理各种情况。

(3) VC开发环境的设置

1安装directX开发环境

2指定include目录:

directX安装目录下的include

directX安装目录下的SAMPLES\MULTIMEDIA\COMMON\INCLUDE

directX安装目录下的SAMPLES\MULTIMEDIA\DIRECTSHOW\BASECLASSES

一般安装目录根据directX的版本可能会有差异,选择对应目录。

3库目录library

directX安装目录下的lib

directX安装目录下的

SAMPLES\MULTIMEDIA\DIRECTSHOW\BASECLASSES\DEBUG

4库Library的指定

在项目设置setting下的link中一定要指定下面的库,

uuid.lib

winmm.lib

msacm32.lib

strmiids.lib

strmbasd.lib

有时还需要删除这些库前面的路径,因为在路径中已经指定了库的路径。

5运行编译前首先要编译连接基本类,生成strmbasd.lib到指定位置。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值