劉 輝 ,魏玉琛 ,蒲 布
(1.重慶郵電大學,重慶400065;2.重慶信科通信工程有限公司,重慶400065)
網絡視頻監控是一種基于寬帶網絡為用戶提供圖像和各種報警信號遠程采集、傳輸、儲存、處理等功能的全新電信業務。這是一個由前端、中間端、后端三部分組成的網絡視頻監控系統。其中解碼模塊將收到的完整數據幀放入解碼器中進行解碼,生成實時視頻影像。
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視頻的解碼。
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。

Directshow技術的最核心就是作為過濾器的可插入標準組件,它是具有特殊功能的COM對象。過濾器又可分為:源過濾器(Source Filter)、變換過濾器(Trans-form Filter)、提交過濾器(Renderer Filter)等。源過濾器引入數據到過濾器圖表中,數據來源可以是文件、網絡、照相機等。不同的源過濾器處理不同類型的數據源,然后將數據往下傳輸;變換過濾器的工作是獲取輸入流,處理數據,并生成輸出流,其對數據的處理包括編解碼、格式轉換、壓縮解壓縮等;提交過濾器主要負責數據的最終去向,接收數據并把數據提交給外設。Directshow使Filter Graph Manager中的Filter按一定的順序連接成一條 “流水線”協同工作,Filter Graph的結構如圖 2所示。過濾器通過文件讀寫、修改數據和顯示數據輸出設備來操作流媒體。為了完成整個任務,必須將所有的過濾器Filter連接起來。應用程序只需要通過COM接口訪問過濾器圖表、控制流媒體或者接收過濾器事件來完成視頻的播放。

Directshow是基于COM系統的開發包。而COM組件對象模型是一種軟件架構,它定義了不同的對象使用一致同意的協議進行通信的一套機制。所有的COM對象都支持相同的接口規范,這使得COM對象可以不依賴于具體的語言和系統平臺。每個COM都至少有一個接口,這里所說的接口是指一套函數和它們參數的定義。每個COM有它自己的GUID-CLSID,每個接口也有它自己的GUID-IID。GUID是一串128 bit數字,由專門的程序產生,可以保證每個GUID的全球唯一性。當知道了一個COM的CLSID和它的接口IID,就可以用CoCreate-Instance函數來實例化該COM對象的其他接口,可用該接口的IID作參數,調用QueryInterface查詢接口函數來完成[1]。得到COM的接口后,就可以用它訪問該接口的一些函數。
本系統采用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]。
COM對象的創建要經過以下步驟:
(1)CoCreateInstance調用CoGetClassObject函數;
(2)COM庫找到DLL程序并進入進程;
(3)調用DLLGetClassObject函數;
(4)DLLGetClassObject函數創建類工廠;
(5)DLLGetClassObject把類工廠接口指針返回給Co-GetClassOjbect函數;
(6)CoGetClassObject把類工廠接口指針返回給Co-GetClassObject函數;
(7)CoCreateInstance得到類工廠后,調用類工廠的對象創建函數;
(8)類工廠創建COM對象;
(9)類工廠把COM對象返回給CoCreateInstance函數,CoCreateInstance函數返回;
(10)客戶直接調用COM對象。
(1)創建一個Filter Graph Manager


(2)根據實際應用,創建一條完整的Filter鏈路。
(3)調用Filter Graph Manager上各個接口的方法進行控制,并且完成Filter Graph Manager與應用程序的事件交互。調用ImediaControl接口的方法控制Filter Graph的狀態轉換:

當兩個Filter連接的時候,它們會采用某一種媒體類型達成一致的協議。媒體類型定義了處于源頭的Filter將要給下一個與其相連接的Filter發送什么樣的數據,以及數據的physical layout。兩個Filter必須支持同一種類型的媒體格式[4]。
在Directshow環境中播放一個H.264格式的文件,需要一個能夠對H.264格式的壓縮視頻進行解碼的解碼器。由于 Directshow沒有提供 H.264的解碼 Filter,所以H.264視頻解碼器需要自行開發。
為了實現H.264視頻解碼器,可設計一個名為H264 Decoder的 Transform Filter,包含一個出 pin、一個輸入pin,用于接收H.264的視頻流輸入,解碼后輸出YUV格式的圖像幀序列。

此Filter的功能是接收視頻流的輸入,解碼后輸出YUV格式的圖像幀序列。而輸入輸出視頻流是通過不同功能的Filter連接完成的。Filter的連接實際上是Filter上pin的連接,連接的方向一般是從上一級Filter的輸出pin指向下一級Filter的輸入pin。只有兩個 Filter都在Graph里,連接才能成功。應用程序可以通過IFilter-Graph::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)。

可以選擇的基類有:CTransformFitler、CTransInPlace-Filter、CVideoTransformFilter、CBaseFilter。 當 Filter 的 輸 入pin接收數據后,經過一定的處理由輸出pin再輸出數據,一般選擇 CTransformFilter或者 CTransInPlaceFilter。由于在Filter上的兩個pin要求的媒體類型互不相同,而CTransInPlaceFilter的輸入和輸出pin上一般使用相同的媒體類型進行連接,并且使用相同的Sample管理器,所以這個Filter不適合用 CTransInPlaceFilter。而CBaseFitler是個一最基本的類,需要做比其他的基類更多的工作。此視頻解碼Filter最后選擇了CTransformFilter類。
CTransformFilter類是從 CBaseFilter繼承而來,其最大特征是將pin上必須實現的函數委托到了Filter上。一般不需要重新寫輸入和輸出pin類,只需要在Filter上實現相應的函數即可。CTransformFilter類使用時需要重載函數:

由于微軟公司推出的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.