分享
 
 
 

DirectShow SDK笔记【关于DirectShow(1)】

王朝other·作者佚名  2006-11-30
窄屏简体版  字體: |||超大  

About DirectShow

本节描述DirectShow的整体结构。本节包含的内容比较丰富,我们可能不需要知道所有的这些知识。因此,我们首先应该选择浏览全部的内容,然后根据实际应用程序的需要查看Using DirectShow的内容。如果有关于DirectShow结构的特殊问题,可以再回过来参考本节的内容。

1. DirectShow System Overview

1.1 The Challenge of Multimedia

进行多媒体编程主要存在如下几个挑战:

·多媒体流包含大量的数据,这些数据又要求进行快速的处理

·音频、视频必须同步,以使它们在相同时间开始、停止,以相同的频率播放

·数据来源多,包括本地文件,计算机网络,电视广播和视频摄像机

·数据源的格式多,比如音频、视频交叉存取的(AVI),高级流格式(ASF),运动图像专家组(MPEG)和数字视频(DV)。

·程序员不能预先知道在用户终端系统存在的硬件设备

1.2 The DirectShow Solution

DirectShow就是被设计来解决这些挑战的。DirectShow通过把应用程序从复杂的数据传输、硬件区别和同步隔离起来。它的主要目标是简化在Windows平台创建数字媒体程序的任务。

为了达到流递音频、视频所需的流量,DirectShow在可能的任何时候使用DirectDraw和DirectSound。这些提交数据的数据有效的利用了用户的声卡和图形卡。DirectShow通过把媒体数据包装为带时间戳的Samples实现回放的同步。为了处理可能不同的数据源、格式和硬件设备,DirectShow使用模块化结构,通过这种结构应用程序可以混合、匹配不同的软件组件,这种组件称为Filters.

DirectShow提供Filters支持捕捉和基于WDM的调频设备,Filters还支持旧的VFW捕捉卡,为音频压缩管理(ACM)编写的编解码器以及视频压缩管理器(VCM)接口。

应用程序、DirectShow组件、以及DirectShow所支持的部分硬件、软件组件之间的关系如图。

如同所示,DirectShow与各种不同的设备进行通信,并控制它们。包括本地文件系统,TV Tuner,视频捕捉卡,VFW编解码器,视频显示(通过DirectDraw或者GDI),以及声卡(通过DirectSound)。因此,DirectShow把应用程序与这些设备的复杂性隔离开来。DirectShow还为某些文件格式提供了本地的压缩、解压Filters.

2. The Filter Graph and Its Components

本条款描述DirectShow的主要组件。主要目的是为应用程序开发人员和编写自定义DirectShow Filter的开发人员做些介绍。应用程序开发人员通常可忽略DirectShow的一些低级细节。但是,阅读此节仍是好主义,可以对DirectShow的结构有一个大概理解。

2.1 About DirectShow Filters

DirectShow基于模块化结构,每个处理阶段都由称为Filter的COM对象完成。DirectShow提供了一系列标准Filter用于应用程序开发,开发者也可以开发自己的Filter来扩展DirectShow的功能。为了举例说明,这里是一个播放AVI视频文件所需要的步骤,连同完成每步的Filters:

·从原始文件读取数据为字节流(File Source Filter)

·检测AVI头,把字节流分析为单独的视频帧和音频Samples(AVI Splitter Filter)

·解码视频帧(各种解码Filters, 取决于压缩格式)

·画视频帧(Video Renderer Filter)

·把音频Samples发送到声卡(默认的DirectSound设备Filter)

这些Filters及结构如图所示:

如图所示,每个Filter都与一个或多个Filter相连接。连接点也是一个COM对象,称为Pins。Filters使用PINS把数据从一个Filter移动到下一个。图中的箭头表示数据的流向。在DirectShow,一个Filters的集合称为Filter Graph。

Filter有三种可能的状态,运行,停止,暂停。当一个Filter运行时,它就处理媒体数据流,当停止时,Filter就不处理数据,暂停状态用来在运行前Cue Data, 在Data Flow in the Filter Graph一节对这些概念有更详细的描述。除非特别的例外,状态改变都是协调贯穿在整个Filter Graph,Graph的所有Filter的状态改变都是统一的。因此,Filter Graph也可说是运行,停止,暂停。

Filter 一般分为下面几种类型。

(1)、源Filter(Source Filter):源Filter引入数据到Filter Graph,数据来源可以是文件、网络、照相机或者是任何地方。每个源Filter处理不同类型的数据源。

