馬希超,魏志強,葛 珊
(中國電子科技集團公司第三研究所,北京 100015)
隨著無人機在偵察監(jiān)視、安防保衛(wèi)、森林消防及航拍攝影等眾多領域的推廣應用,作為其核心載荷的光電吊艙得到了人們越來越多的關注[1-2]。在執(zhí)行飛行任務時,光電吊艙作為無人機的“眼睛”,通過有線或無線傳輸鏈路將采集的可見光視頻和紅外視頻實時傳輸至地面,由地面操控臺上運行的顯控軟件接收并顯示。目前,主流的光電吊艙采集的可見光視頻分辨率基本都可達到1 920×1 080 像素,幀率為25 f/s 或30 f/s。通過計算可知,如果直接傳輸原始視頻數(shù)據(jù),數(shù)據(jù)量會達到Gb/s 的量級,對于遠距離無線傳輸來說極難實現(xiàn)。因此,通常對視頻進行編碼,如采用H.264 或H.265 格式,將數(shù)據(jù)量壓縮至Mb/s 的量級,再經(jīng)無線鏈路傳輸后由地面顯控軟件解碼后顯示[3-4]。
視頻編解碼的引入對顯控軟件提出了更高的要求[5],主要體現(xiàn)在實時性和平穩(wěn)性兩個方面。一方面,顯控軟件從接收視頻流到解碼再到顯示需經(jīng)過多個環(huán)節(jié),若簡單地順序執(zhí)行,必然會導致較大的滯后,對操控設備和觀察視頻造成明顯的影響。為保證較好的實時性,需要設計合理的多線程架構,盡量減小視頻顯示的延遲滯后。另一方面,在H.264或H.265 格式的視頻碼流中,視頻幀分為關鍵幀(I幀)、前向參考幀(P幀)和雙向參考幀(B幀)3類[6]。其中,I 幀每隔一定時間出現(xiàn)一次,包含一幀圖像的完整信息,因此數(shù)據(jù)量較大;其余的P 幀和B 幀只包含幀差信息,數(shù)據(jù)量小。因此,傳輸、接收及解碼I 幀時所需的時間較長,導致視頻在顯示時出現(xiàn)周期性卡頓現(xiàn)象。此時,需要采取適當?shù)姆椒▉肀WC視頻顯示的平穩(wěn)性。
本文描述一種針對機載光電吊艙的視頻流實時解碼顯示技術。通過設計合理的多線程架構,采用動態(tài)圖像緩存技術,實現(xiàn)了視頻解碼顯示的低延遲和無卡頓,提高了顯控軟件的實時性和平穩(wěn)性。
整個流程分為3 個線程,即接收線程、解碼線程及顯示線程。3 個線程并行運行,通過視頻流緩存和圖像緩存兩個存儲區(qū)進行數(shù)據(jù)交換。處理流程和線程結(jié)構如圖1 所示。

