VS2010C++学习(5):基于DirectShow的视频预览录像程序学习VC++编制的基于DirectShow视频捕获程序,主要练习基于DirectShow程序的应用。
一、主要内容:1.基于DirectShow视频预览;2.基于DirectShow视频录像;二、设计实现:(一)、安装DirectShow首先我们安装DirectShow SDK,由于现在directShow没有和direcxtx一起发布,而是和windows sdk打包发布了,可以到官网下载最新的windows sdk开发包。
一个可用的下载地址为/07/hh/DXSDK_Feb10.rar 然后安装好windows SDK。
安装完DirectShow SDK的目录为C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow。
(二)、开发环境配置开发环境的配置主要有两个工作要做:一是在使用Directshow SDK开发自己的程序时需要的DirectShow的有关静态库的配置,二是visual C++开发环境的配置。
1)生成DirectShow SDK开发库使用DirectShow SDK开发用户自己的程序需要几个静态链接库:quartz.lib、strmbasd.lib、STRMBASE.lib和strmiids.lib。
中间两个lib需要用户自己编译生成,而其他两个微软已经提供。
下表列出了使用DirectShow SDK开发程序所有要使用的库。
2)更改添加的include内容:C:\Program Files\MicrosoftSDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses;C:\Program Files\Microsoft SDKs\Windows\v7.1\Include;添加过程如下。
选择“Ex005属性”→“选项”→“VC++目录”→“包含目录”,将上面的2个Include内容添加进去。
3)更改添加lib路径要添加的lib内容:C:\Program Files\MicrosoftSDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses\Debug;C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib;添加过程和Include内容相似,选择“Ex005属性”→“选项”→“VC++目录”→“库文件”选项。
4)添加链接库支持C:\Program Files\MicrosoftSDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses\Debug;C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib;5)小贴士DirectShow中的例子,在编译的过程中经常会出现这样的错误:Error1error C2061:syntax error:identifier'CAMSchedule'c:/program files/microsoftsdks/windows/v6.0/samples/multimedia/directshow/baseclasses/refclock.h80这主要是因为在不同SDK的目录里包含了多个schedule.h file和refclock.h因此需要在“Ex005属性”→“选项”→“VC++目录”→“包含目录”中调整include的顺序,将samples/multimedia/directshow/baseclasses放到其他的sdk之前即可(三)、DirectShow视频采集方案流媒体处理技术以其复杂性和技术性一直受到人们的关注。
随着网络技术的不断发展,流媒体在网络上得到了广泛地应用。
如何能够简单、有效地进行流媒体处理,已成为一个焦点问题。
为此,Microsoft推出了DirectShow,DirectShow 是Microsoft推出的基于Windows平台的流媒体处理开发包,它与DirectX一起发布。
DirectShow对流媒体的捕捉、回放提供了强大的支持。
1)DirectShow系统结构分析DirectShow主要由过滤器(Filter Graph)图表构成。
过滤图表中包含了各种Filter,这些Filter能够按一定顺序连接在一起,构成一条流水线。
从功能的角度划分,Filter大体可以分为3类,●Source Filters;主要负责获取数据,可以是一个文件、一个采集卡、声卡或数码相机等。
●Transform Filters;负责数据的转换、传输。
例如各种码器、解码器等。
●Rendering Filters。
负责数据的最终去向,例如将数据传送到声卡、显卡或存储为文件。
在开发DirectShow应用程序时,通常需要设计一个过滤图表(Filter Graph),向过滤图表中添加相应的过滤器,最后连接过滤器的引脚就完成了功能的设计。
例如,实现一个简单的视频预览功能,需要向过滤图表中添加一个视频捕捉源过滤器和一个Video Renderer过滤器,将视频捕捉源过滤器的输出引脚与Video Renderer过滤器的输入引脚相连就可以了。
而在程序中只需要按照设计过滤图表的捕捉添加过滤器并连接过滤器引脚就可以了。
在连接过滤器引脚时需要注意:只能是输出过滤器引脚与输入过滤器引脚相连,两个输出过滤器或两个输入过滤器引脚是不能相连的。
2)Filter图表设计为了方便用户设计过滤图表,DirectX提供了一个Graph Edit工具。
位于C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\graphedt.exe。
点击运行。
演示如何使用Graph Edit工具设计过滤图表,过滤图表的功能是实现视频的预览功能。
具体步骤如下:(1)单击“Graph/Insert Filters”菜单项打开“添加过滤器”窗口,选择一个视频捕捉源过滤器。
选择“Video Renderer”最终去向过滤器,连接,如图1。
图2宽屏haali视频分离器单击工具栏中的“>”按钮运行过滤图表,将显示一个视频预览窗口。
3)枚举系统设备使用Graph Edit工具,用户可以非常方便地获得与某一系统设备相关的过滤器。
但是,在程序中该如何获得这些过滤器呢?用户可以采用枚举的方式列举系统中安装的设备。
以列举系统中的视频捕捉设备为例,(1)首先定义一个设备列举接口ICreateDevEnum的一个指针;(2)调用CoCreateInstance方法创建ICreateDevEnum实例。
(3)然后定义一个列举监视器IEnumMoniker的一个指针;(4)调用ICreateDevEnum实例的CreateClassEnumerator方法创建IEnumMoniker实例。
(5)最后以循环的方式调用IEnumMoniker实例的Next方法遍历系统设备;(6)调用IEnumMoniker实例的BindToObject方法将系统设备绑定到过滤器上。
在上面的描述中,ICreateDevEnum实例的CreateClassEnumerator方法的第一个参数确定枚举的系统设备。
例如,第一个参数为CLSID_VideoInputDeviceCategory,表示将要枚举系统中的视频捕捉卡,为CLSID_VideoCompressorCategory,表示枚举系统中的视频压缩器。
下面的代码演示了如何枚举系统中的视频捕捉卡。
//枚举视频设备;值=CLSID_VideoInputDeviceCategory//音频设备的值=CLSID_AudioInputDeviceCategory;ICreateDevEnum*pDevEnum=NULL;CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC,IID_ICreateDevEnum,(void**)&pDevEnum);IEnumMoniker*pClassEnum=NULL;pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pClassEnum,0);ULONG cFetched;while(pClassEnum->Next(1,&pMoniker,&cFetched)==S_OK){pMoniker->BindToObject(0,0,IID_IBaseFilter,(void**)&pSrc);pMoniker->Release();break;}pClassEnum->Release();而下面的代码则用于判断系统中是否安装了指定的视频压缩器。
ICreateDevEnum*pDevEnum=NULL;CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC,IID_ICreateDevEnum,(void**)&pDevEnum);IEnumMoniker*pClassEnum=NULL;//列举视频压缩设备;值=CLSID_VideoCompressorCategorypDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory,&pClassEnum,0);while(pClassEnum->Next(1,&pMoniker,&cFetched)==S_OK){IPropertyBag*pProp=NULL;pMoniker->BindToStorage(0,0,IID_IPropertyBag,(void**)&pProp);VARIANT varName;varName.vt=VT_BSTR;pProp->Read(L"FriendlyName",&varName,0);CString str=varName.bstrVal;if(str.Find("Microsoft Video1",0)!=-1){pMoniker->BindToObject(0,0,IID_IBaseFilter,(void**)&pCompress);pMoniker->Release();break;}VariantClear(&varName);}pClassEnum->Release();4)查找Filter Pin过滤器引脚每一个过滤器(Filter)至少应有一个引脚(Pin),或者是输入引脚或者是输出引脚。