張凱
(蘇州科達科技股份有限公司 上海研發中心,上海 201103)
一種保證初始數據完整性的實時視頻流分發插件①
張凱
(蘇州科達科技股份有限公司 上海研發中心,上海 201103)
在視頻監控聯網系統中進行實時監控時,如果監控客戶端收到的初始視頻數據不完整會出現初始播放畫面花屏的問題.基于開源多媒體框架GStreamer,針對H.264編碼標準,設計并實現了一種實時視頻流分發插件.該插件使用隨機創建的請求型source襯墊用于視頻數據的分發,并通過緩存當前IDR幀組的方法確保發送初始視頻數據的完整性.該插件可應用于流媒體服務器當中,解決實時監控時初始畫面花屏的問題.實驗結果表明,應用該插件的流媒體服務器能夠高效分發實時視頻數據并保證初始播放畫面完整,對提升實時監控效果有著明顯的作用.
視頻監控;流媒體服務器;GStreamer框架;H.264標準;IDR幀;RTP協議
視頻監控聯網系統中使用IPC(IP Camera網絡攝像機)作為監控前端采集實時視頻流,通過流媒體服務器分發到多個監控客戶端(以下簡稱客戶端)進行實時視頻監控.流媒體服務器的這種工作模式呈現“一進多出”的拓撲形態.
高清視頻編碼標準(如H.264[1])使用幀間圖像數據壓縮技術.由于實時視頻流訪問的隨機性,客戶端獲取到的初始視頻幀(第一個視頻幀)可能需要參考之前的幀進行解碼,這會導致客戶端由于接收的初始視頻數據不完整出現初始播放畫面花屏現象,影響了實時監控效果.
為解決這一問題,需要在視頻流分發側保證發送到客戶端的每一路視頻流的初始視頻數據是完整的.
在視頻流分發側使用緩存數據保證所發送數據完整性是目前業內常用方式.內容分發網絡 CDN (Content Delivery Network)是使用數據緩存方式的代表[2].在CDN中,使用緩存代理服務器緩存流媒體服務器的內容,客戶端從緩存代理服務器上獲取流媒體內容.
CDN在提升流媒體服務響應速度,媒體流分發容量的同時,也對網絡傳輸服務質量提出了很高的要求.在CDN中傳輸實時視頻流時,緩存代理服務器和流媒體服務器之間需要實時同步緩存數據.若緩存代理服務器和流媒體服務器之間的網絡質量不佳,實時監控效果會受到較大影響.
本文提出了在流媒體服務器上通過實時視頻流分發插件緩存當前視頻數據以保證初始視頻數據完整性的方法,針對H.264編碼標準,基于GStreamer框架[3,4]設計并實現了一個應用于流媒體服務器中的實時視頻流分發插件.相比較CDN而言,本文描述的流媒體服務器不需要緩存代理服務器就能通過分發插件保證所分發初始視頻數據的完整性,不再產生流媒體服務器與緩存代理服務器之間的通訊開銷.
本文描述了分發插件的設計與實現方法并給出相關實驗結果.
1.1 GStreamer中相關定義
GStreamer框架基于插件(plugins).GStreamer中的插件是一段可以加載的代碼,常常以動態鏈接庫的形式存在.一個GStreamer插件中可包含一個或多個元件(Element)[5].
元件是GStreamer中最重要的概念,見定義1.
定義1.元件:GStreamer中,元件是構建一個媒體管道的基本塊,GStreamer中的元件都繼承自GstElement對象.
多媒體應用程序可以創建若干個元件(elements)連接在一起,從而構成一個管道(pipeline)來完成一個媒體處理任務.GStreamer中的管道見定義2.
定義2.管道:管道是一種容器元件,可以向管道中添加元件從而將一組存在鏈接的元件組合成一個大的邏輯元件.管道可以操作包含在其自身內部的所有元件.
管道中的元件需要建立鏈接關系,襯墊(Pads)在GStreamer中被用于元件之間的鏈接,從而讓數據流能在管道中流動.襯墊的定義見定義3.
定義3.襯墊:襯墊是元件之間的接口,元件之間的數據交互依靠襯墊來完成.襯墊能夠限制數據流的通過,只有兩個元件鏈接在一起的襯墊允許通過的數據類型一致時,這兩個元件才可交換數據.
一個襯墊很像一個物理設備上的接口,如電視機上的HDMI輸入接口和機頂盒上的HDMI輸出接口.正因為電視機和機頂盒都有相同類型的接口,才可以使用數據線連接起來完成媒體流的播放.
根據數據流向,襯墊被分為兩種類型:source襯墊與sink襯墊.數據向元件之外流出可以通過一個或多個source襯墊,元件接受數據通過一個或多個sink襯墊來完成.在一個管道中,數據流從一個元件的source襯墊流到另一個元件的sink襯墊.
根據生命周期,襯墊分為永久型(always)、隨機型(sometimes)、請求型(request)三種類型.永久型襯墊在元件創建時就存在,并一直存在直到所屬元件銷毀.隨機型襯墊在某種特定條件觸發后才創建并存在.請求型襯墊只在應用程序明確發出請求時才創建并存在.
使用元件,管道和襯墊這些GStreamer基本元素可以構建豐富的多媒體應用程序.
1.2 IDR幀組
視頻編碼中,每一個圖像幀代表一幅靜止的圖像.實際壓縮時,會采取各種算法減少數據的容量[6].
I幀表示關鍵幀,可理解為這一幀畫面的完整保留,解碼時只需要本幀數據就可以完成.P幀表示的是這一幀跟之前一個關鍵幀(或P幀)的差別,解碼時需要用之前緩存的關鍵幀(或P幀)疊加上本幀定義的差別,生成最終畫面.B幀是雙向差別幀,B幀記錄本幀與前后幀的差別.要解碼B幀,不僅要取得之前的緩存畫面,還要解碼之后的畫面,通過前后畫面與本幀數據的疊加獲得最終畫面.
在H.264編碼中,I幀不用參考任何幀,但是之后的P幀和B幀有可能參考這個I幀之前的幀.為區分首個I幀和其他I幀,把首個I幀稱為IDR(Instantaneous Decoding Refresh即時解碼刷新)幀[1].由IDR幀開始,重新開始編解碼一個新的幀序列.IDR幀之后的所有幀都不會引用該IDR幀之前幀的內容.由此可知,IDR幀阻斷了誤差的積累,提供了隨機訪問性,播放器可以從視頻流中任意一個IDR幀播放而不會導致花屏.
考察幀序列(下標表示幀的顯示順序):I1P4B2B3P7B5B6I8P11B9B10P14B11B12.這里I1和I8就是IDR幀,因為其之后的幀不需要跨過該幀去參考之前的幀.
定義4定義了IDR幀組的概念.
定義4 IDR幀組 視頻流中一個IDR幀和其之后,下一個IDR幀之前的幀組成的集合稱為IDR幀組.
參考幀序列:I1P4B2B3P7B5B6I8P11B9B10P14B11B12.{I1,P4,B2,B3},{I1,P4,B2,B3,P7,B5,B6},{I8, P11,B9,B10}都可被稱為IDR幀組.
流媒體服務器是視頻監控聯網系統的核心部分.流媒體服務器獲取所請求IPC的實時視頻流,并將這一路視頻流分發到各個請求的客戶端[2].
基于GStreamer框架,僅用于實時視頻瀏覽的流媒體服務器架構如圖1所示.本文約定IPC生成的視頻流格式為H.264編碼格式,客戶端與流媒體服務器之間,流媒體服務器與IPC之間都使用RTSP[7]作為控制協議,使用RTP[8]作為視頻數據傳輸協議.為方便描述,本文約定一個IPC只提供一路實時視頻流,并使用ES流(Elementary Stream,基本流)傳輸.