(2)、变换Filter(Transform Filter):变换Filter的工作是获取输入流,处理数据,并生成输出流。编码、解码读书变换Filter的例子。

(3)、提交Filter(Renderer Filter):提交Filter在Filter图表里处于最后一级,它们接收数据并把数据提交给用户。比如,视频Renderer把视频帧画在显示器,音频Renderer把音频数据发送到声卡,File-Writer Filter把数据写入文件。

(4)、分割Filter(Splitter Filter):分割Filter把输入流分割成多个输出。例如,AVI分割Filter把一个AVI格式的字节流分割成视频流和音频流。

(5)、混合Filter(Mux Filter):混合Filter把多个输入组合成一个单独的数据流。例如,AVI混合Filter把视频流和音频流合成一个AVI格式的字节流。它进行AVI分割Filter相反的操作。

这些Filters种类的区别并非绝对。比如ASF Reader Filter既是Source Filter又是Splitter Filter.

所有的Filters都暴露了IBaseFilter接口,所有的Pin都暴露了IPin接口。DirectShow也定义了一些其他的接口实现更特殊的功能。

2.2 About the Filter Graph Manager

Filter Graph Manager也是一个COM对象,用来控制Filter Graph中的所有的Filter,主要有以下的功能:

·协调Filters之间的状态改变

·建立参考时钟

·传递事件到应用程序

·提供应用程序建立Filter Graph的方法

下面就这些功能做一个简单的说明。可以本文档的其他地方找到详细说明。

状态改变:Filters的状态改变必须以一种特殊顺序发生。因此,应用程序并不将状态改变的命令直接发给Filter,而是发送给Filter Graph Manager一个简单命令,由Manager将命令分发给Graph中每一个Filters。Seeking也是按同样的方式工作,先由应用程序将Seek命令发送到Filter Graph Manager,然后由其分发给每个Filters。

参考时钟:Graph中的Filter都采用的同一个时钟,称为参考时钟(Reference Clock),参考时钟可以确保所有的数据流同步,视频桢或者音频Sample应该被提交的时间称为Presentation Time。它是相对于参考时钟来确定的。Filter Graph Manager应该选择一个参考时钟,可以选择声卡上的时钟,也可以选择系统时钟。

Graph事件:Filter Graph Manager采用事件队列机制将Graph中发生的事件通知给应用程序,这个机制类似于Windows的消息循环。

Graph构建的方法:Filter Graph Manager给应用程序提供了将Filter添加进Graph的方法,连接Filter的方法,断开Filter连接的方法。

Filter Graph Manager没有的一个功能就是把数据从一个Filter移动到另一个Filter。这是由Filters自己通过它们的PIN连接完成的。处理过程总是在不同的线程进行。

注意:Filters总是与Filter Graph Manager在同一进程,被进程类服务器加载。在Filters之间,Filters与Filter Graph Manager之间的函数调用都不会存在列举(Marshall)。

2.3 About the Media Type

因为DirectShow是基于模块化的,就需要有一种方式来描述Filter Graph每一个点的数据格式,例如,我们还以播放AVI文件为例,数据以RIFF块的形式进入Graph中,然后被分割成视频和音频流,视频流由一系列视频桢组成,而且还可能是压缩的。解码后,视频流由一系列的非压缩的位图组成,音频流也是同样的处理过程。

2.3.1 Media Types: How DirectShow Represents Format

媒体类型是一种很普遍的,可以扩展的用来描述数字媒体格式的方法,当两个Filter连接的时候,他们会在某种媒体类型达成一致。媒体类型决定了上一级Filter将要给下游的Filter发送什么类型的数据,以及数据的物理布局。如果两个Filters在媒体类型上没有达成一致,那么他们就没法连接起来。

对于某些应用程序,我们不需要担心媒体类型。比如在文件回放中,DirectShow处理了所有的细节。其他类型的应用程序可能需要直接在媒体类型上操作。

媒体类型是通过AM_MEDIA_TYPE结构定义的,此结构包含如下信息:

·主类型:它是一个GUID值,定义的全部的数据种类。主类型包括视频、音频、未解析的字节流、MIDI数据等等。

·子类型:也是GUID值,进一步定义媒体类型。比如,主类型是视频时,子类型可能是RGB-24、RGB-32和UYVY等等。对于音频,子类型可能是PCM音频、MPEG-1 Payload等等。主类型提供了比子类型更多的信息,但是它还没有定义格式的所有信息。比如,视频子类型没有定义图像大小和帧率。这些通过下面的格式子块说明。

