《电子技术应用》
您所在的位置:首页 > 嵌入式技术 > 设计应用 > 基于Directshow的H.264解码器的设计与实现
基于Directshow的H.264解码器的设计与实现
来源:电子技术应用2011年第9期
刘 辉1,2, 魏玉琛1, 蒲 布1
1.重庆邮电大学,重庆400065; 2. 重庆信科通信工程有限公司, 重庆400065
摘要: 为实现视频监控系统中视频的解码,提出了一个H.264视频解码器在Directshow中的实现方案。Directshow应用程序编程接口是一个基于Windows平台的优秀流媒体架构,它为在Windows平台上处理各种格式的媒体文件回放、音视频采集等高性能要求的多媒体应用提供了完整的解决方案。
关键词: H.264 DirectShow 解码器
中图分类号: TP311.1
文献标识码: A
文章编号: 0258-7998(2011)09-139-03
Design and implementation of H.264 decoder based on Directshow
Liu Hui1,2, Wei Yuchen1, Pu Bu1
1. Chongqing University of Posts and Telecommunications,Chongqing 400065, China; 2. Chongqing Informationg Technology Communication Engineering Co. Ltd, Chongqing 400065, China
Abstract: In video surveillance system,for the realization of decoding the video in video surveillance system presents a program for the realization of H.264 video decoder by using Directshow technology. Directshow is a good streaming media construction, which belongs to Windows.It provides the whole solution for returning the seperate format media, video/voise collection, and other high quality multimedia application on Windows.
Key words : H.264; Directshow; decoder


    网络视频监控是一种基于宽带网络为用户提供图像和各种报警信号远程采集、传输、储存、处理等功能的全新电信业务。这是一个由前端、中间端、后端三部分组成的网络视频监控系统。其中解码模块将收到的完整数据帧放入解码器中进行解码,生成实时视频影像。
    H.264是继MPEG4之后的新一代数字视频压缩格式,它既保留了以往压缩技术的优点和精华,又具有其他压缩技术无法比拟的优点。H.264最具价值的部分是更高的数据压缩比。在同等的图像质量条件下,H.264的数据压缩比能比当前DVD系统中使用的MPEG-2高2~3倍,比MPEG-4高1.5~2倍。正因为如此,经过H.264压缩的视频数据,在网络传输过程中所需要的带宽更少,也更加经济。所以本系统选择采用H.264格式视频。
    DirectX软件开发包是微软公司提供的一套在Windows操作平台上开发高性能图形、声音、输入、输出和网络游戏的编程接口。可以用来开发游戏以及作为其他各类多媒体应用程序的底层API函数集。它是一种基于COM的系统,既不属于驱动程序层,也不属于应用程序层。作为DirectX的一个COM组成元素,Directshow应用程序编程接口是一个Windows平台上的流媒体架构,提供各种格式的高品质多媒体流的捕获、处理、传送和回放。Directshow集成了DirectX其他组件中的先进技术,能做到自动检测、使用视频和音频硬件加速设备。它不仅支持基于WDM驱动程序的硬件设备,也向上兼容Video for Windows驱动程序的硬件设备。Directshow采用多线程多任务的方式,还支持宽松的格式变化。Directshow为播放视频监控中涉及到的各种类型的音频、视频数据提供了非常有效的途径。因此本系统采用Directshow来实现视频监控系统中H.264视频的解码。
1 Directshow体系结构
 Directshow基于模块化结构,每个功能模块都采取COM组件方式,称为Filter。Filter负责执行一些多媒体流的处理过程,采用Filter Graph模型来管理整个数据流的处理过程。Directshow的体系结构图如图1所示。它通过提供各种功能的Filter完成总体应用框架的工作,从而使多媒体应用程序设计变得简单。每个Filter都分别具有一个不同的应用功能,Filter之间通过Pin相互连接。每个过滤器都拥有属于自己的针脚。针脚分为输入针脚和输出针脚,输入针脚把过滤器外部的数据接收到过滤器中进行处理,输出针脚把过滤器中处理后的数据传送到下一个过滤器。经过输入输出针脚的传递,数据从一个过滤器传送到了下一个过滤器中。当两个pin连接的时候,必须有一个pin提供一个allocator。Directshow定义了一系列函数调用来确定由哪个pin提供allocator,以及buffer的数量和大小。在数据流开始之前,allocator会创建一个内存池pool of buffer,在开始发送数据流以后,源Filter就会将数据填充到内存池中一个空闲的buffer中,然后传递给下一个的Filter。

