1. 程式人生 > >WebRTC中丟包重傳NACK實現分析

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) .