基于DirectShow的多媒体流捕获

时间:2022-06-20 10:20:57

基于DirectShow的多媒体流捕获

随着计算机网络和多媒体技术的发展,多媒体应用如视频会议、远程监控、远程教育、可视电话、医疗视频会诊等迅速兴起,视频和音频捕获成为多媒体应用中的关键环节和重要前提。目前采用较多的基于设备软件开发工具箱(SDK)的捕获方式存在成本较高、灵活性和扩展性较差等问题,难以满足用户需求和网络环境的变化。微软公司推出的多媒体开发软件包―――DirectShow成为解决这些问题的一个有力工具。

DirectShow提供高质量的多媒体数据流的捕获和回放功能,广泛支持多种媒体格式,包括ASF、MPEG、AVI、DV、MP3和WAV等。同时DirectShow对VFW具有良好的兼容性,并具有其无法比拟的优势,包括支持大量多媒体数据捕获的同时可通过网络传播和播放,支持视频与音频在捕获和播放中的完全同步,支持来自不同媒体源数据捕获的合成等。本文着重介绍如何利用Visual C++实现基于DirectShow的视频和音频捕获以及其中涉及到的关键问题,以供工程人员和开发人员参考使用。

DirectShow的原理

1、DirectShow的体系结构。

应用程序与DirectShow组件以及DirectShow所支持的软硬件之间的关系如图1所示。DirectShow使用模块化的架构,系统中的基础模块称为过滤器(Filter)。过滤器作为软件的组件,可完成单一的数据流处理功能。按照功能,过滤器大致分为3类:源过滤器(Source Filter)、转换过滤器(Transform Filter)和表现过滤器(Rendering Filter)。源过滤器负责从媒体源获取数据;转换过滤器负责数据的格式转换、传输,如数据流分离/合成、编码/解码等;表现过滤器负责数据的最终去向,将数据送往显卡和声卡进行播放,或输出到文件进行存储。

过滤器之间通过引脚(Pin)进行有序连接,组合而成过滤器图(Filter Graph),用以实现组合的一系列功能。应用程序创建过滤器图管理器(Filter Graph Manager),负责过滤器图的组织和连接功能并控制数据在其中的流动。

为了提高系统的稳定性,Windows操作系统对硬件操作进行了隔离;应用程序一般不能直接访问硬件。过滤器工作在用户模式(User mode,操作系统特权级别为Ring 3),而硬件工作在内核模式(Kernel mode,操作系统特权级别为Ring 0)。

2、DirectShow的开发方法。

开发DirectShow应用程序,主要有以下三个基本步骤:

(1)调用CoCreateInstance函数,创建一个过滤器图管理器组件;

(2)根据项目实际需求,构建一条完整的过滤器链路(也可应用其它的DirectShow帮助组件来完成过滤器图的构建);

(3)调用过滤器图管理器上的接口方法来控制过滤器图,并完成过滤器图管理器与应用程序的事件交互。

DirectShow技术建立在COM(Component Object Model)技术基础上,所有部件和功能都可由COM接口来构建和实现。过滤器图管理器的重要COM接口包括:

IGraphBuilder:用于创建过滤器图。

IMediaControl:用于控制媒体流在过滤器图中的传输。

IMediaEventEx:用于控制过滤器图的事件。

IVideoWindow:用于设置多媒体播放窗口的属性。

IBasicAudio:用于控制音频特性。

IBasicAudio:用于控制视频特性。

IMediaPosition:用于查找和定位数据流。

IPin:用于管理两个过滤器之间的引脚,从而连接过滤器。

另外,由于直接使用IGraphBuilder接口构建视频和音频捕获过滤器图比较复杂,DirectShow提供了辅助组件―――捕获图构建器(Capture Graph Builder),通过调用其IcaptureGraphBuilder2的接口方法,可以简便地完成过滤器图的构建和控制。

基于DirectShow视频和音频捕获的实现

1、编译环境的设置。

安装Microsoft DirectX SDK后,需要设置VC编译环境。包括:

(1)在VC系统目录中添加DirectX SDK的Include和Lib目录;

(2)创建工程,选择Win32动态库;

(3)选择_stdcall函数调用协议;

(4)添加已编译基类源代码生成的库Strmbase.lib(版)或Strmbasd.lib(调试版)。

2、 过滤器图的构建设计。

捕获系统需要实现的功能:从视频采集设备和音频采集设备实时获取数据流,预览视频和监听音频,并将视频流与音频流合成后存储。设计如图2所示的过滤器图,各个过滤器组件功能:Video Capture和Audio Capture分别负责实时捕获视频和音频;Video Renderer将视频流送往显卡进行视频预览;Smart Tee负责音频流的分流;AVI Muxer将视频流与音频流合成AVI流,File Writer将合成后数据存储在硬盘;Audio Renderer将数据送往声卡进行音频播放。