·格式子块:它是描述格式细节的数据块。它是从AM_MEDIA_TYPE结构单独分配。AM_MEDIA_TYPE的pbFormat指针指向格式子块。

pbFormat是一个void*的指针,因为格式块会因为媒体类型的不同而有不同的布局。PCM音频使用WAVEFORMATEX结构。视频块结构包括VIDEOINFOHEADER和VIDEOINFOHEADER2。AM_MEDIA_TYPE的formattype成员是指明在格式块所包含结构类型的GUID。每种结构都有一个GUID。cbForamt成员指定了格式块的大小。总是需要在废弃pbFormat指针前检测它的值。

如果格式块被填充,主类型和子类型的信息可以忽略。但是,在没有完整的格式块时,主类型和子类型提供了一种方便的方法来识别格式。比如我们可指定一个通用的24位RGB格式(MEDIASUBTYPE_RGB24),而不需要知道VIDEOINFOHEADER结构所需要的所有信息,比如图像大小和帧率。

比如,Filter可能使用下面的代码来检测媒体类型:

HRESULT CheckMediaType(AM_MEDIA_TYPE *pmt)

{

if (pmt == NULL) return E_POINTER;

// Check the major type. We're looking for video.

if (pmt->majortype != MEDIATYPE_Video)

return VFW_E_INVALIDMEDIATYPE;

// Check the subtype. We're looking for 24-bit RGB.

if (pmt->subtype != MEDIASUBTYPE_RGB24)

return VFW_E_INVALIDMEDIATYPE;

// Check the format type and the size of the format block.

if ((pmt->formattype == FORMAT_VideoInfo) &&

(pmt->cbFormat >= sizeof(VIDEOINFOHEADER) && (pmt->pbFormat != NULL))

{

// Now it's safe to coerce the format block pointer to the

// correct structure, as defined by the formattype GUID.

VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER*)pmt->pbFormat;

return S_OK;

}

return VFW_E_INVALIDMEDIATYPE;

}

AM_MEDIA_TYPE结构也包含了一些可选信息。它们可提供一些附加信息。但是Filters并不要求使用它们:

·lSampleSize: 如果非0就表示每个Sample的大小。如果是0,表示Sample大小可能随时改变

·bFixedSizeSamples: 如果是TRUE,表示lSampleSize值有效,否则应该忽略lSampleSize

·bTemporalCompression: 如果是FALSE,表示所有的帧都是关键帧

2.4 About Media Samples and Allocators

Filters通过Pin的连接来传递数据,数据流是从一个Filter的输出Pin流向相连的Filter的输入Pin。虽然有其他不少的传输机制存在,输出Pin最常用的传递数据的方式是调用输入Pin上的IMemInputPin::Receive方法。

根据的Filter不同,有多种方式来分配媒体数据的内存块,可以在堆上分配,可以在DirectDraw的表面,也可以采用GDI共享内存,还有其他的一些分配机制。内存分配的响应对象被称为Allocator,也是一个COM对象,暴露了IMemAllocator接口。

当两个Pin连接的时候,必须有一个Pin提供Allocator,DirectShow定义了一系列函数调用来确定由哪个Pin提供Allocator. PIN之间还会在Buffer的数量和大小上达成一致。

在数据流开始之前,Allocator会创建一个Buffer池,在数据流动期间,上一级Filter就会将数据填充到Buffers然后传递给下一级Filter。但是,上一级Filter并不是直接将内存Buffer的指针直接传递给下一级的Filter,而是通过一个Media Sample的COM对象,这个COM对象是Allocator创建的用来管理内存Buffer。Media Sample暴露了IMediaSample接口,一个Sample包含如下内容:

·指向内部Buffer的指针

·时间戳

·一些标志

·可选的媒体类型

时间戳定义了Presentation Time,Renderer Filter就根据这个时间来安排Render顺序的。标志用来标示数据从前一个Sample后是否中断等等,媒体类型提供了一种中途改变数据格式的方法。通常,一般Sample没有媒体类型,表明它的格式从前一个Sample后没有改变。

当一个Filter正在使用Buffer,它就会保持一个Sample的引用计数,Allocator通过引用计数用来确定是否可以重新使用一个Buffer。这样就防止了覆盖另一个Filter正在使用的Buffer。当所有的Filter都释放了对Sample的引用,Sample才返回到Allocator的内存池重新使用。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有