圖1 基于GStreamer框架的流媒體服務器架構
圖1 的流媒體服務器中,clientproxy元件接收來自客戶端的實時瀏覽請求建立RTSP會話,并對RTSP會話中所請求的IPC建立對應的數據分發管道.該數據分發管道為定義2所定義的GStreamer管道,包含一個ipcsrc元件,一個 streamdispatcher元件和若干個clientsink元件.Clientsink元件是隨機產生的,每建立一個對該IPC請求的RTSP會話,clientproxy元件就在該數據分發管道中創建一個clientsink元件與其對應.
數據分發管道中的ipcsrc元件使用RTSP協議向所請求IPC獲取實時視頻流,獲取的實時視頻流使用RTP協議由IPC發送到ipcsrc元件.Ipcsrc元件收到承載實時視頻流的RTP包后,傳遞到streamdispatcher元件進行分發.Streamdispatcher元件將收到的RTP包分別傳遞給管道中每個clientsink元件.
管道中每個clientsink元件包含了其對應RTSP會話的會話參數(傳輸協議,地址端口等信息),clientsink元件將streamdispatcher元件分發的RTP包根據會話參數發送到客戶端.
以圖1為例,clientproxy元件收到客戶端1對IPC1的實時視頻流會話請求后建立RTSP會話1,并建立名為管道1的數據分發管道.管道1中包含一個ipcsrc元件ipcsrc1,一個streamdispatcher元件streamdispatcher1和一個clientsink元件clientsink1(包含RTSP會話1的會話參數).ipcsrc1使用RTSP協議向IPC1請求實時視頻流后,承載視頻流的 RTP包經“ipcsrc1→streamdispatcher1→clientsink1”的路徑傳遞后發送到客戶端1.此后若clientproxy元件又建立客戶端2對IPC1請求的RTSP會話2,則在管道1中再創建clientsink元件clientsink2(包含RTSP會話2的會話參數),承載視頻流的 RTP包經“ipcsrc1→streamdispatcher1→clientsink2”的路徑傳遞后發送到客戶端2.
圖1中管道的生命周期依賴于請求其對應IPC的客戶端RTSP會話數目:當會話數目大于0時,管道被創建clientproxy元件;當會話數目等于0時,管道被clientproxy元件銷毀.
streamdispatcher元件是數據分發管道中的分發控制中樞,不僅將數據分發給clientsink元件,還保證發送 給 clientsink 元 件 的 初 始 幀 為 IDR 幀 . streamdispatcher元件的設計與實現是本文的重點,下一節將詳細介紹streamdispatcher元件的設計與實現.
3.1 設計思想
將IPC發送的實時視頻流視為一個幀序列.為確保發送到客戶端的初始幀為IDR幀,streamdispatcher元件需緩存當前幀參考的IDR幀組(當前幀參考的IDR幀及當前幀與IDR幀之間的其它幀).Streamdispatcher元件在分發數據時總是先發送緩存的當前IDR幀組,再發送當前幀.這種工作方式可由圖2示意.
圖2中t1時刻,請求IPC實時視頻流的RTSP會話1建立,與之對應的 clientsink元件也隨之創建. streamdispatcher元件此時收到IPC發送的當前幀為SLICE1m(非IDR幀,且IDR1與SLICE1m之間無IDR幀).因為在t1時刻之前,streamdispatcher元件中已經緩存了IDR1及IDR1至SLICE1m之間所有幀的IDR幀組,所以在t1時刻streamdispatcher元件首先發送緩存的IDR幀組,再發送SLICE1m幀給對應RTSP會話1的clientsink元件.對應RTSP會話1的clientsink元件收到初始幀為IDR1.同理在t2時刻,streamdispatcher元件中緩存的是IDR2及IDR2至SLICE2n之間(IDR2與SLICE2n之間無IDR幀)所有幀的IDR幀組,對應RTSP會話2的clientsink元件收到的初始幀為IDR2.

