2 DirectShow的系统组成
DirectShow技术是建立在DirectDraw和DirectSound组件基础之上的,它通过DirectDraw对显卡进行控制以显示视频,通过DirectSound对声卡进行控制以播放声音。 DirectShow可提供高质量的多媒体流的捕获和回放功能;支持多种媒体格式,包括ASF(Advanced Systems Format),MPEG(Motion Picture Experts Group),AVI(Audio-Video Interleaved),MP3(MPEG Audio Layer-3)和WAV声音文件;可以从硬件上捕获媒体数据流;可以自动检测并使用视频和音频加速硬件。因此,DirectShow可以充分发挥媒体的性能,提高运行速度,可以简化媒体播放、媒体间的格式转换和媒体捕获等工作。同时,它还具有极大的可扩展性和灵活性,可以由用户自己创建组件,并将这个组件加入DirectShow结构中以支持新的格式或特殊的效果。
应用程序与DirectShow组件以及DirectShow所支持的软硬件之间的关系如图1所示。
图1 DirectShow系统框图
2.1 过滤器(filter)
由图1可以看到,过滤器是DirectShow最基本的组成元件。过滤器是一个COM组件,是完成DirectShow处理过程的基本单元。DirectShow提供了一组标准的过滤器供应用程序使用,程序开发者也可以创建自定义的过滤器来扩充DirectShow的功能,但必须是以COM形式建立的。DirectX为用户提供了DirectShow基类库(DirectShow Base Class Library),用户自定义的过滤器都可以从基类库提供的基类和接口派生出来。
过滤器主要分为以下几种类型:
(1)源过滤器(source filter):源过滤器引入数据到过滤器图表中,数据来源可以是文件、网络、照相机等。不同的源过滤器处理不同类型的数据源。
(2)变换过滤器(transform filter):变换过滤器的工作是获取输入流,处理数据,并生成输出流。变换过滤器对数据的处理包括编解码、格式转换、压缩解压缩等。
(3)提交过滤器(renderer filter):提交过滤器在过滤器图表里处于最后一级,它们接收数据并把数据提交给外设。
(4)分割过滤器(splitter filter):分割过滤器把输入流分割成多个输出。例如,AVI分割过滤器把一个AVI格式的字节流分割成视频流和音频流。
(5)混合过滤器(mux filter):混合过滤器把多个输入组合成一个单独的数据流。例如,AVI混合过滤器把视频流和音频流合成一个AVI格式的字节流。
过滤器的这些分类并不是绝对的,例如一个ASF读过滤器(ASF Reader filter)既是一个源过滤器又是一个分割过滤器。
在DirectShow里,一组过滤器称为一个过滤器图表(filter graph)。过滤器图表用来连接过滤器以控制媒体流,它也可以将数据返回给应用程序,并搜索所支持的过滤器。过滤器有三种可能的状态:运行、停止和暂停。暂停是一种中间状态,停止状态到运行状态必定经过暂停状态。暂停可以理解为数据就绪状态,是为了快速切换到运行状态而设计的。在暂停状态下,数据线程是启动的,但被提交过滤器阻塞了。通常情况下,过滤器图表中所有过滤器的状态是一致的。
2.2 引脚(pin)
过滤器可以和一个或多个过滤器相连,连接的接口也是COM形式的,称为引脚。过滤器利用引脚在各个过滤器间传输数据。每个引脚都是从Ipin这个COM对象派生出来的。每个引脚都是过滤器的私有对象,过滤器可以动态的创建引脚,销毁引脚,自由控制引脚的生存时间。引脚可以分为输入引脚(Input pin)和输出引脚(Output pin)两种类型,两个相连的引脚必须是不同种类的,即输入引脚只能和输出引脚相连,且连接的方向总是从输出引脚指向输入引脚。
过滤器之间的连接(也就是引脚之间的连接),实际上是连接双方媒体类型(Media Type)协商的过程。连接的大致过程为:如果调用连接函数时已经指定了完整的媒体类型,则用这个媒体类型进行连接,成功与否都结束连接过程;如果没有指定或不完全指定了媒体类型,则进入下面的枚举过程--枚举欲连接的输入引脚上所有的媒体类型,逐一用这些媒体类型与输出引脚进行连接(如果连接函数提供了不完全媒体类型,则要先将每个枚举出来的媒体类型与它进行匹配检查),如果输出引脚也接受这种媒体类型,则引脚之间的连接宣告成功;如果所有输入引脚上枚举的媒体类型,输出引脚都不支持,则枚举输出引脚上的所有媒体类型,并逐一用这些媒体类型与输入引脚进行连接,如果输入引脚接受其中的一种媒体类型,则引脚之间的连接宣告成功;如果输出引脚上的所有媒体类型,输入引脚都不支持,则这两个引脚之间的连接过程宣告失败。过滤器与引脚连接如图2所示。
图2 过滤器和引脚连接示意图
2.3 媒体类型(Media Type)
媒体类型是描述数字媒体格式的一种通用的可扩展方式。两个过滤器相连时,必须使用一致的媒体类型,否则这两个过滤器就不能相连。媒体类型能识别上一级过滤器传送给下一级过滤器的数据类型,并对数据进行分类。
实际在很多应用程序中,用户根本不需要担心媒体类型的问题,DirectShow会处理好所有的细节。但有些应用程序需要对媒体类型进行操作。媒体类型一般可以有两种表示:AM_MEDIA_TYPE和CMediaType。前者是一个结构,后者是从这个结构继承过来的类。
每个AM_MEDIA_TYPE由三部分组成:Major type、Subtype和Format type。这三个部分都使用GUID(全局唯一标识符)来唯一标示。Major type主要定性描述一种媒体类型,这种媒体类型可以是视频、音频、比特数据流或MIDI数据等等;Subtype进一步细化媒体类型,如果是视频的话可以进一步指定是RGB-24,还是RGB-32,或是UYVY等等;Format type则用一个结构更进一步细化媒体类型。
如果媒体类型的三个部分都指定了某个具体的GUID值,则称这个媒体类型是完全指定的;如果媒体类型的三个部分中有任何一个值是GUID_NULL,则称这个媒体类型是不完全指定的。GUID_NULL具有通配符的作用。
2.4 过滤器图表管理器(Filter Graph Manager)
DirectShow通过过滤器图表管理器来控制过滤器图表中的过滤器。过滤器图表管理器是COM 形式的,它的功能有:协调过滤器间的状态转变;建立参考时钟;把事件(event)传送给应用程序;为应用程序提供建立过滤器图表的方法。
一些常用的过滤器图表管理器接口如下:
IGraphBuilder:为应用程序提供创建过滤器图表的方法。
IMediaControl:提供控制过滤器图表中多媒体数据流的方法,包括运行、暂停和停止。IMediaEventEx:继承自IMediaEvent接口,处理过滤器图表的事件。
IVideoWindow:用于设置多媒体播放器窗口的属性,应用程序可以用它来设置窗口的所有者、位置和尺寸等属性。
IBasicAudio:用于控制音频流的音量和平衡。
IBasicVideo:用于设置视频特性,如视频显示的目的区域和源区域。
IMediaSeeking:提供搜索数据流位置和设置播放速率的方法。
IMediaPosition:用于寻找数据流的位置。
IVideoFrameStep:用于步进播放视频流,可使DirectShow应用程序,包括DVD播放器一次只播放一帧视频。
2.5 过滤器图表中的数据流动
当用户要创建自定义的过滤器时,就需要了解媒体数据是如何在过滤器图表中传输的。为了在过滤器图表中传送媒体数据,DirectShow过滤器需要支持一些协议,称之为传输协议(transport)。相连的过滤器必须支持同样的传输协议,否则不能交换媒体数据。
大多数的DirectShow过滤器把媒体数据保存在主存储器中,并通过引脚把数据提交给其它的过滤器,这种传输称为局部存储器传输(local memory transport)。虽然局部存储器传输在DirectShow中最常用,但并不是所有的过滤器都使用它。例如,有些过滤器通过硬件传送媒体数据,引脚只是用来提交控制信息,如IOverlay接口。
DirectShow为局部存储器传输定义了两种机制:推模式(push model)和拉模式(pull model)。在推模式中,源过滤器生成数据并提交给下一级过滤器。下一级过滤器被动的接收数据,完成处理后再传送给再下一级过滤器。在拉模式中,源过滤器与一个分析过滤器相连。分析过滤器向源过滤器请求数据后,源过滤器才传送数据以响应请求。推模式使用的是IMemInputPin接口,拉模式使用IAsyncReader接口,推模式比拉模式要更常用。