,,
(中國艦船研究設(shè)計(jì)中心,武漢 430064)
視頻監(jiān)視系統(tǒng)以其直觀、準(zhǔn)確、及時(shí)和信息內(nèi)容豐富而廣泛應(yīng)用于許多場合。在船舶領(lǐng)域,視頻監(jiān)視系統(tǒng)在安全防范,災(zāi)害發(fā)現(xiàn)與確認(rèn),信息獲取等方面也有著普通傳感器無法比擬的優(yōu)勢[1-2]。
在災(zāi)害發(fā)生時(shí),通過的視頻,可以確切地獲知船舶的安全狀態(tài)。直觀的信息有利于指揮員能夠快速準(zhǔn)確地處理分析現(xiàn)場情況,有效地組織各種力量采取應(yīng)對(duì)措施,減輕甚至消除災(zāi)害所帶來的影響,將艦船維持在正常或接近正常的狀態(tài)。
DirectShow是一個(gè)處理Windows平臺(tái)上各種格式的媒體文件的播放、音視頻采集等高性能要求的成熟技術(shù)。DirectShow不但能支持多種音視頻編解碼器和多種媒體類型并提供高品質(zhì)的媒體流解碼和回放,而且能夠封裝硬件差異驅(qū)動(dòng)接口[3],及用與設(shè)備無關(guān)的方法提供設(shè)備相關(guān)的性能。基于DirectShow以上的優(yōu)勢,本文采用DirectShow開發(fā)船舶監(jiān)視系統(tǒng)。
DirectShow 是一個(gè)基于COM(組件對(duì)象模型)系統(tǒng)的一個(gè)開放性的應(yīng)用框架,由許多模塊化的軟件組件組成[4]。DirectShow系統(tǒng)功能見圖1。
DirectShow系統(tǒng)位于Ring3特權(quán)級(jí)別應(yīng)用層,它使用Filter Graph模型來管理整個(gè)數(shù)據(jù)流的處理過程。Filter是用于處理數(shù)據(jù)的功能模塊,它在Filter Graph中按一定的順序協(xié)同工作,F(xiàn)ilter分為3類:Source Filter、Transform Filter和Rendering Filter[5]。
圖1 DirectShow系統(tǒng)
Source Filter主要負(fù)責(zé)獲取數(shù)據(jù)和前期的處理,并把數(shù)據(jù)往下傳輸。數(shù)據(jù)源可以是文件、采集卡、數(shù)字?jǐn)z像機(jī)等。Transform Filter主要負(fù)責(zé)數(shù)據(jù)格式轉(zhuǎn)換,并把數(shù)據(jù)繼續(xù)往下傳輸。完成數(shù)據(jù)的分離與合成、解碼盒編碼等。Rendering Filter主要負(fù)責(zé)將數(shù)據(jù)傳輸給顯卡、聲卡等硬件設(shè)備進(jìn)行多媒體的播放,并把數(shù)據(jù)流轉(zhuǎn)換成文件進(jìn)行存儲(chǔ)。
Filter包含一個(gè)或多個(gè)Pin,F(xiàn)ilter通過Pin進(jìn)行連接,使數(shù)據(jù)構(gòu)成一條順序的鏈路。由于Source Filter和Rendering Filter分別為數(shù)據(jù)流的起點(diǎn)和終點(diǎn),所以Source Filter不包含輸入Pin,Rendering Filter不包含輸出Pin。
開發(fā)Filter,選擇合適的父類,不但能減少編程和調(diào)試的工作量,而且能有效地降低出錯(cuò)率。DirectShow SDK已經(jīng)根據(jù)各種不同的應(yīng)用從CbaseFilter派生出了相應(yīng)功能的子類。所要定制的Source Filter是一個(gè)實(shí)時(shí)源,同時(shí)需要在屬性頁中設(shè)置攝像頭的IP地址及其端口,以及幀速率,邊界大小等屬性。
選擇CSource類和CPersistStream類作為將要開發(fā)名為Finley’s Video Filter的Source Filter的父類。CSource類和CPersistStream類結(jié)構(gòu)見圖2。
圖2 CSource類和CPersistStream類的結(jié)構(gòu)示意
CSource類作為一般推模式Source Filter的父類,而CPersistStream類用于實(shí)現(xiàn)屬性頁。
Sample是一個(gè)封裝了一定大小數(shù)據(jù)內(nèi)存的COM組建,它被用來傳輸Filter之間的數(shù)據(jù)。兩個(gè)連接的PIN共享同一個(gè)命名為Allocator的Sample分配器,用來創(chuàng)建、管理一個(gè)或多個(gè)Sample。在數(shù)據(jù)傳輸時(shí),上一級(jí)Filter的輸出Pin調(diào)用ImemAllocator::GetBuffer函數(shù),得到一個(gè)空閑Sample的數(shù)據(jù)內(nèi)存地址,并放入數(shù)據(jù)。然后再將這個(gè)Sample傳送給下一級(jí)Filter的輸入Pin。數(shù)據(jù)從上一級(jí)Filter的輸出Pin傳送到下一級(jí)Filter的輸入Pin,并沒有進(jìn)行數(shù)據(jù)的內(nèi)存?zhèn)浞?,而只是?shù)據(jù)到達(dá)的通知。所以Pin的連接只是一個(gè)虛擬的邏輯連接,這樣做減少了所占用的資源并提高了運(yùn)行效率。
Filter的數(shù)據(jù)傳輸分為推模式(push model)和拉模式(pull model)兩種形式。由于本系統(tǒng)用于船舶的視頻監(jiān)視系統(tǒng),所以采用的Source Filter屬于實(shí)時(shí)源(live source)。它能夠自己產(chǎn)生數(shù)據(jù)并用專門的線程將這些數(shù)據(jù)往下推送。數(shù)據(jù)從Capture Pin出來,調(diào)用數(shù)據(jù)流的下一個(gè)Filter的輸入Pin上的ImemInputPin::Receive函數(shù),實(shí)現(xiàn)Source Filter到下一個(gè)Filter的傳送。同樣,下一個(gè)Filter也調(diào)用ImemInputPin::Receive進(jìn)行數(shù)據(jù)的接收。
由于Filter都是COM組建,除了要重寫CreateInstance、NonDelegatingQueryInterface等函數(shù)外,還需要重寫CSource類和CPersistStream類中特定的虛函數(shù)。
CSource類的派生類要?jiǎng)?chuàng)建各個(gè)CSourceStream類實(shí)例。
GetMediaType:提供輸出Pin上首選媒體類型。
CheckMediaType:鏈接媒體類型的檢查。
DecideBufferSize:決定數(shù)據(jù)傳輸單元Sample的內(nèi)存大小。
FillBuffer:在Sample中填充數(shù)據(jù)。
由于這4個(gè)函數(shù)是用于Filter之間的媒體協(xié)商的,應(yīng)把它寫在CMonitorVideoPin中。
CPersistStream類主要是實(shí)現(xiàn)Filter設(shè)置界面的類,它的派生類要實(shí)現(xiàn)兩個(gè)重要的函數(shù)。
WriteToStream和ReadFromStream:用于寫入和讀取Filter設(shè)置的信息,如數(shù)據(jù)流的大小,IP地址,端口號(hào),透明度,幀速率等,其中所有的屬性需要寫相應(yīng)的實(shí)現(xiàn)函數(shù)。
Filter是一種組件,使用前必須注冊。首先需要為新Filter生成一個(gè)新的CLSID,同時(shí)要為屬性頁生成GUID。使用系統(tǒng)中的GuidGen.exe程序生成GUID,然后在命令行狀態(tài)下執(zhí)行“regsvr32 Finley’s Video Filter的絕對(duì)路徑”即可。
本文硬件采用DS-2DF1-512海康威視攝像頭,采用千兆網(wǎng)與計(jì)算機(jī)相連。軟件采用VC和DirectShow庫編寫Source Filter,采用C++Builder編寫監(jiān)視軟件。
Filter Graph是Filter的容器,是Filter鏈路的組合。首先在GraphEdit程序中加載所創(chuàng)建的Source Filter。Transform Filter和Rendering Filter分別采用DirectShow SDK提供的Color Space Converter和Video Mixing Renderer 9。把它們的輸出Pin與輸入Pin以此連接,見圖3。
根據(jù)實(shí)際需要對(duì)Filter的屬性進(jìn)行設(shè)定。其中由于Color Space Converter不是CPersistStream的派生類,所以不能設(shè)置屬性。
圖3 Filter Graph結(jié)構(gòu)示意
完成所有設(shè)置之后對(duì)Filter Graph進(jìn)行保存。在主函數(shù)中調(diào)用API函數(shù)LoadGraphFile加載Filter Graph即可顯示實(shí)時(shí)視頻。
Filter有停止(Stopped)、暫停(Paused)和運(yùn)行(Running)三種狀態(tài)。暫??梢哉J(rèn)為是數(shù)據(jù)準(zhǔn)備就緒狀態(tài),也是停止與運(yùn)行之間切換的中間狀態(tài)。所有Filter是通過IMediaFilter的接口方法來控制狀態(tài)轉(zhuǎn)換的。暫停和運(yùn)行兩種狀態(tài)基本上是相同的,暫停只是阻塞了數(shù)據(jù)傳輸?shù)木€程。在本系統(tǒng)中因?yàn)镕inley’s Video Filter是一個(gè)實(shí)時(shí)源,暫停過程中采集的數(shù)據(jù)已經(jīng)失去了實(shí)時(shí)性,所以并不要求在暫停狀態(tài)下啟動(dòng)數(shù)據(jù)傳輸。在這種情況下Video Mixing Renderer 9在暫停狀態(tài)下是接收不到任何Sample的。由于暫停和運(yùn)行基本相同,而暫停又是運(yùn)行與停止的中間狀態(tài),下面著重討論停止與暫停兩個(gè)狀態(tài)的切換。
停止→暫停。從Video Mixing Renderer 9開始進(jìn)行暫停狀態(tài)的轉(zhuǎn)換,同時(shí)Filter調(diào)用所有Pin的Active函數(shù)進(jìn)行初始化,從后向前進(jìn)入就緒狀態(tài)。當(dāng)Finley’s Video Filter進(jìn)入就緒狀態(tài)并啟動(dòng)數(shù)據(jù)線程,開始發(fā)送Sample后,則狀態(tài)轉(zhuǎn)換完成。
暫停→停止。Video Mixing Renderer 9進(jìn)入停止?fàn)顟B(tài)時(shí),調(diào)用所有Pin的Inactive函數(shù),使上一級(jí)Filter調(diào)用IMemAllocator::GetBuffer脫離阻塞狀態(tài),并終止所有Receive函數(shù)的等待,直到Finley’s Video Filter進(jìn)入停止?fàn)顟B(tài)。
其它的功能只需要設(shè)計(jì)新的Filter或采用DirectShow框架提供的相應(yīng)的Filter,組成相應(yīng)的Filter Graph即可實(shí)現(xiàn)。實(shí)現(xiàn)視頻流的文件存儲(chǔ)實(shí)現(xiàn),只用在實(shí)時(shí)視頻播放Filter Graph中的Transform Filter后增加一個(gè)PIN,并把數(shù)據(jù)推入相應(yīng)的File writer Filter中即可。實(shí)現(xiàn)視頻文件播放,在相應(yīng)的Filter Graph中采用AVI/WAV File Source作為Source Filter即可。這些都是DirectShow SDK中提供的Filter,若需要其它特殊的功能則需要自己定制Filter。本系統(tǒng)自行定制了Finley’s File Source Filter用以視頻文件播放。
視頻監(jiān)視系統(tǒng)滿足船舶行業(yè)日常安全管理和及時(shí)發(fā)現(xiàn)災(zāi)情和隱患的需求,具有占用資源少,可移植性強(qiáng)等優(yōu)點(diǎn),為對(duì)數(shù)字視頻信息做進(jìn)一步的處理,實(shí)現(xiàn)智能監(jiān)控打下基礎(chǔ)。
[1] 韋 磊,張英俊,付瀟瀟,等.船舶視頻監(jiān)控系統(tǒng)的研究[C]∥中國航海學(xué)會(huì)2006年度學(xué)術(shù)交流會(huì)優(yōu)秀論文集,北京:中國航海學(xué)會(huì),2007:184-186.
[2] 曹 輝,張均東,宋 威.視頻技術(shù)在船舶領(lǐng)域中的研究與應(yīng)用[J].船海工程,2007,36(3):122-125.
[3] 黃振宇,王 敏,吳 濤.基于COM的Directshow Filter實(shí)現(xiàn)[J].微機(jī)發(fā)展,2004,14(5):113-116.
[4] 涂 超,葉家瑋.基于Direct Show的橋區(qū)船舶視頻采集系統(tǒng)開發(fā)[J].船海工程,2009,38(4):121-123.
[5] 陸其明.DirectShow開發(fā)指南[M].北京:清華大學(xué)出版社,2003.