【B2B研发商城】 【加入收藏】 【设为首页】 【进入论坛】 【站点地图】

你的位置:中国研发网 >> 专题频道 >> 机器视觉 >> 详细内容 在线投稿

基于Dirctshow的视频采集完整方案设计附源码

排行榜 收藏 打印 发给朋友 举报 来源: 互联网   发布者:未知
热度67票  浏览383次 【共0条评论】【我要评论 时间:2009年11月17日 15:41
说起视频捕捉问题,我们先要来看一下视频捕捉卡。根据使用的驱动程序的不同来分类,目前市场上大致有两种捕捉卡:VFW (Video for Windows)卡和WDM (Windows Driver Model)卡。前者是一种趋于废弃的驱动模型,而后者是前者的替代模型;WDM还支持更多新的特性,比如直接支持电视接收、视频会议、1394接口的设备、桌面摄像机、多条视频流(Line-21或Closed-Caption等)同时输出等等。采用VFW的一般都是些以前生产的卡;市面上新出现的,一般都是采用了WDM驱动程序。另外,视频捕捉卡的接口,可以是以PCI或AGP的方式插入PC机箱,也可以直接以USB接口的方式外挂;还有就是通过1394接口与PC机相连的数码摄像机等等。

二、vfw视频采集

FW是微软公司1992年推出的关于数字视频的一个软件包,它能使应用程序通过数字化设备从传统的模拟视频源得到数字化的视频剪辑。VFW的一个关键思想是播放时不需要专用硬件,为了解决数字视频数据量大的问题,需要对数据进行压缩。它引进了一种叫AVI的文件标准,该标准未规定如何对视频进行捕获、压缩及播放,仅规定视频和音频该如何存储在硬盘上,以及在AVI文件中交替存储视频帧和与之相匹配的音频数据。VFW使程序员能通过发送消息或设置属性来捕获、播放和编辑视频剪辑。在Windows   9x系统中,当用户在安装VFW时,安装程序会自动地安装配置视频所需要的组件,如设备驱动程序、视频压缩程序等。     

 VFW主要由以下6个模块组成:     

 ●AVICAP.DLL:包含执行视频捕获的函数,它给AVI文件的I/O处理和视频、音频设备驱动程序提供一个高级接口;     

 ●MSVIDEO.DLL:包含一套特殊的DrawDib函数,用来处理屏幕上的视频操作;     

 ●MCIAVI.DRV:包括对VFW的MCI命令解释器的驱动程序;     

 ●AVIFILE.DLL:包含由标准多媒体I/O(mmio)函数提供的更高的命令,用来访问.AVI文件;     

 ●压缩管理器(ICM):用于管理的视频压缩/解压缩的编译码器(Codec);     

 ●音频压缩管理器ACM:提供与ICM相似的服务,适用于波形音频。     

 开发步骤   

 AVICap窗口类支持实时的视频流捕获和单帧捕获,并提供对视频源的控制。虽然MCI也提供数字视频服务(比如它为显示.AVI文件的视频提供了AVI   VIDEO命令集),为视频叠加提供了Overlay命令集,但这些命令主要是基于文件的操作,它们不能满足实时地从视频缓存中取数据的要求,   对于使用没有视频叠加能力的捕获卡的PC机来说,   用MCI提供的命令集是无法捕获视频流的。而AVICap窗口类在捕获视频方面具有一定的优势,它能直接访问视频缓冲区,不需要生成中间文件,实时性很强,效率很高。而且,它还可将数字视频捕获到一个文件中。     

 1.创建“捕获窗”   

 在进行视频捕获之前必需要先创建一个“捕获窗”,并以它为基础进行所有的捕获及设置操作。“捕获窗”用AVICap窗口类的“CapCreateCaptureWindow”函数来创建,其窗口风格一般为WS_CHILD和WS_VISIBLE。   

 捕获窗类似于标准控件(如按钮、列表框等),并具有下列功能:     

 ●将视频流和音频流捕获到一个AVI文件中;     

 ●动态地同视频和音频输入器件连接或断开;     

 ●以Overlay或Preview模式对输入的视频流进行实时显示;     

 ●在捕获时,可指定所用的文件名并能将捕获文件的内容拷贝到另一个文件;     

 ●设置捕获速率;     

 ●显示控制视频源、视频格式、视频压缩的对话框;     

 ●创建、保存或载入调色板;     

 ●将图像和相关的调色板拷贝到剪贴板;     

 ●将捕获的单帧图像保存为DIB格式的文件。     

 2.关联捕获窗和驱动程序   

 单独定义的一个捕获窗是不能工作的,它必需与一个设备相关联,这样才能取得视频信号。用函数CapDriverConnect可使一个捕获窗与一个设备驱动程序相关联。   

 3.设置视频设备的属性   

 通过设置TcaptureParms结构变量的各个成员变量,可以控制设备的采样频率、中断采样按键、状态行为等等。设置好TCaptureParms结构变量后,可以用函数CapCaptureSetSetup使设置生效。之后还可以用CapPreviewScale、CapPreviewRate来设置预览的比例与速度,也可以直接使用设备的默认值。   

 4.打开预览   

 利用函数CapOverlay选择是否采用叠加模式预览,这样占用系统资源小,并且视频显示速度快。然后用CapPreview启动预览功能,这时就可以在屏幕上看到来自摄像机的图像了。   

 通过以上4步就可以建立一个基本的视频捕获程序。但如果想自已处理从设备捕获到的视频数据,则要使用捕获窗回调函数来处理,比如一帧一帧地获得视频数据或以流的方式获得视频数据等等。

