-- 作者:admin -- 发布时间:2005-11-30 12:13:00 -- DirectShow系统综述 多媒体的挑战 使用多媒体会出现以下主要的挑战 1 多媒体包含了大量的需要快速处理的数据。 DirectShow提供的解决办法 DirectShow被设计来解决以上的挑战。主要的设计目的是通过将应用程序与数据传输,硬件区别以及同步等复杂过程分隔开来从而简化在微软平台创建数字媒体应用程序的任务。 如图所示,DirectShow滤波器可以与很多硬件通讯并控制它们,包括当地文件系统,TV调谐器,视频捕获卡, VFM编解码器,视频显示器(通过DirectShow和图形设备接口(GDI)),以及声卡(通过DirectSound)。这样DirectShow就将应用程序与设备的复杂事物隔离开来。DirectShow对于一定格式的文件也提供自带的压缩,解压滤波器。 过滤器图形及其组件 这篇文章描述了DirectShow的主要组件。可以作为应用程序及定制DirectShow滤波器的开发人员的介绍性文档。应用程序开发人员通常可以不理会DirectShow中许多底层的细节。然而,为了全面理解DirectShow的结构,阅读这一章也是一个不错的想法。 关于DirectShow滤波器 DirectShow使用模组结构,处理的每一个阶段都通过一个叫滤波器的COM组件来完成。DirectShow为应用程序提供了一套标准的滤波器,开发人员定制自己的滤波器来扩展DirectShow。这里有几个步骤来播放AVI视频文件,每一步都是通过滤波器来完成。 1 从字节流文件中读取原始数据(文件源滤波器-File Source Filter) 如图所示,每一个滤波器与一个或多个其它的滤波器相连。而连接点也是COM对象,叫做针(pin)。滤波器使用针从一个滤波器向另外一个移动数据。图形中的箭头显示了数据传输的方向。在DirectShow中,滤波器集合为称作滤波器图形。 滤波器有三个可能的状态:运行,停止和暂停。当滤波器运行的时候,它可以处理数据。当停止时,它停止处理数据。暂停状态用来在运行前提示数据。Data Flow in the Filter Graph部分详细描述的这个概念。大多数情况下,整个过滤器图形(Filter Graph)中的状态变化是同等的。图形中的过滤器统一调整状态。这样,整个滤波器图形也可以被称作运行,停止或暂停。 滤波器可以被分为以下几个比较大的类别: 这几个类别间的区别不是绝对的。比如,ASF读滤波器就可以同时扮演Source Filter和Splitter Filter的角色。 关于滤波器图形管理器 滤波器图形管理器(Filter Graph Manager)是一个在滤波器图形中控制滤波器的组件,它执行了许多包括下面的函数: 这里简要地介绍一下这些函数。详细内容可以在本文档的其他部分获得。 状态变化(State Changes)。滤波器间状态变化必须以一定的次序发生。因此,应用程序并不直接发送状态变化命令给滤波器。而是给滤波器图形管理器发送一个命令,管理器在将这个命令发送个滤波器。查询工作也有类似的方式:应用程序发送查询命令给管理器,管理器再把它发送给滤波器。 注意 关于媒体类型 由于DirectShow是一个模组,因此它需要在滤波器图形的每一点通过一种方式来描述数据的格式。比如,考虑AVI的播放。数据以大块重复流(Stream of RIFF Chunks)的形式进入图形。它们被解析成视频和音频。视频流由可能被压缩的视频桢组成,解码后,视频流成为一系列解压得位图(Bitmaps)。音频也进行了同样过程的处理。 媒体类型:DirectShow如何表现格式 媒体类型是用来描述数字媒体格式的一个普遍的可扩展的方法。当两个滤波器连起来的时候他们对于一种媒体类型达成一致。媒体类型用来识别上流(Upstream)滤波器将什么样的数据类型传递给了下流(Downstream)滤波器,以及数据的物理布局(layout)。如果两个滤波器不能在媒体类型上取得一致,他们就不能被连接。
1 主类(Major type)主类是一个GUID(Global unique identifier),它定义了全部的数据类别。主要类型包括视频,音频, 未解析字节流, MIDI数据等等。 2 子类(Subtype)子类是另外一个GUID,用来进一步定义格式。比如,在视频主类中,存在子类, RGB-24, RGB-32, UYVY等等。在音频中,有PCM音频,MPEG-1有效载荷(Playload)等等子类。子类比主类提供更多的信息,但是它没有对于格式的每个方面都进行了定义。比如,视频子类没有定义图像的尺寸或者桢频率(Frame Rate)。它们由下面描述的格式模块来定义。 3 格式模块(Format Block)格式模块是一个数据模块,用它来详细地描述格式。格式模块与AM_MEDIA_TYPE结构是分开的,结构中的pbFormat成员指向格式模块。 pbFormat被声明为void*,这是因为格式模块布局的改变依赖媒体类型。比如,PCM音频使用WAVEFORMATEX结构。视频使用各种结构,包括VIDEOINFOHEADER和VIDEOINFOHEADER2。AM_MEDIA_TYPE中的formattype成员是一个指定在格式模块中上述哪一个结构被包含的GUID。每一个格式模块指定一个GUID。cbFormat成员指定了块的尺寸。通常在废弃pbFormat指针之前要检查这些值。 如果这个块被填充,那么主类和子类就包含了多余的信息。然而,主类和子类可以在格式模块不完整的情况下提供一个便利的方法识别格式。比如,你可以指定一个普通的24位RGB格式(MEDIASUBTYPE_RGB24),而不需要知道通过VIDEOINFOHEADER所得到的全部信息,比如尺寸和桢频率。
AM_MEDIA_TYPE结构也包含一些可选的领域。它们用来提供附加信息,但是滤波器并不需要使用它们。 1 ISampleSize 如果这项非零,它定义了每一个样本的尺寸。如果等于零,表示每个样本的尺寸可以改变。 关于媒体样本和分配符 滤波器通过针(pin)连接传送数据。数据从输出针流往另一个滤波器的输入针。对于输出针传送数据最一般的方法是在输入针上调用IMemInputPin::Receive方法。尽管也存在其它的机制。 Media Sample包括 1 一个指向正在使用的缓冲的指针 时间戳定义了表示时间,描画滤波器用它来规划描画。标记用来表示一些情况,比如从前一个样本开始,数据中是否有中断。媒体类型为滤波器提供了一种方法去改变中流格式。通常样本没有媒体类型,它意味着从上一个样本开始,格式没有改变。 硬件设备如何参与滤波器图形 这篇文档描述了微软的DirectShow如何与音频和视频硬件交互作用。 包装滤波器(Wrapper Filter) 对于应用程序开发人员,包装滤波器使得应用程序像对DirectShow滤波器那样控制设备。不需要特别的编写程序;与核心模式设备通信的细节被这个滤波器封装了起来。 Video For Windows设备 音频捕获和混频设备(声卡) WDM流设备 为了支持WDM流设备,DirectShow提供Ksproxy滤波器(ksproxy.ax)。KsProxy一直被叫做瑞士军刀ss Army Knife)滤波器,因为它可以有很多不同的用途。滤波器上针的数目,以及滤波器提供的COM接口数目完全依靠运行的驱动的性能。KsProxy并不以KsProxy在滤波器图形中出现,而是采用一个更友好的设备名,被写在注册表中。浏览你系统中的WDM设备,运行GraphEdit并且从WDM流设备中选择。尽管在你的系统中仅仅有一个WDM卡,这个卡可能包含多个设备。每一个设备被描述成一个单独的滤波器,并且每一个滤波器实际上是一个KsProxy。 应用程序使用系统设备计数器(System Device Enumerator)在系统中查找WDM设备名称。KsProxy通过调用名称上的BindToObject初始化。由于KsProxy能够描述所有WDM设备,它必须查询驱动程序以决定驱动支持哪些特性集合。特性集合是WDM驱动和一些用户模式滤波器比如MPEG-2软件解码器,所使用的数据结构集。KsProxy配置自己并提供COM接口来对应那些特性集合。KsProxy将COM方法调用解释成特性集合并且将它们送给驱动程序。硬件供应商可以通过提供plug-ins 扩展KsProxy,通过提供应商指定界面提供特殊的设备性能。所有这些细节对于应用程序不可见。应用程序像对其他DirectShow一样通过KsProxy控制设备。 核心流 构建滤波器图形 The Filter Graph and Its Components文档描述了DirectShow滤波器图形各个基本的模块。这部分介绍了各个模块是如何被创建和被连接从而完成处理数据功能的。 图形构建组件 DirectShow提供了几个可以构建滤波器图形的组件。包括: 智能连接 智能连接这个概念包含了滤波器图形管理器用来构建全部或部分滤波器图形所采用的一套算法。当滤波器图形管理器需要附加的滤波器来完成图形的时候,它大体上需要做以下一些工作: 图形构建概述 为了创建一个滤波器图形,首先要创建一个滤波器图形管理器的实例。
滤波器管理器提供了一下的图形构建方法: 1 IFilterGraph::ConnectDirect试图在两个针之间进行直接连接。如果不能连接,方法实效。 这些方法提供了构建图形的3个基本方法 1 滤波器图形管理器构建整个图形。 滤波器图形管理器构建整个图形 为了构建图形的其他部分,滤波器图形管理器使用迭代模式—在输出针上取得滤波器支持的媒体类型,然后在注册表中搜索可将此媒体类型作为输入的滤波器,它采用以下几个标准来缩小搜索范围和为滤波器排优先级。 滤波器图形管理器使用Filter Mapper对象来搜索注册表当每个滤波器被添加的时候,滤波器图形管理器试图将它连接到前一个滤波器的输出针上。滤波器间协调决定可否连接,如果可以,可以使用哪一种媒体类型,如果新的滤波器不能连接。滤波器图形管理器将抛弃它,并且尝试另外的滤波器。继续这个过程指导每一个流被表现出来。 滤波器图形管理器构建部分图形 除了简单的播放一个文件,你的应用程序必须至少做一些图形构建的工作。比如一个视频捕获程序必须选择一个捕获源滤波器并且将它添加到图形中。如果你要将数据写入AVI文件,你必须将AVI Mux和File Writter滤波器添加到图形中。然而,也可能使用滤波器图形管理器完成图形。比如,你可以通过调用Render方法来表现一个preview针。 应用程序构建整个图形 在一些情况下,你的应用程序也许需要通过添加连接每一个滤波器来完成图形构建。在这种情况下。你也许应该明确的指导哪一个滤波器应该被添加到图形中。用这种方法,应用程序通过调用AddFilter,添加每一个滤波器,列举滤波器上的每一个针,并且通过调用Connect或者ConnectDirect来连接它们。 智能连接 智能连接是滤波器图形管理器用来构建图形的一种机制。它由几种用来选择滤波器并且将他们添加到滤波器图形中的相关算法组成。对于应用程序编程,你几乎不需了解智能连接的细节。但是如果你在构建一个滤波器图形时遇到困难并想解决问题,或者你正在自己写滤波器并想使它用于自动图形构建,你需要阅读这一节。 智能连接包括以下IGraphBuilder方法 IGraphBuilder::Render Render方法构建了图形的子部分。它开始于未连接的输出针并且向下工作,在必要的时候,增加滤波器。开始滤波器必须已经存在于图形中。在每一步,Render方法搜索一个可以与前一个滤波器相连接的滤波器。如果连接的滤波器有多个输出针,那么流可以分叉。如果每一个流都拥有了Renderer那么搜索停止。如果Render方法失效,它会返回并使用另外一套滤波器重试。 1. 如果针支持IStreamBuilder接口,滤波器图形管理器将整个过程交给IStreamBuilder::Render方法处理。通过提供这个接口,针将承担起构建图形剩余部分直到Renderer的责任。然而,很少有针支持这个接口。 每一个滤波器都用一个merit值注册,一个数值表明了一个滤波器对于其他滤波器的优先级别。EnumMatchingFilters方法按merit顺序返回滤波器,最小的值是MERIT_DO_NOT_USE+1。它忽略merit值小于等于MERIT_DO_NOT_USE的滤波器。滤波器也被分为几个类别,由GUID定义。类别本身也有merit,EnumMatchingFilters方法忽略merit值小于等于MERIT_DO_NOT_USE的类别,尽管其中的滤波器可能有比较高的merit值。 总而言之,Render方法按一下次序尝试滤波器。 滤波器图形中的数据流 这一部分描述了媒体数据在滤波器图形中如何移动。通常,写DirectShow应用程序时,你不需要了解这些细节。尽管在一些情况下,你会发现这对你很有用。如果你正在写DirectShow滤波器,你需要了解这部分的材料。 传输(Transports) 为了移动媒体数据通过图形,DirectShow滤波器必须支持一些可能的协议。这些协议叫做传输。当两个滤波器相连时,他们必须支持同一个传输。否则就不能交换媒体数据。通常,一个传输需要其中的一个针支持一个特殊的接口。当滤波器连接的时候,一个针向另外一个查询接口。 大多数DirectShow滤波器在主内存中装纳媒体数据,并且通过针将它们传送到另外一个滤波器。这种传输叫做局部存储传输。尽管局部存储传输是DirectShow中最常用的一种传输方式,并不是所有的滤波器都使用它。比如,一些滤波器沿着硬件途径传送数据,仅仅使用针来传输控制信息。比如IOverlay接口。 DirectShow定义了局部存储传输的两种机制,推模式和拉模式。推模式中源滤波器产生数据并将它传给下流的滤波器。那个滤波器被动的接受数据,处理它,并进一步将它传给下流。在拉模式中,源滤波器连接一个Parser滤波器。Parser滤波器向源滤波器请求数据。源滤波器通过传送数据来相应请求。推模式IMemInputPin接口。拉模式使用IAsyncReader接口。 样本和分配器 当一个针向另外一个针传递媒体数据时,它并不是将指向存储缓冲器的指针传递给另一个针。而是传递给了管理内存的一个COM对象。这个对象叫做media sample,提供IMeidaSample接口。接收针通过调用IMediaSample方法,比如IMediaSample::GetPointer,IMediaSample::GetSize和IMediaSample::GetActualDataLength等来访问存储缓冲器。 样本通常从输出针到输出针方向向下流动。在推模式下,输出针通过调用输入针上的IMemInputPin::Receive方法来传递样本。输入针或者同步处理数据(完全在Receive方法内部),或者在Worker Thread上异步处理。输入针容许在Receive方法中阻塞,如果它需要等待资源。 另外有一个COM对象,叫做Allocator,用来创建和管理媒体样本。Allocator提供IMemAllocator接口,当一个滤波器需要一个空缓冲器的media sample时,它会调用IMemAllocator::GetBuffer方法,这个方法将返回指向样本的指针。每一对连接针共享一个Allocator。当两个针连接时,它们决定哪个针提供Allocator。针也可以设定Allocator的属性,比如缓冲器的数量,每一个缓冲器的大小。 媒体样本参考计数 Allocator产生一个有限样本池。在任意时刻,一些样本可能在使用,而其他可以被GetBuffer调用。Allocator使用参考计数来追踪样本。GetBuffer方法返回一个样本和参考计数1。如果参考计数归零,样本返回Allocator池,这样它又可以被GetBuffer重新调用。只要参考计数大于零,这个样本就不能被GetBuffer调用。如果属于Allocator的每一个样本都被使用,那么GetBuffer方法会阻塞知道有了可用的样本。 比如,假设一个输入针接收到了一个样本。如果它在Receive方法中同步处理样本,它并不增加计数值,在Receive返回式,输出针释放样本,参考计数归零,样本返回Allocator池。另一方面,如果输入针在Worker Thread上处理样本,它会在离开Receive方法前,增加计数值。参考计数为2。当输出针释放样本,计数值变为1,样本仍然没有返回池中。在Worker Thread处理完样本后,它调用Release来释放样本。这时样本才返回池中。 当一个针接收到一个样本,它会将它拷贝到另外一个样本,或者它会修改原始样本并将它传给下一个滤波器。潜在地,一个样本可以环游整个图形,每一个滤波器依次调用AddRef和Release。因此,输出针决不能在调用Receive方法后再重用一个样本,因为下流滤波器也许正在使用这个样本。输出针通常调用GetBuffer获取一个新的样本。 这种机制就减少了内存分配的数量,因为滤波器可以重用同一个缓冲器。它也防止了滤波器偶然地在未处理的数据上写的操作,因为allocator有一系列可用的样本。 滤波器可以对输入输出使用独立的Allocator。如果它扩展了输入数据(比如,解压缩输入),那么它可能会这么做。如果输出没有输入长,滤波器可能占位(In Place)处理数据,而不必将它拷贝到新的样本中。在那种情况下,两个或者更多的针连接可以共享一个allocator。 Committing和Decommitting Allocators 滤波器状态 滤波器有三个可能状态,停止,暂停和运行。停止状态的目的是在图形中提示数据,而使运行命令立即响应。滤波器图形管理器控制所有的状态转变。当一个应用程序调用IMediaControl::Run,IMeidaControl::Pause或者IMediaControlStop时,管理器会在滤波器上调用相应的IMediaFilter方法。停止和运行间的状态转换通常都要经过暂停状态,所以如果应用程序在一个停止的图形上调用Run,管理器在运行前暂停图形。 Source > Transform > Renderer 假设源滤波器不是一个实况捕获源。当源滤波器暂停,它产生一个线程用来产生新数据并将它尽快写入media sample。这个线程通过IMemInputPin::Receive方法将样本推往下流传递给Transform滤波器的输入针。Transform滤波器在源滤波器的线程上接收到样本。它可能通过Worker Thread将样本传给Renderer,不过通常它用同一个线程来传递数据。当Renderer暂停时,它等待接受样本。在接收一个样本后,它会阻塞并且无限期地保持样本。如果它是个视频Renderer,它会将样本显示为张贴图像,只要需要就可以重画。 这时,流完全被提示并且准备来表现。如果图形仍然暂停,样本将会在图形中在第一个样本后堆积起来。直到每一个滤波器的Receive和GetBuffer都阻塞,然而,没有数据丢失。一旦源线程通畅,它会在阻塞点恢复。 | |||
-- 作者:admin -- 发布时间:2005-11-30 12:15:00 --
此主题相关图片如下:
转自:http://www.learnsky.com/bbs/printpage.asp?BoardID=10&ID=887 |
(转)DirectShow系统综述
最新推荐文章于 2021-09-29 10:12:39 发布