圖2 streamdispatcher元件工作原理
Clientproxy元件建立RTSP會話時會創建對應的clientsink元件,然后向streamdispatcher元件申請創建一個請求型source襯墊,并將此襯墊與clientsink元件的sink襯墊進行鏈接.當streamdispatcher元件在接收視頻流數據后,通過已創建的請求型source襯墊將數據推送到 clientsink元件.Ipcsrc、clientproxy和clientsink之間的襯墊鏈接關系如圖3所示.

圖3 管道中元件的襯墊鏈接關系
3.2 IDR幀識別方法
ES流中,IPC將H.264視頻編碼后的NALU (Network Abstract Layer Unit)封裝在RTP包中.NALU的首字節定義如圖4所示.

圖4 NALU的首字節定義
其中F為1個比特,在規范中規定為0.NRI為2個比特,用于表示NALU的優先級.Type為5個比特,表示NALU的類型.若NALU類型為5,則表示該NALU為IDR圖像,其對應的幀為IDR幀.
RTP在對NALU封包時,會使用單一NAL單元模式,組合封包模式,分片封包模式這三種模式中的一種.在實際運行中,應根據視頻流的封包模式判斷RTP載荷的NALU類型是否為IDR幀類型.
以分片封包模式為例,若RTP包載荷的首字節中Type為28,表示為FU-A類型的分片單元.此時應判斷該RTP包是否為第一個分片單元,若為第一個分片單元,再對FU頭字節(載荷的第二個字節)的后5個比特判斷NALU類型.只有包含第一個分片單元且FU頭字節中類型為5的RTP包才被判斷為IDR幀類型.
3.3 視頻流分發算法
如圖3所示,管道中每一個clientsink元件創建時, streamdispatcher元件也會創建一個請求型source襯墊與該clientsink元件鏈接,承載實時視頻流的RTP包經該source襯墊傳遞到與其連接的clientsink元件.創建請求型source襯墊的過程如算法1所示.
當承載實時視頻流的RTP包從streamdispatcher元件的sink襯墊流入時,streamdispatcher元件將流入的RTP包分發到使用算法1創建的source襯墊中,同時緩存當前幀的IDR幀組數據.這個過程使用算法2描述.算法2在streamdispatcher元件每接收到一個RTP數據包時都會被調用一次.