三、directshow视频采集:

使用DirectShow来处理一般的视频捕捉问题,是相对比较简单的。这当然得益于DirectShow这一整套先进的应用架构。捕捉卡通常也是以一个(Capture) Filter的形式出现的。处理视频捕捉,我们同样是使用Filter Graph,同样是操作Filter;控制起来,就似于操作媒体文件的播放。

 当视频捕捉卡正确安装到系统中后,使用GraphEdit插入Filter,我们可以在“Video Capture Sources”目录下看到代表捕捉卡的那个Filter。一般一个Capture Filter至少有一个Capture Output Pin;典型的情况下,还有一个Preview Pin或者Video Port Pin(一般Preview Pin和VP Pin不会共存)。有些视频捕捉卡,能够同时捕捉Video和Audio,那么它的Filter自然还应该有Audio部分的输出Pin。视频捕捉卡都注册在CLSID_VideoInputDeviceCategory目录之下;要知道系统中安装了哪些捕捉卡,需要利用系统枚举,如下:

 

ICreateDevEnum *pDevEnum = NULL;

IEnumMoniker *pEnum = NULL;

// Create the System Device Enumerator.

HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,

CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,

reinterpret_cast<void**>(&pDevEnum));

if (SUCCEEDED(hr))

{

// Create an enumerator for the video capture category.

hr = pDevEnum->CreateClassEnumerator(

CLSID_VideoInputDeviceCategory, &pEnum, 0);

}

  Capture Filter的创建也不是象其他Filter一样使用CoCreateInstance,而是在枚举的过程中BindToObject。在这一点上,对WDM卡和VFW卡的处理是一致的。

 

  将Capture Filter加入Filter Graph之后,剩下的Filter怎么连接?DirectShow给我们提供了一个简单的解决方法:使用ICaptureGraphBuilder2接口。如下创建:

 

IGraphBuilder *pGraph = 0;

ICaptureGraphBuilder2 *pBuild = 0;

// Create the Capture Graph Builder.

HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, 0,

CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,

(void**)&pGraph);

if (SUCCEEDED(hr))

{

// Create the Filter Graph Manager.

hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,

IID_IGraphBuilder, (void**)&pGraph);

if (SUCCEEDED(hr))

{

// Initialize the Capture Graph Builder.

pBuild->SetFiltergraph(pGraph);

}

}

  接下来,就是使用ICaptureGraphBuilder2::RenderStream来继续各个Output Pin的连接。值得注意的是,这里有一个Pin Category的概念,作为RenderStream的第一个参数,比如Preview Pin的目录为PIN_CATEGORY_PREVIEW,Capture Pin的目录为PIN_CATEGORY_CAPTURE等等。下面是Preview Pin的连接示例:

 

ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder

// Initialize pBuild (not shown).

IBaseFilter *pCap; // Video capture filter.

/* Initialize pCap and add it to the filter graph (not shown). */

hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,

pCap, NULL, NULL);

  调用RenderStream实现Preview链路,不管Capture Filter是否有Preview Pin或者只有VP Pin,Capture Graph Builder都能自动正确地处理。(如果只有VP Pin,则自动连接VP Pin;如果Capture Filter只有一个Capture Output Pin,则自动插入一个Smart Tee Filter然后再连接。)

三层交换技术交换机与路由器密码恢复交换机的选购路由器设置专题路由故障处理手册数字化校园网解决方案

要实现视频捕捉到文件,最简单的方法也是使用ICaptureGraphBuilder2::RenderStream。如下(假设生成的是AVI文件):

 

IBaseFilter *pMux;

hr = pBuild->SetOutputFileName(

&MEDIASUBTYPE_Avi, // Specifies AVI for the target file.

L"C:\\Example.avi", // File name.

&pMux, // Receives a pointer to the mux.

NULL);

hr = pBuild->RenderStream(

&PIN_CATEGORY_CAPTURE, // Pin category.

&MEDIATYPE_Video, // Media type.

pCap, // Capture filter.

NULL, // Intermediate filter (optional).

pMux); // Mux or file sink filter

使用Capture Graph Builder构建Filter链路的好处,还在于它能自动加入Crossbar Filter(用于选择捕捉卡的输入端子,一般有三种:AV、S-Video、TV),如果是电视卡的话还有TV Tuner Filter等等;使用ICaptureGraphBuilder2::FindInterface就可以找到相应的控制接口等等。

本站所有文章欢迎任何形式的转载,但请注明作者及出处,尊重他人劳动成果!
文章转载自:中国研发网 [http://www.yanfaw.com]
本文标题:基于Dirctshow的视频采集完整方案设计附源码
TAG: 方案 源码 视频 采集 Dirctshow
顶:4 踩:4
对本文中的事件或人物打分:
当前平均分:0.89 (19次打分)
对本篇资讯内容的质量打分:
当前平均分:-0.7 (23次打分)
【已经有17人表态】
2票
感动
3票
路过
2票
高兴
2票
难过
3票
搞笑
2票
愤怒
1票
无聊
2票
同情
上一篇 下一篇
发表评论

网友评论仅供网友表达个人看法,并不表明本网同意其观点或证实其描述。

查看全部回复【已有0位网友发表了看法】