需要说明的是,一般视频捕获器提供有预览和捕获两个输出引脚,而音频捕获器只有捕获输出引脚。对于只有捕获输出引脚的视频捕获器也可使用插入Smart Tee的方法实现数据分流。

3、程序实现。

在这一部分,分析和说明捕获功能的实现步骤,并给出核心代码:

(1) 创建过滤器图管理器组件。

CoInitialize(NULL); //初始化COM库

//创建过滤器图管理器

IGraphBuilder *pGraphBuilder;

CoCreateInstance(CLSID_FilterGraph, NULL,

CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraphBuilder);

//创建捕获图构建器

ICaptureGraphBuilder2 *pCapGraphBuilder;

CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,

CLSCTX_INPROC_SERVER,IID_ICaptureGraphBuilder2,(void**)&pCapGraphBuilder);

pCapGraphBuilder->SetFiltergraph(pGraphBuilder); //添加捕获图构建器到管理器中

//获得有用接口

IMediaControl *pControl;

IMediaEventEx *pEventEx;

pGraphBuilder->QueryInterface(IID_IMediaControl,(void **)&pControl);

pGraphBuilder->QueryInterface(IID_ImediaEventEx,(void **)&pEventEx);

(2)创建捕获过滤器。

//枚举采集设备

ICreateDevEnum *pCreateDevEnum = NULL;

CoCreateInstance(CLSID_ SystemDeviceEnum, NULL,

CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pCreateDevEnum); //创建设备枚举器

IEnumMoniker *pVideoEnumMoniker = NULL;

pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,

&pVideoEnumMoniker, 0); //指定类型目录

/ * 以枚举视频设备为例。枚举音频设备与此类似,代表音频采集的过滤器注册为CLSID_AudioInputDeviceCategory 类型 */

IMoniker *pVideoMoniker = NULL;

IPropertyBag *pVideoPropBag;

pVideoMoniker->BindToStorage(0, 0, IID_IPropertyBag,

(void**)(&pVideoPropBag)); //枚举设备标识

VARIANT varVideoName;

VariantInit(&varVideoName);

pVideoPropBag->Read(L"VideoFriendName", &varVideoName, 0); //取得设备的友好名称

//创建Video Capture过滤器

IBaseFilter *pVideoCap;

pVideoMoniker ->BindToObject(0,0,IID_IbaseFilter,(void **)&pVideoCap);

//添加Video Capture过滤器到过滤器图

pGraphBuilder->AddFilter(pVideoCap,L"Video Capture Filter");

(3) 构建其它过滤器,并加入过滤器图。

/* ICaptureGraphBuilder2提供了RenderStream函数,可以自动构建Smart Tee和Renderer过滤器,并将它们连接成一个完整的过滤器图。如果Capture过滤器既有预览引脚又有捕获引脚,那么RenderStream将两个引脚和Render过滤器连接;如果Caprture过滤器只有捕获引脚,那么捕获图构建器自动插入Smart Tee过滤器将视频流或音频流分流,并完成过滤器之间的连接。*/

//构建视频预览的过滤器链路

IBaseFilter *pVideoCap; //

pCapGraphBuilder->RenderStream

(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,pVideoCap, NULL, NULL);

//构建音频监听的过滤器链路

IBaseFilter *pAudioCap;

pCapGraphBuilder->RenderStream

(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio,pAudioCap, NULL, NULL);

//构建视音频合成并保存文件过滤器链路

/* SetOutputFileName函数会自动创建AVI Muxer过滤器和File Writer过滤器,并且将这两个过滤器添加到过滤器图中。*/

IBaseFilter *pMux;

pCapGraphBuilder->SetOutputFileName

(&MEDIASUBTYPE_Avi,L"C:\\Capture.avi",&pMux, NULL);

//连接捕获器和AVI Muxer过滤器

pCapGraphBuilder->RenderStream

(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pVideoCap, NULL, pMux);

pCapGraphBuilder->RenderStream

(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, pAudioCap, NULL, pMux);

//设置音频流为主流

IConfigAviMux *pConfigAviMux;

pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigAviMux);

pConfigAviMux->SetMasterStream(1);

(4)控制过滤器图

pControl->Run();//开始捕获

pControl->Pause();//暂停

pControl->Stop();//停止捕获

结束语

DirectShow提供了开放式的开发环境,模块化的管理结构,及对媒体格式和硬件的广泛支持,使得在Windows平台上捕获和处理多媒体数据流变得简单而高效。本文探讨了利用VC++基于DirectShow捕获多媒体数据流的实现方法,为此方法基础上实现的流媒体捕获系统成本较低,捕获质量良好,解决了基于设备SDK和VFW的捕获方式中存在的硬件通用性差、不易实现功能修改和扩展等问题,此方法也为后续的流媒体处理研究和实现提供了有益的参考,在多媒体应用开发方面具有广阔的前景。

上一篇:的联谊会怎么开 下一篇:卫星宽带与多媒体业务