WebRTC中丟包重傳NACK實現分析

在WebRTC中,前向糾錯(FEC)和丟包重傳(NACK)是抵抗網絡錯誤的重要手段。FEC在發送端將數據包添加冗餘糾錯碼,糾錯碼連同數據包一起發送到接收端;接收端根據糾錯碼對數據進行檢查和糾正。RFC5109[1]定義FEC數據包的格式。NACK則在接收端檢測到數據丟包後,發送NACK報文到發送端;發送端根據NACK報文中的序列號,在發送緩衝區找到對應的數據包,重新發送到接收端。NACK需要發送端發送緩衝區的支持,RFC5104[2]定義NACK數據包的格式。

本文在研究WebRTC源代碼的基礎上,以Video數據包的發送和接收爲例,深入分析ANCK丟包重傳機制的實現。主要內容包括:SDP協商NACK,接收端丟包判定,NACK報文構造、發送、接收和解析,RTP數據包重傳。下面分別詳細論述之。

一、SDP協商NACK

NACK作爲RTP層反饋參數,和Video Codec聯繫在一起。WebRTC在初始化階段,創建PeerConnectionFactory對象,在該對象中創建MediaEngine,其中的VideoEngine爲WebRtcVideoEngine2。該對象在構造時,會收集本端支持的所有Video Codec,NACK作爲Codec的屬性被一起收集。在接下來的SDP協商過程中,NACK屬性被協商到Offer/Answer中,如圖1所示。

1

圖1 SDP協商NACK及作用於Video JitterBuffer

PeerConnection在CreateOffer時,收集本端的會話控制信息、音視頻Codec信息和網絡信息等內容。視頻Codec信息從WebRtcVideoEngine2中獲取。最後本端Offer形成SDP報文,經過PeerConnection對象發送到網絡。

接收端在收到Offer之後,首先調用SetRemoteDescription,根據本地配置信息向下創建VideoReceiveStream對象,本地NACK配置信息會最終到達VCMJitterBuffer。接着PeerConnection調用CreateAnswer,生成Answer;根據Offer中的Codec信息和本端支持的Codec信息,最終選定雙方都支持的Codec集合。最後用生成的Answer作爲參數調用SetLocalDescription,根據Answer中的Video Codec信息向下重新創建VideoReceiveStream對象。NACK信息向下傳遞最終到達VCMJitterBuffer,在這裏設置NACK相關參數。這些參數在接收RTP數據包過程中發揮作用,比如判斷丟包、是否發送NACK報文等。Answer發回發送端時,發送端調用SetRemoteDescription執行同樣的設置流程。

二、接收端丟包判定

Video接收端丟包判定在Worker線程中進行。RTP數據包到達接收端後,經過RTP模塊到達VCM模塊的JitterBuffer對象,最終調用VCMJitterBuffer的InsertPacket函數對數據包進行緩存和重排。

VCMJitterBuffer把丟失RTP數據包的序列號存儲在集合missing_seq_nums中。對於本次從RTP模塊到來的數據包,標記其序列號爲seq1,而上次到達數據包的序列號爲seq2。如果seq1 > seq2,則表示seq1順序到達,標記(seqnum2, seqnum1)區間內的數據包爲丟失狀態,將其存儲到missing_seq_nums集合中。注意這裏的丟失狀態是暫時的,如果下個數據包到達時有seq1 < seq2,則表示數據包亂序到達,則把missing_seq_nums中小於seq1的序列號都刪除掉。

在更新missing_seq_nums集合時,如果集合中存儲的序列號超過預設的容量,則通過調用RecycleFramesUntilKeyFrame()不斷丟包來減少集合中的序列號,直到集合中的序列號總數低於預設容量值。

三、NACK報文發送和接收

接收端的NACK報文構造和發送工作在ModuleProcessThread線程中週期性完成。過程如圖2所示。

2

圖2 NACK報文構造和發送

ModuleProcessThread線程週期性調用VideoReceiver::process函數,該函數通過VCMReceiver調用VCMJitterBuffer::GetNackList,從missing_seq_nums集合中得到過去一段時間內丟失RTP數據包的序列號。然後調用RtpStreamReceiver::ResendPackets函數。調用流程最終會到達RTCPSender::SendRTCP,發送類型爲NACK的RTCP報文。

NACK報文是類型爲205的RTCP 擴展反饋報文,如圖3所示:

3

圖3 NACK報文格式

其中PT = 205,FMT = 1,Packet identifier(PID)即爲丟失RTP數據包的序列號,Bitmao of Lost Packets(BLP)指示從PID開始接下來16個RTP數據包的丟失情況。一個NACK報文可以攜帶多個RTP序列號,NACK接收端對這些序列號逐個處理。

NACK報文構造完成以後,發送到網絡層。NACK報文是RTCP報文的一種,因此其發送、接收和分析遵循RTCP報文處理的一般流程。這部分內容可參考文檔[3]。

四、RTP數據包重傳

接收端在接收和解析NACK報文後,通過回調機制處理各種類型的RTCP報文,對於NACK報文,會調用RTPSender重新發送RTP數據包,如圖4所示:

4

圖4 發送端數據包重傳

RTCPReceiver在解析RTCP之後,得到RTCP報文的描述結構,然後通過回調進行報文語義處理。NACK報文會被髮送到RTPSender進行處理。RTPSender根據NACK報文中包含的序列號,到RTPPacketHistory緩存中查找對應的RTP數據包。如果找到,則把數據包發送到網絡。

至此,一個完整的NACK報文迴路完成,丟失的RTP數據包會重新發送到接收端。

五、總結

本文深入分析了WebRTC內部關於丟包重傳(NACK)的實現細節,對NACK的SDP協商、丟包判定和重傳進行深入研究,爲繼續學習掌握WebRTC的QoS機制奠定基礎。

參考文獻

[1] RFC5109 – RTP Payload Format for Generic Forward Error Correction.

[2] RFC5104 – RFC 5104 – Codec Control Messages in the RTP Audio-Visual  Profile with Feedback (AVPF) .

[3] WebRTC中RTP/RTCP協議實現分-http://www.jianshu.com/p/c84be6f3ddf3.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章