算法1中padContext為srcPad的上下文對象,包含兩個成員變量:sessionid和initialized.sessionid為整型,用于存放所創建襯墊對應的 RTSP會話 ID. initialized為布爾型,表示該襯墊是否已經接收到了初始IDR幀,初始值為FALSE.算法1的第6行表示srcPad設置上下文對象.
streamdispatcher元件使用列表變量srcPadList存放所有被請求創建的source襯墊,并用index變量記錄索引.算法1的第7行表示新創建的srcPad被加入到srcPadList列表中.

算法2中,idrGroupList是streamdispatcher元件用于緩存當前IDR幀組的列表變量,在streamdispatcher元件初始化時創建且設初始值為空.rtpPkg是來自sink襯墊由IPC發送的RTP數據包,被parseFrameType函數用來判斷載荷中NALU類型是否為IDR幀類型 (判斷方法參考3.2節,本文中只考慮單一NAL單元模式和分片封包模式).
算法2的第1至14行描述了向每個已創建source襯墊(包含在srcPadList中)推送數據的過程.算法2先根據每個source襯墊的上下文信息了解該襯墊是否已經接收過初始IDR幀:如果該襯墊還未接收過初始幀:在緩存當前IDR幀組的idrGroupList不為空且當前NALU類型不為 IDR幀類型的條件下,先推送idrGroupList,再推送rtpPkg到該襯墊,并將上下文中的初始幀接收標示置為TRUE;如果該襯墊已經接收過初始IDR幀:只需要將當前rtpPkg數據推送至該襯墊即可.
向source襯墊推送數據后,需要判斷當前rtpPkg是否需要加入到idrGroupList中,算法2的第15至25行描述了這一個過程.如果當前rtpPkg的NALU類型為IDR幀類型則表示idrGroupList已緩存的IDR幀組不再成為當前IDR幀組,這時算法2清空idrGroupList后添加當前rtpPkg到idrGroupList中.
算法2利用緩存的當前IDR幀組保證了發送到各source襯墊的初始幀為IDR幀.
應用第2節介紹的架構,基于GStreamer 1.6版本開發了一個簡單的流媒體服務器,僅實現實時瀏覽IPC的功能.其中clientproxy元件和streamdispatcher元件都實現為獨立插件,ipcsrc元件和clientsink元件實現在一個插件當中.基于GStreamer 1.6版本自帶的rtspsrc,decodebin,autovideosink等插件開發了流媒體服務器的實時瀏覽客戶端,可用于實時瀏覽IPC監控的視頻流.
服務器與IPC之間,客戶端與服務器之間都通過RTSP協議建立媒體會話并且使用RTP協議進行視頻流傳輸.實驗使用一個IPC作為視頻監控前端,客戶端建立多個RTSP會話來測試streamdispatcher插件的分發效率.IPC視頻流為ES流,使用H.264編碼,分辨率為704×400,幀率為25fps,平均每3秒發送一個IDR幀.
實驗所使用服務器為PC機,操作系統為windows 7,CPU為英特爾酷睿雙核處理器(2.5GHZ),內存為4GB.實驗中針對不同的RTSP會話數目重點考察了streamdispatcher插件分發一個RTP包(執行一次算法2)的時間,并和不使用streamdispatcher插件直接分發RTP包的時間做了比較.實驗結果如圖5所示.