1.1 Filter的原理
 Directshow技术的最核心就是作为过滤器的可插入标准组件,它是具有特殊功能的COM对象。过滤器又可分为:源过滤器(Source Filter)、变换过滤器(Trans-form Filter)、提交过滤器(Renderer Filter)等。源过滤器引入数据到过滤器图表中,数据来源可以是文件、网络、照相机等。不同的源过滤器处理不同类型的数据源,然后将数据往下传输;变换过滤器的工作是获取输入流,处理数据,并生成输出流,其对数据的处理包括编解码、格式转换、压缩解压缩等;提交过滤器主要负责数据的最终去向,接收数据并把数据提交给外设。Directshow使Filter Graph Manager中的Filter按一定的顺序连接成一条“流水线”协同工作,Filter Graph的结构如图2所示。过滤器通过文件读写、修改数据和显示数据输出设备来操作流媒体。为了完成整个任务,必须将所有的过滤器Filter连接起来。应用程序只需要通过COM接口访问过滤器图表、控制流媒体或者接收过滤器事件来完成视频的播放。

 

 

1.2 COM组件
 Directshow是基于COM系统的开发包。而COM组件对象模型是一种软件架构,它定义了不同的对象使用一致同意的协议进行通信的一套机制。所有的COM对象都支持相同的接口规范,这使得COM对象可以不依赖于具体的语言和系统平台。每个COM都至少有一个接口,这里所说的接口是指一套函数和它们参数的定义。每个COM有它自己的GUID-CLSID,每个接口也有它自己的GUID-IID。GUID是一串128 bit数字,由专门的程序产生,可以保证每个GUID的全球唯一性。当知道了一个COM的CLSID和它的接口IID,就可以用CoCreateInstance函数来实例化该COM对象的其他接口,可用该接口的IID作参数,调用QueryInterface查询接口函数来完成[1]。得到COM的接口后,就可以用它访问该接口的一些函数。
2 Directshow的应用
 本系统采用VC++6.0开发多媒体应用程序,开发应用程序之前先要配置开发和编译环境,在写应用程序时要包含头文件Dshow.h并连接到库文件strmbased.lib;在VC++的Library和Include中要加入DirectX SDK中的Lib和Include文件,并且放在标准的VC目录之前[2]。利用Directshow开发应用程序的步骤 :(1) 创建Source Filter、
Trans-form Filter、Renderer Filter; (2) 创建FilterGraph管理各个Filter,并且负责和应用程序交互实现播放控制等。
 由于Directshow使用COM技术实现,首先要调用CoInitialize函数进行初始化。接着创建用于组建过滤器的过滤器组件管理器和Capture -GraphBuilder组件,定义接口指针并获取接口[3]。
2.1 COM对象的创建
 COM对象的创建要经过以下步骤:
 (1) CoCreateInstance调用CoGetClassObject函数;
 (2) COM库找到DLL程序并进入进程;
 (3) 调用DLLGetClassObject函数;
 (4) DLLGetClassObject函数创建类工厂;
 (5) DLLGetClassObject把类工厂接口指针返回给CoGetClassOjbect函数;
 (6) CoGetClassObject把类工厂接口指针返回给CoGetClassObject函数;
 (7) CoCreateInstance得到类工厂后,调用类工厂的对象创建函数;
 (8) 类工厂创建COM对象;
 (9)类工厂把COM对象返回给CoCreateInstance函数,CoCreateInstance函数返回;
 (10) 客户直接调用COM对象。
2.2 开发DirectShow一般过程
 (1) 创建一个Filter Graph Manager
 IGraphBuilder *pGraph=NULL
 HRESULThr=CoCreateInstance(CLSJD_FilterGraph, NULL,CLSCTX_INPROC_SERVER,IDD_IGraphBuilder,(void**)& pGraph)
    (2) 根据实际应用,创建一条完整的Filter链路。
 (3) 调用Filter Graph Manager上各个接口的方法进行控制,并且完成Filter Graph Manager 与应用程序的事件交互。调用ImediaControl接口的方法控制Filter Graph的状态转换:
 IMediacontol *pControl=NULL
 hr=pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl)
 hr=pControl->Run()
2.3媒体类型的检测
 当两个Filter连接的时候,它们会采用某一种媒体类型达成一致的协议。媒体类型定义了处于源头的Filter将要给下一个与其相连接的Filter发送什么样的数据,以及数据的physical layout。两个Filter必须支持同一种类型的媒体格式[4]。
