DirectShow技术介绍(长篇)-1

    技术2022-06-29  55

    DirectShow 用于控制多媒体数据流;它可以在运行时允许用户播放数字电影和对不同格式的声音进行解码,包括MPEG-1。这种播放性能可以让音视频卡支持Microsoft DirectX?APIDirectShow 同样可以播放AVI电影文件和Apple QuickTime (.mov)格式文件。

     

    DirectShow 被广泛地应用于Windows 95, Windows 98, Windows 2000应用程序。DirectShow 直接和驱动程序通讯,DirectShow 不使用AVICap, 因为AVICap分配了数据缓冲区,如果一个DirectShow 层没有放在AVICap 顶层,那么缓存区数据必须要通过转化去指向它,这样会造成效率低下。

     

    DirectShow Filter Graph

    DirectShow结构定义了标准的组件去控制处理带时间标记(time-stamped)的多媒体数据流,这些组件被称为过滤器(Filter)。把这些Filter放在一个容器中,这个容器就是Filter Graph。可能有三种类型的FilterSource transform render。。(注:有些资料将Filter翻译为过滤器,FilterGraph翻译为过滤器图表,这里我都用原单词)。应用程序可以通过Filter Graph管理器来进行数据访问。Filter Graph 管理器会对Filter Graph配置进行管理,同时还会通过Filter Graph控制数据的转移。Filter Graph 管理器提供了一套COM接口,去允许应用程序与Filter Graph实现通讯。应用程序可以直接调用Filter Graph管理器接口去控制媒体流或者去获得Filter事件。还可以使用DirectShow ActiveXOCX控件进行程序设计。,还有一套MCI子集命令可以用来向后兼容Microsoft VFW 1.x版本和遵循OM-1 MPEG MCI 规范。

     

     

    WDM数据流 

    WDM数据流主要应用包括视频捕获,电视浏览,VBI数据编码支持和DVD电影播放。DirectShow可以非常容易地使用这些数据。 

     

    视频捕获 Minidrivers

    视频卡由一些组件构成,比如电视信号调谐器,AM/FM调谐器,视频解码器,音频解码器等,它们都由WDM Minidriver控制。使用Minidrivers ,就可以允许硬件开发商为不同的卡开发器驱动程序,他们只需要把Minidriver写到他们的卡上,当硬件设计修改后,不需要对修改驱动做更多的修改。

     

    Windows 98 Windows 2000下,视频设备使用WDM Minidriver去控制视频数据流,视频捕获 Minidrivers 相当与一个客户端,它会去控制处理硬件设备的图像数据和其他相关数据。Minidrivers提供了如下的功能:

    捕获压缩和非压缩的视频数据流,VBI数据,时间编码和其他辅助数据流。 

    控制视频流相关设备,比如电视信号调谐器,视频路由设备,电视音频控制器和视频压缩编码器。 

    在流内核中完成处理工作,减少操作过程提高效率。 

     

    Pins, Streams, Formats

    数据流视频捕获驱动程序可以同时支持多个压缩数据,非压缩数据,时间编码, VBI解码数据以及自定义数据。为了保证每种数据同步匹配,捕获驱动程序为这些数据创建了一个新的数据流。每个流都会用一个WDM流针脚(Pin)来传递,通过针脚,单个数据流就可以把它的数据连接到不同的流Filter中去,还可以通过DirectShow 用户Filter的输出针脚,把数据转换输出给用户。(前面我们提到Filter3种类型:Source transform renderSource只有输出针脚,而transform有输入、输出2个针脚,render只有输入针脚)

     

    每个针脚都可以支持多种不同的数据格式。比如,一个针脚它可以提供RGB16, RGB24, YVU9, JPEG 数字视频。针脚可以连接到一个共享的系统内存的数据缓存区,它还可以直接连接到硬件设备。

     

    视频流命名约定

    通常,DirectShow WDM 流会共享媒体的格式定义和流命名约定。但是基于内核模式(Kernel-mode)和用户模式(User-mode)下的命名约定有一些小的命名差异。比如,内核模式下的很多格式定义和GUID定义会在名称前加个”KS”前缀,BITMAPINFOHEADER就是用户模式下的定义,而KS_BITMAPINFOHEADER就是内核模式下的相同结构的定义。在内核模式下,流格式使用KSDATAFORMAT数据结构。这个结构可以被扩展去包含其它特别的数据格式信息。

     

    typedef union {

        struct {

          ULONG  FormatSize;

          ULONG   Flags;

          ULONG   SampleSize;

          ULONG  Reserved;

          GUID   MajorFormat;

          GUID   SubFormat;

          GUID   Specifier;

        };

     

        ULONGLONG  Alignment;

     

    } KSDATAFORMAT, *PKSDATAFORMAT, KSDATARANGE, *PKSDATARANGE;

     

     

    DirectShow 视频捕获的接口和属性

    DirectShow 提供了与许多视频相关的接口,它们中的一些还有附带相关的属性。下面列出的这些接口是实际应用较多,并不带相关属性的:

    IAMAudioInputMixer 

    IAMDroppedFrames 

    IAMStreamConfig 

    IAMVfwCaptureDialogs 

    IAMVfwCompressDialogs 

    IcaptureGraphBuilder 

    ICreateDevEnum 

     

    下表列出了DirectShow 接口与捕获驱动程序通讯的相关属性。

     

    DirectShow 接口             相关属性

     

    IAMTuner                PROPSETID_VIDCAP_TUNER

    IAMTVAudio              PROPSETID_VIDCAP_TVAUDIO

    IAMCrossbar             PROPSETID_VIDCAP_CROSSBAR 

    IAMVideoProcAmp         PROPSETID_VIDCAP_VIDEOPROCAMP

    IAMAnalogVideoDecoder   PROPSETID_VIDCAP_VIDEODECODER 

    IAMAnalogVideoEncoder   PROPSETID_VIDCAP_VIDEOENCODER

    IAMCameraControl        PROPSETID_VIDCAP_CAMERACONTROL

     

    捕获数据流类型

    视频流大致由时间标记,数字视频,和其他相关信息(比如VBI,时间编码)组成,流可以被暂停,开始和停止。流一般是100ns一次进行数据采样,大多数情况下,每个数据帧存放在每个ImediaSample缓存区中。

     

    流输出数据格式

    流的数据类型由KSDATARANGE 数据结构的StreamDescriptionFlags 字段来标识,它们定义如下:

    KS_VIDEOSTREAM_CAPTURE :主要的视频流格式,用于视频会议和把数据写入磁盘。

    KS_VIDEOSTREAM_PREVIEW :用于显示视频,它使用的是没有压缩的数据格式,所以不需要进行特别的解压操作。

    KS_VIDEOSTREAM_VBI     :用于VBI应用。

    KS_VIDEOSTREAM_NABTS   :用于NABTS 解码VBI 采样.

    KS_VIDEOSTREAM_CC 

    KS_VIDEOSTREAM_EDS

    KS_VIDEOSTREAM_TELETEXT:用于图文信息

    KS_VIDEOSTREAM_STILL   :用于Still image.

    KS_VIDEOSTREAM_IS_VPE  :用于基于VPE的数据流。

       

    学习DirectShow有一段时间了,把这段学习过程中翻译出来的SDK与大家分享,同时也希望专家们指出我理解上的错误,万分感谢。

    1. DirectShow介绍

        DirectShow是一个windows平台上的流媒体框架,提供了高质量的多媒体流采集和回放功能。它支持多种多样的媒体文件格式,包括ASFMPEGAVIMP3WAV文件,同时支持使用WDM驱动或早期的VFW驱动来进行多媒体流的采集。DirectShow整合了其它的DirectX技术,能自动地侦测并使用可利用的音视频硬件加速,也能支持没有硬件加速的系统。

        DirectShow大大简化了媒体回放、格式转换和采集工作。但与此同时,它也为用户自定义的解决方案提供了底层流控制框架,从而使用户可以自行创建支持新的文件格式或其它用途的DirectShow组件。

        以下是几个使用DirectShow编写的典型应用:DVD播放器、视频编辑应用、AVIASF转换器、MP3播放器和数字视频采集应用。

        DirectShow是建立在组件对象模型(COM)上的,因此当你编写DirectShow应用时,你必须具备COM客户端程序编写的知识。对于大部分的应用,你不需要实现自己的COM对象,DirectShow提供了大部分你需要的DirectShow组件,但是假如你需要编写自己的DirectShow组件,你还需要具备编写COM组件的知识。

    1.1. DirectShow支持的格式

        DirectShow是一个开放的框架,因此只要有合适的filter来分析和解码,它可以支持任何格式。DirectShow默认支持以下的文件类型和压缩格式:

        注:打*号的需要Windows Media Format SDK支持

        文件类型:

          Windows Media? Audio (WMA)*

          Windows Media? Video (WMV)*

          Advanced Systems Format (ASF)*

          Motion Picture Experts Group (MPEG)

          Audio-Video Interleaved (AVI)

          QuickTime (version 2 and lower)

          WAV

          AIFF

          AU

          SND

          MIDI

        压缩格式:

          Windows Media Video*

          ISO MPEG-4 video version 1.0*

          Microsoft MPEG-4 version 3*

          Sipro Labs ACELP*

          Windows Media Audio*

          MPEG Audio Layer-3 (MP3) (decompression only)

          Digital Video (DV)

          MPEG-1 (decompression only)

          MJPEG

          Cinepak

        微软自己没有提供MPEG2解码器,一些可用的DirectShow MPEG2硬件或软件解码器是由第三方提供的。

    1.2. 常见问题集(摘录)

    1.2.1. 一般问题

        DirectShow支持哪些操作系统?

          DirectShow支持Windows9XWindows2000Windows MeWindows XP

       

        *使用DirectShow需要多少COM知识?

          应用程序开发者只需要基本的COM组件知识:实例化COM组件、调用接口、管理接口的引用计数。Filter开发者则需要更多。

         

        *有与DirectShow兼容的硬件列表(HCL)吗?

          没有。如果硬件兼容DirectShowDirectShow会使用它们,如果没有兼容的硬件,DirectShow使用GDI绘制视频,以及使用WaveOut系列多媒体API来播放音频。

         

        *可以使用哪些语言来编写DirectShow应用?

          DirectShow主要为C/C++开发设计。Visual Basic只能使用其中的很小一部分。可以通过MS JScriptVB Script来支持基于脚本的DVDTV应用。也可能用Delphi来编写,但SDK文档不提供这方面的内容。

         

        DirectShow会通过托管代码实现吗?

          目前还没有这个计划。DirectX SDK提供了有限的使用音视频回放类的托管回放功能,你可以使用COM interop创建托管代码的DirectShow客户端应用,但是因为性能上的原因,不推荐创建运行在CLR上的filter

     

        DirectShow开发需要什么样的编译器?

          任何能够产生COM对象的编译器都可以。

         

        DirectShowDirectX的其它组件的关系

          DirectShowDirectX的其它组件在内部进行联系。DirectShow在硬件的支持下使用DirectSoundDirectDrawVideo RendererOverlay Mixer使用DirectDraw 3DirectDraw5表面(surfaces)。Video Mixing Renderer 7(只支持WINXP)使用DirectDraw7表面。Video Mixing Renderer 9使用最新的(目前是Directx9Direct3D API函数。即便是某个应用程序包含了DirectX其它组件,你也不必使用其它组件的API去编写它。参考SDK的例子:Texture3D Sample

         

        DirectShowActiveMovie的关系?

          ActiveMovieDirectShow原来的名称,现已不再使用,但是一部分API仍保留了"AM"的前缀,比如AM_MEDIA_TYPEIAMVideoAccelerator

         

        DirectShow是限于多媒体应用吗?

          DirectShow默认包含的组件主要是为音视频流设计的,但是,DirectShow框架已经成功地用于其它数据流的解决方案中。

         

        GraphEdit工具有源码吗?GraphEdit.exe是否可再发布?

          没有源码,不可再发布。

         

        DMO可以代替DirectShow filter吗?

          在编写编码器、解码器、效果器应用时,鼓励用DMO代替DirectShow filter。在其它的应用中,使用DirectShow filter可能会比较合适。

         

    1.2.2. 程序编写问题

        *如何设置编译环境,需要哪些头文件和库?

          参考"设置编译环境"章节

         

        GraphEdit列示了很多没有文档支持的filter,它们都是些什么?

          GraphEdit枚举了所有作为filter类型注册在系统中的filter,包括由第三方应用程序安装的filter,以及其它微软技术如Windows MediaNetMeeting安装的,另外,一些DirectShow filter被用来做硬编码或硬解码驱动的外壳。Microsoft H.263 Video Codec用于NetMeeting,不再被DirectShow支持。

       

        *如何知道DirectShow已经被安装?

          调用CoCreateInstance创建一个Filter Graph Manager实例,如果成功,表示DirectShow已经被安装,下面是一个例子:

     

          IGraphBuilder *pGraph;

           HRESULT hr = CoCreateInstance(CLSID_FilterGraph,

                 NULL, CLSCTX_INPROC_SERVER,

                 IID_IGraphBuilder, (void **) &pGraph);

     

        *如果不通过属性设置页来更改filter的设置?

          当然是通过filter提供的接口罗。如果没有提供,就没有办法啦

         

        DirectShow能通知应用程序当前回放位置吗?

          不提供回调来通知位置,需要使用一个计时器定时调用IMediaSeeking::GetCurrentPosition方法来得到当前回放位置。

         

        filter运行在哪个特权级别下?

          运行在Ring 3特权级别下,某些流控制驱动(如音视频采集驱动)运行在Ring 0特权级别下。

         

        *需要一个Kernel调试器吗?

          这依据具体的项目。安装DirectX调试运行时库(DirectX debug runtime library)意味着安装调试驱动(Debug driver)和其它核心组件(kernel mode component),因此如果你的应用程序在其中的某个组件中产生了一个调试断言(debug assert),你的机器就会自动重启除非你拥有一个kernal调试器。

        DEFINE_GUID宏是怎么工作的?

          使用DEFINE_GUID宏可以让你通过包含同一个头文件来定义GUID值而不必使用extern关键词。比如,你的工程中有三个源文件:src1.cpp,src2.cpp,src3.cpp,它们都使用一个相同的GUID值,而为了保证一致性,这个GUID只能在你的工程中定义一次,这时,其它的源文件必须定义外部引用来使用它。用了DEFINE_GUID,你可以使用在所有源文件中包含同一个头文件,在头文件中这样定义GUID

     

        DEFINE_GUID(CLSID_MyObject,

             0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);

        这个例子中GUID0,实际编程中请用Guidgen工具来产生一个GUID,在其中的一个源文件中,在你的头文件前包含initguid.h,如:

     

     // Src1.cpp #include  #include "MyGuids.h"  // Src2.cpp #include "MyGuids.h"

     // Src3.cpp #include "MyGuids.h"

    在没有包含Initguid.h的地方,DEFINE_GUID宏创建外部引用来使用GUID值,在包含Initguid.h的地方,DEFINE_GUID重定义DEFINE_GUID宏以产生GUID的定义。

     如是没有在任何地方添加Initguid.h,你会得到一个链接错误:"unresolved external symbol." ,如果同样的GUID包含Initguid.h两次,会得到编译错误"redefinition; multiple initialization."要解决这些问题,请确认Initguid.h只包含一次。同样的,不要包含Initguid.h到预编译头文件中去,因为预编译头文件会被每个源文件包含。


    最新回复(0)