圖1 流程圖
在接收線程中,程序以循環(huán)的方式不斷接收視頻流數(shù)據(jù)并存入視頻流緩存;解碼線程同樣以循環(huán)的方式不斷檢查視頻流緩存中的數(shù)據(jù)量,當數(shù)據(jù)量超過一定的閾值,提取數(shù)據(jù)進行解碼,并將解碼后的圖像存入圖像緩存;顯示線程以定時器方式周期性地從圖像緩存中提取圖像進行顯示。3 個線程在各自獨立運行的同時緊密配合,以保證數(shù)據(jù)的快速傳遞,最大限度降低延遲,同時數(shù)據(jù)流向清晰,避免產(chǎn)生線程沖突。
接收線程用于完成光電吊艙下傳視頻流的接收。光電吊艙通常采用UDP 通信協(xié)議,通過網(wǎng)絡下傳視頻流,可能帶有加密幀頭。接收線程通過循環(huán)的方式不斷讀取網(wǎng)絡數(shù)據(jù),根據(jù)通信協(xié)議從加密數(shù)據(jù)包中提取有效的視頻流數(shù)據(jù),并立即將數(shù)據(jù)存入視頻流緩存。視頻流緩存為全局存儲區(qū),需具備大量數(shù)據(jù)快速寫入寫出的能力。同時,它對內(nèi)存空間的控制十分重要,一旦發(fā)生接收線程和解碼線程配合失常的情況,如接收線程正常運行而解碼線程由于初始化問題未能運行時,視頻流緩存將出現(xiàn)只存入不取出的情況,最終導致內(nèi)存溢出,程序崩潰。為避免這種情況的發(fā)生,采用環(huán)形存儲器作為視頻流緩存。環(huán)形存儲器采用先進先出原則,當存儲空間用盡后會從尾部回到頭部,用新的數(shù)據(jù)覆蓋最早的數(shù)據(jù)。這樣既可以免去不斷申請新內(nèi)存空間的開銷,又可避免出現(xiàn)內(nèi)存溢出的情況。在程序運行過程中,接收線程控制存儲器的寫入指針不斷存入視頻流數(shù)據(jù),到達末端后便回到起點繼續(xù)寫入;解碼線程控制存儲器的讀取指針以追趕的方式不斷取出數(shù)據(jù),使存儲器內(nèi)的數(shù)據(jù)量始終保持在一定長度之內(nèi),實現(xiàn)動態(tài)平衡。
解碼線程同樣采用循環(huán)方式不斷獲取視頻流緩存中的數(shù)據(jù)量。當數(shù)據(jù)量大于設定的閾值N(如1 024 Bytes)時,則提取N個字節(jié)的數(shù)據(jù)移交至解碼器處理。解碼器調(diào)用FFmpeg 程序庫對H.264 或H.265 碼流解碼,并轉(zhuǎn)換為RGB 格式圖像存入圖像緩存。
在H.264 或H.265 碼流中,大部分幀都是只包含幀差信息的參考幀(P 幀和B 幀),數(shù)據(jù)量較小。每隔固定時間(如1 s)會有一個關鍵幀I 幀,包含完整的圖像信息,數(shù)據(jù)量大,使得傳輸和解碼都較為耗時。因此,解碼得到各幀圖像的時間間隔是不均勻的。若不加處理地將每一幀解碼圖像立即顯示,則會每隔一段時間出現(xiàn)一次卡頓現(xiàn)象,影響視頻顯示的連貫性和平穩(wěn)性。
為解決這一問題,本文引入了圖像緩存。圖像緩存的總體思路是將解碼圖像依次存入緩存,由顯示線程定時提取圖像進行顯示,使顯示的周期與解碼的周期隔離開來并保持均勻。圖像緩存采用隊列形式,以先入先出原則進行存取。采用圖像緩存需要解決的一個重要問題是保證輸入輸出的平衡。雖然根據(jù)相機的幀率可以計算各幀的平均間隔,但并不十分精確。此外,為定時器設定的響應周期也無法做到與真實的幀間隔完全一致,會導致輸入輸出的不平衡。若輸出快于輸入,則會耗盡緩存內(nèi)的圖像,存入一幀則立即顯示一幀,導致緩存失去作用,視頻依然發(fā)生卡頓;若輸出慢于輸入,則緩存數(shù)量不斷增加,若不加限制會導致內(nèi)存溢出,程序崩潰,若設置限幅則會丟失圖像。
本文采用動態(tài)圖像緩存的方法實現(xiàn)輸入輸出的平衡,流程如圖2 所示。每隔一段時間判斷一次緩存內(nèi)的圖像數(shù)量,若數(shù)量較多,則減小定時器的間隔,加快顯示;若數(shù)量較少,則增大定時器的間隔,減慢顯示;若數(shù)量適中,則保持初始間隔。以30 f/s的可見光視頻為例,設初始顯示間隔T=33 ms。每解碼30 幀判斷一次緩存數(shù)量N,若N>5,則令T=30 ms,加速顯示,消耗緩存數(shù)量,減小視頻滯后;若N<3,則令T=34 ms,稍稍減慢顯示,積累緩存數(shù)量,避免出現(xiàn)卡頓;若3 ≤N≤5,則令T=33 ms,保持穩(wěn)定顯示。
經(jīng)過對提取頻率的動態(tài)調(diào)整,可以使圖像緩存長期維持在數(shù)量較少的狀態(tài),保持輸入與輸出的平衡和穩(wěn)定。
測試所用的光電吊艙顯控軟件采用C++語言和Qt 框架編寫,實現(xiàn)了本文所述的多線程架構和動態(tài)圖像緩存技術。在解碼線程和顯示線程中分別記錄每幀圖像解碼和顯示的時間戳,計算解碼時間間隔和經(jīng)動態(tài)調(diào)整后的顯示時間間隔,最后繪制如圖3 所示的曲線圖。
從圖3 可知,解碼間隔極不穩(wěn)定,約30 幀(大概1 s)會出現(xiàn)一次120 ms 以上的長間隔,即處理I幀所需的時間。而經(jīng)動態(tài)調(diào)整后,顯示間隔平穩(wěn)程度顯著提高,絕大多數(shù)數(shù)據(jù)穩(wěn)定在33 ms 左右,其中一小段在30 ms 左右,這是緩存數(shù)量較多、加快顯示的結(jié)果。這一結(jié)果表明,采用動態(tài)圖像緩存技術可以有效提高視頻顯示的平穩(wěn)性,避免出現(xiàn)卡頓現(xiàn)象。

圖2 動態(tài)圖像緩存流程

圖3 幀間隔統(tǒng)計
此外,合理的多線程架構設計也使顯控軟件具有較好的實時性。本文用簡易方法測試了從相機成像到視頻編碼、傳輸再到接收、解碼及顯示全過程的總延遲時間約為0.4 s,如圖4 所示。在這一較低的延遲下,控制光電吊艙和觀察視頻時基本不會產(chǎn)生明顯的滯后現(xiàn)象。

圖4 延遲時間測試
本文介紹了一種針對機載光電吊艙的視頻流實時解碼技術,通過設計合理的多線程架構和數(shù)據(jù)交換方式,采用動態(tài)圖像緩存技術,實現(xiàn)了低延遲和無卡頓的視頻解碼顯示效果,對于充分發(fā)揮光電吊艙的性能和提高地面顯控軟件的運行效率與使用體驗具有重要意義。