一、前言
隨着移動互聯網的快速發展以及智能終端性能的逐步提高,智能終端間進行實時音視頻通訊成爲未來移動互聯網
發展的一個重要方向。那麼如何保證智能終端之間實時音視頻通訊的服務質量成爲一個必須加以重視的問題。實時音
視頻通訊包括採集、編碼、網絡傳輸、解碼、播放等環節,其中採集、編解碼和播放是不受網絡條件影響的,只受限
於編解碼算法,播放策略等因素,網絡傳輸的丟包、抖動和亂序對qos的影響最爲重大,因此本文介紹的qos解決方案
要解決的是網絡傳輸丟包、抖動和亂序因素對服務質量的不好影響。
二、發送端
對於實時音視頻通訊,常採用UDP協議來傳輸多媒體數據,本文是採用基於udp的rtp協議來傳輸音視頻數據。對
於不同格式的編碼數據,會有不同的rtp打包協議,比如對於H.264視頻數據,文檔rfc3984對NAL U的rtp打包封裝進行
了規範,詳情請參考該文檔。對於視頻數據的打包封裝,因爲一幀視頻數據的數據長度可能大於MTU,所以相關的打
包協議都會規定將長度大於MTU的幀進行切割,分塊封裝到多個rtp包進行傳輸。爲了避免丟包、抖動和亂序對服務質
量的影響,本方案在發送端和接收端各建立了節點數相等的一段循環buffer,用於緩存發送端數據和接收端數據。
發送端在發送數據的時候,某個rtp包的seq爲send_seq,發送端把這個包通過udp socket發送出去的同時,把這
個rtp包的數據拷貝到send_seq對應節點的buffer中去,以便這個rtp包接收方沒收到時,發送方還能重發這個rtp包。
這裏要注意的一點是,發送端和接收端的循環buffer節點數要能被65536整除,這樣rtp seq增加到最大值65535時對應
最後一個節點,下一個rtp包的seq爲0正好對應上第一個節點,避免rtp seq掉頭時出現漏洞。
三、接收端
和發送端類似,接收端也開闢了一段節點數能被65536整除的循環buffer,用於緩存接收到的rtp包。接收端收到rtp
包時,需要去解析rtp包頭,取出接收到的rtp包的seq,對應下圖中的received_seq。
當收到第一個包時,start_seq和end_seq都被設置爲received_seq,並把收到的rtp包送到解碼單元。後面收到
rtp包時,有兩個工作要做,一個工作是接收的模塊將接收到的rtp包拷貝到received_seq指向的節點的buffer,並將這
個節點的數據flag(用於標記該節點是否填充了數據)設置爲true,同時要根據start_seq、end_seq和received_seq的
關係來決定要不要將end_seq更新爲received_seq的值,如果received_seq對應的包本來應該end_seq對應的包之前
到達,則不更新end_seq的值,否則就更新。另一個工作是要每過一段時間都要去掃描start_seq到end_seq對應的每
個節點,首先,若當前時間和start_seq對應的數據到達時間的差值超過一定閾值(比如500ms),則將start_seq和
end_seq之間的每個節點的數據全部丟棄,將每個節點的數據flag設置爲false,更新start_seq爲end_seq。其次,若
start_seq對應的節點的下一個節點的數據falg爲true,則將該節點的數據送到解碼單元,同時將start_seq更新爲該
節點的seq,並將該節點的數據flag設置爲false;若flag爲false,且當前時間和start_seq對應的數據到達時間的差值超
過一定閾值(比如50ms),則將該節點的seq(lost_seq)發送給發送端,請求發送端將seq對應的rtp數據再發一遍。這樣,當有些包很久(大於500ms)都沒收到,就認爲它來不了,直接將它們丟棄;有些包短時間(小於
50ms)沒來,則向發送端發送重傳請求,請求發送端再發一次該包,試圖能補上這些包。
四、結果分析
沒加qos模塊時,兩個手機視頻通信在有丟包情況下回出現視頻幀不完整,播放出現馬賽克的現象,加上qos模塊後,視頻播放流暢,效果大爲改善。同時我們爲了測試該方案的作用,在發送端人爲地分別丟棄10%和20%的視頻rtp包,接收端解碼播放效果良好,沒有出現馬賽克現象。