3 解码器设计
    在Directshow环境中播放一个H.264格式的文件,需要一个能够对H.264格式的压缩视频进行解码的解码器。由于Directshow没有提供H.264的解码Filter,所以H.264视频解码器需要自行开发。
3.1 Filter的设计
 为了实现H.264视频解码器,可设计一个名为H264 Decoder的Transform Filter,包含一个出pin、一个输入pin,用于接收H.264的视频流输入,解码后输出YUV格式的图像帧序列。
 Filter的注册名:“H.264 Decoder”
 Filter类型:Transform Filter
 CLSID:CLSID_FilterH.264
 Merit值:MERIT_DO_NOT_USE
 此Filter的功能是接收视频流的输入,解码后输出YUV格式的图像帧序列。而输入输出视频流是通过不同功能的Filter连接完成的。Filter的连接实际上是Filter上pin的连接,连接的方向一般是从上一级Filter的输出pin指向下一级Filter的输入pin。只有两个Filter都在Graph里,连接才能成功。应用程序可以通过IFilterGraph::AddFilter将Filter添加Graph中,当一个Filter被添加到graph中时,Filter图标管理器通过IbaseFilter::JoinFilterGraph来通知Filter。pin连接的过程为:
   (1) Filter Graph Manager表管理器首先调用输出pin上的IPin::Connect;
 (2)如果输出pin接受连接,就调用输入pin上的IPin::ReceiveConnection;
 (3) 如果输入pin也接受连接,则双方连接成功。
 从Directshow的基类继承得到Filter以实现一个独立的线程,专门用于H.264的解码输出。在输入pin上实现媒体类型检查(CheckMediaType)。
 HRESULT CheckMediaType(const CMediaType *mtOut)
   {if(mDecodeFilter->mMpegInputPin->IsConnerted())
   {if((mtOut->subtype==MEDIASUBTYPE_YUV||mtOut->subtype==MEDIASUBTYPE_RGB24)&&mtOut->formattype==FORMAT_VideoInfo)
    {VIEDEOINFOHEADED*pFormat=(VIDEOINFOHEADER*)mtOut->pbFormat;
    if(pFormat->bmilteader.biHeight==mDecodeFilter->mImageHeight&&pFormat->bmiHeader.biWidth==mDecodeFilter->mImageWidth)
            { return S_OK}
           }
      }
Return E_FAIL
}
3.2基类的选择
    可以选择的基类有:CTransformFitler、CTransInPlaceFilter、CVideoTransformFilter、CBaseFilter。当Filter的输入pin接收数据后,经过一定的处理由输出pin再输出数据,一般选择CTransformFilter或者CTransInPlaceFilter。由于在Filter上的两个pin要求的媒体类型互不相同,而CTransInPlaceFilter的输入和输出pin上一般使用相同的媒体类型进行连接,并且使用相同的Sample管理器,所以这个Filter不适合用CTransInPlaceFilter。而CBaseFitler是个一最基本的类,需要做比其他的基类更多的工作。此视频解码Filter最后选择了CTransformFilter类。
  CTransformFilter类是从CBaseFilter继承而来,其最大特征是将pin上必须实现的函数委托到了Filter上。一般不需要重新写输入和输出pin类,只需要在Filter上实现相应的函数即可。CTransformFilter类使用时需要重载函数:
     CTransformFilter::CheckInputType
     CTransformFilter::CheckTransform
     CTransformFilter::DecideBufferSize
     CTransformFilter::GetMediaType
     CTransformFilter::Transform
     由于微软公司推出的Directshow没有提供H.264的视频解码器。因此本文还需要使用ffmpeg中提取出的、经过优化的H.264视频解码组件。
    本系统采用Directshow设计了H.264视频的解码器,并且利用ffmpeg提取出了H.264解码代码,实现了H.264视频的解码播放,如图3所示。

参考文献
[1] 潘爱民.COM原理与应用[M].北京:清华大学出版社,1999.
[2] 陆其明.Directshow开发指南[M].北京:清华大学出版社,2003.
[3] 陆其明. Directshow实务精选[M]. 北京:科学出版社,2004.
[4] 侯春明.MPEG-2视频解码器在Directshow中的实现[J].计算机技术与自动化,2007(4):86-88.

此内容为AET网站原创,未经授权禁止转载。