圖5 RTP包分發消耗時間及比較
圖5 中的消耗時間是分發一個RTP包到所有clientsink插件所消耗的時間(采集頭1000個RTP包的分發時間作為樣本,計算出平均時間).每個clientsink插件對應一個RTSP會話,隨著會話數目的增加,分發時間也隨之增加.分發時間隨會話連接數目線性增加,這與算法2的邏輯擬合.
圖5對使用streamdispatcher插件分發和不使用streamdispatcher插件直接分發所消耗的時間進行了比較.可以看到兩者在消耗時間上基本無差別,這是因為streamdispatcher插件只在直接分發流程上增加了一些條件判別,所增加的開銷極小.
我們的實驗目標設置為300路實時視頻流并發輸出能力.在會話連接數目達到300時,一個RTP包發送到所有clientsink插件的消耗時間為542206納秒.使用抓包工具得知IPC平均一秒內大約發送60個RTP包,因而streamdispatcher插件的轉發能力完全能夠滿足實驗目標.
Streamdispatcher插件保證了發送到客戶端的初始幀為IDR幀,這也使得視頻監控的效果得到了提升,圖 6展示了使用 streamdispatcher插件和未使用streamdispatcher插件的視頻監控效果.

圖6 streamdispatcher插件使用與否的效果比對
圖6 中,未使用streamdispatcher插件的流媒體服務器發送到客戶端的初始畫面出現花屏現象,而使用streamdispatcher插件的流媒體服務器保證了客戶端初始畫面的完整性,提升了視頻監控效果.
本文基于GStreamer框架,針對H.264編碼規范,設計并實現了一種實時視頻流分發插件:使用隨機創建的請求型source襯墊完成數據的分發,并通過緩存當前IDR幀組的方法保證了發送的初始幀為IDR幀,解決了視頻監控初始畫面花屏的問題.本文所描述的插件可應用于流媒體服務器當中,實驗證明這種保證了初始數據完整性的實時視頻流分發插件在高效轉發的同時,也大大提升了實時視頻監控效果.
雖然本文討論的插件針對H.264編碼規范,但這種在視頻分發端緩存當前IDR幀組以保證初始視頻數據完整性的思路仍可擴展到兼容多種編碼格式的流媒體服務器設計當中.
1 Wiegand T,Sullivan G J,Bjontegaard G,Luthra A.Overview of the H.264/AVC video coding standard.IEEE Trans.on Circuits&SystemsforVideoTechnology,2003,13(7):560–576.
2楊戈,廖建新,朱曉民,樊秀梅.流媒體分發系統關鍵技術綜述.電子學報,2009,37(1):137–145.
3 Taymans W,Baker S,Wingo A,Bultje RS,Kost S.GStreamer Application Development Manual(1.6.0).2013.https://gstreamer. freedesktop.org/documentation/.
4劉興民,趙連軍.基于GStreamer的遠程視頻監控系統的關鍵技術研究.計算機應用與軟件,2011,28(5):243–246.
5 Boulton RJ,Walthinsen E,Baker S,Johnson L,Bultje RS, Kost S,Müller TP,Taymans W.GStreamer Plugin Writer’s Guide(1.6.0). 2013. https://gstreamer.freedesktop.org/ documentation/.
6計文平,郭寶龍,丁貴廣.新一代視頻編碼國際標準的研究.計算機應用與軟件,2004,21(2):60–62.
7 Schulzrinne H,Rao A,Lanphier R.Real Time Streaming Protocol(RTSP).RFC 2326,Internet Engineering Task Force, 1998,4.
8 Schulzrinne H,Casner S,Frederick R,Jacobson V.RTP:A Transport Protocol for Real-Time Applications.RFC 3550, Internet Engineering Task Force,2003,7.
Real Time Video Stream Dispatch Plugin for Ensuring the Integrity of Initial Data
ZHANG Kai
(Suzhou Keda Technology Co.Ltd.,Shanghai R&D Center,Shanghai 201103,China)
In the real time video surveillance network system,if the initial video data
by the monitoring client is not complete,the screen will show blurred screen.For H.264 coding standard,this paper designs and implements real time video stream dispatch plugin based on the open source multimedia GStreamer framework.The plugin uses a randomly requested source pad to dispatch video data.It also caches current IDR frames group to ensure the integrity of initial IDR frame to be sent.The plugin can be used in streaming media server to solve the problem of the blurred screen of initial screen effect in video surveillance.Experiment shows that the streaming media server with this plugin can effectively distribute the real time video data and ensure the integrity of the initial playback screen,which has a significant effect on improving the real-time monitoring effect.
video surveillance;streaming media server;GStreamer framework;H.264 standard;IDR frame;RTPprotocol
2016-08-28;收到修改稿時間:2016-09-27
10.15888/j.cnki.csa.005747