基于ARM的移動視頻監控終端設計與實現
FU indicator的Type字段表示RTP采用的負載結構,28,29時表示采用分片封包模式,NRI字段的值根據NALU的NRI值設置。FU header的S位置1時表示該包是NALU的起始分片,E位置1時表示該包是NALU的結束分片。
2.1.3 RTP丟包處理
由于網絡穩定性原因,可能造成RTP丟包的情況。針對單一NALU模式和組合封包模式丟包不會影響解碼器的正常工作,會導致監控畫面花屏或跳幀想象,但對于實時監控是在可承受的范圍。對于分片封包模式丟包會造成接收端收到一個不完整的NALU,對一個不完整的NALU解碼可能造成解碼失敗,甚至系統崩潰。因此,對于分片封包模式的RTP包需要判斷接收的NALU是否丟包。
傳輸分片封包模式的NALU時,一個NALU分割封裝成若干個RTP包具有相同的時間戳、依次遞增的序列號。對接收的RTP包根據FU header頭信息做不同的處理:接收到起始分片(S=1),根據序列號在鏈表中添加節點,保存視頻數據、起始分片序列號,計數器加1;接收到中間分片,在鏈表中找到時間戳相同的節點,將此RTP包序列號與起始序列號相減,計算出視頻數據在鏈表的相對偏移,存儲視頻數據到鏈表相應位置,計數器加1;接收到結束分片(E=1),同中間分片一樣,但還需要保存結束分片序列號。每接收一個RTP包后判斷NALU完整性,在接收到起始分片、結束分片的前提下,結束分片序列號與起始分片序列號之差是否等于計數器的值,以此判斷一個NALU是否接收完整,若接收到所有分片,置位結構體中FrameCompelere,解碼器可根據此位判斷NALU完整性。
2.2 H.264解碼器的實現
監控終端通過網絡接收到H.264視頻流后,需要移植H.264的解碼庫實現實時解碼。在眾多解碼器中經對比和分析,選用ffmpeg開源解碼器來實現。ffmpeg庫為音視頻數據分離、轉換、解碼提供了完整解決方案,其中兩個重要庫libavformat和libavcodec,分別支持各種音視頻文件格式和音視頻解碼器。
利用ffmpeg的API函數進行視頻流解碼,先做好解碼前的準備工作。調用av_register_all()函數注冊所有的文件格式和編解碼器的庫,也可以只注冊特定的解碼器。關于解碼器的信息在AVCodecContext結構體中,它包含解碼器所有信息,查找H.264解碼器CODEC_ID_H264,通過avcodec_open()函數打開解碼器。用avcodec_alloc_frame()函數分配一幀的存儲空間,存儲解碼后輸出的數據。
在雙向鏈表中已經保存了接收的視頻流,從鏈表頭讀取NALU進行解碼,每讀取一個NALU將鏈表頭指向下一個單元,釋放已讀取NALU占有的內存。NALU的頭信息定義了視頻流所屬類型,一般包括增強信息(SEI)、序列參數集(SPS)、圖像參數集(PPS)、條帶(Slice)等。先將SPS、PPS參數集通過解碼器解碼出來設置解碼圖像尺寸、片組數、參考幀數、量化和濾波參數等。依次從鏈表頭讀取NALU,調用avcodec_decode_ video()函數解碼輸出到分配的存儲空間,當完成一幀的解碼,就需要對解碼后的圖像顯示到液晶屏。解碼輸出的圖像格式為YUV420P,可以采用ffmpeg提供的sws_seale()把圖像格式轉換為RGB格式顯示,也可以采用其他SDL之類的庫直接YUV覆蓋顯示。整個解碼流程如圖5所示。
3 結語
系統采用S3C2440硬件平臺和嵌入式Linux操作系統相結合,設計了移動視頻監控終端,重點闡述了用RTP協議在網絡中通過套接字傳輸視頻流,結合開源解碼庫ffmpeg實時解碼H.264視頻流的解決方案。經測試,對于QCIF分辨率監控畫面具有較好的實時性和可靠性。當視頻分辨率增大時,解碼器的解碼性能成為視頻監控終端的瓶頸。因此,本文的后續工作就是針對ffmpeg解碼庫在ARM9平臺的優化,提升解碼性能。
評論