1引言
眾所周知萝玷,WebRTC的擁塞控制和碼率估計(jì)算法采用GCC算法[1]墨状。該算法充分考慮了網(wǎng)絡(luò)丟包和網(wǎng)絡(luò)延遲對(duì)碼率估計(jì)的不同影響豁陆,分別基于丟包率和網(wǎng)絡(luò)延遲進(jìn)行碼率估計(jì)篇裁,最后綜合這另種碼率得出最優(yōu)值沛慢。在算法實(shí)現(xiàn)上,基于丟包率的碼率估計(jì)在發(fā)送端進(jìn)行达布,基于網(wǎng)絡(luò)延遲的碼率估計(jì)在接收端進(jìn)行团甲。最后在發(fā)送端計(jì)算出最優(yōu)值,作用于Codec和PacedSender模塊黍聂。GCC算法能夠較好地基于網(wǎng)絡(luò)實(shí)時(shí)狀況估計(jì)網(wǎng)絡(luò)帶寬躺苦,為網(wǎng)絡(luò)實(shí)時(shí)通信應(yīng)用打下堅(jiān)實(shí)基礎(chǔ)[2][3][4]。
然而产还,隨著時(shí)間推移匹厘,在實(shí)際測(cè)試中發(fā)現(xiàn)GCC算法逐漸顯出一些弊端,比如不能適應(yīng)所有網(wǎng)絡(luò)模型脐区,應(yīng)對(duì)網(wǎng)絡(luò)峰值能力差愈诚,等等。為此,Google官方從M55版本引進(jìn)最新的擁塞控制算法Sendside-BWE炕柔,把所有碼率計(jì)算模塊都移到發(fā)送端進(jìn)行酌泰,并采用全新的Trendline濾波器取代之前的Kalman濾波器[5]。實(shí)測(cè)表明汗唱,新的算法實(shí)現(xiàn)能夠更好更快地進(jìn)行碼率估計(jì)和網(wǎng)絡(luò)過載恢復(fù)宫莱。
本文基于WebRTC的M66版本和相關(guān)RFC,深度分析學(xué)習(xí)最新Sendside-BWE算法的實(shí)現(xiàn)哩罪。
2 GCC算法回顧
關(guān)于GCC算法已經(jīng)有很多分析和論述[6][7]授霸,本文只回顧其算法框架,并分析其在實(shí)際應(yīng)用中存在的問題际插。
GCC算法分兩部分:發(fā)送端基于丟包率的碼率控制和接收端基于延遲的碼率控制碘耳。基于丟包率的碼率控制運(yùn)行在發(fā)送端框弛,依靠RTCP RR報(bào)文進(jìn)行工作辛辨。WebRTC在發(fā)送端收到來自接收端的RTCP RR報(bào)文,根據(jù)其Report Block中攜帶的丟包率信息瑟枫,動(dòng)態(tài)調(diào)整發(fā)送端碼率As斗搞。基于延遲的碼率控制運(yùn)行在接收端慷妙,WebRTC根據(jù)數(shù)據(jù)包到達(dá)的時(shí)間延遲僻焚,通過到達(dá)時(shí)間濾波器,估算出網(wǎng)絡(luò)延遲m(t)膝擂,然后經(jīng)過過載檢測(cè)器判斷當(dāng)前網(wǎng)絡(luò)的擁塞狀況虑啤,最后在碼率控制器根據(jù)規(guī)則計(jì)算出遠(yuǎn)端估計(jì)最大碼率Ar。得到Ar之后架馋,通過RTCP REMB報(bào)文返回發(fā)送端狞山。發(fā)送端綜合As、Ar和預(yù)配置的上下限叉寂,計(jì)算出最終的目標(biāo)碼率A萍启,該碼率會(huì)作用到Encoder、RTP和PacedSender等模塊屏鳍,控制發(fā)送端的碼率勘纯。
發(fā)送端基于丟包率的碼率估計(jì)計(jì)算公式:
接收端基于延遲的碼率估計(jì)計(jì)算公式:
GCC算法充分考慮丟包率和延遲對(duì)碼率的影響,在實(shí)時(shí)通訊應(yīng)用(如視頻會(huì)議)中能夠發(fā)揮良好效果孕蝉。然而,在某些特定應(yīng)用場(chǎng)景下(比如實(shí)時(shí)在線編輯)腌逢,GCC算法的表現(xiàn)不太讓人滿意降淮,主要體現(xiàn)在它應(yīng)對(duì)峰值流量的能力上,具體表現(xiàn)在:1)算法一開始基于Increase狀態(tài)增加碼率,當(dāng)檢測(cè)到Decrease狀態(tài)時(shí)調(diào)用Ar[t(i)] = Alpha * Rr[t(i)]佳鳖,這個(gè)時(shí)候?qū)崟r(shí)碼率Rr(ti)可能遠(yuǎn)小于Ar[t(i-1)]霍殴,這樣在后續(xù)過程中Ar處于較低水平;此時(shí)若有視頻關(guān)鍵幀沖擊系吩,則數(shù)據(jù)包大量在PacedSender的隊(duì)列中排隊(duì)来庭,造成較大排隊(duì)延遲。2)基于1)中論述的情況穿挨,碼率估計(jì)模塊反饋給Codec的編碼碼率很低月弛,但編碼器需要編碼關(guān)鍵幀時(shí),內(nèi)部的碼率控制模塊控制出的最小碼率仍然大于反饋碼率科盛。這兩種情況都會(huì)造成較大的發(fā)送端排隊(duì)延遲帽衙,進(jìn)而在接收端造成較大的JitterBuffer延遲,最終導(dǎo)致端到端延遲到達(dá)500ms的水平贞绵,這在實(shí)時(shí)在線編輯應(yīng)用中是無法容忍的厉萝。
基于此,Google官方從WebRTC M55開始引入新的碼率估計(jì)算法榨崩,把所有碼率計(jì)算模塊都移動(dòng)到發(fā)送端谴垫,并采用全新的Trendline濾波器,基于碼率探測(cè)機(jī)制快速準(zhǔn)確地估計(jì)出實(shí)時(shí)碼率母蛛。
3 Sendside-BWE算法框架
從本節(jié)開始系統(tǒng)分析Sendside-BWE算法的框架和實(shí)現(xiàn)翩剪,圖4顯示該算法的基本實(shí)現(xiàn)框架,以及和GCC算法的對(duì)比溯祸。
圖4中棕色線是Sendside-BWE算法的數(shù)據(jù)控制流回路:發(fā)送端在發(fā)送RTP數(shù)據(jù)包時(shí)肢专,在RTP頭部擴(kuò)展中設(shè)置傳輸層序列號(hào)TransportSequenceNumber;數(shù)據(jù)包到達(dá)接收端后記錄該序列號(hào)和包到達(dá)時(shí)間焦辅,然后接收端基于此構(gòu)造TransportCC報(bào)文返回到發(fā)送端博杖;發(fā)送端解析該報(bào)文,并執(zhí)行Sendside-BWE算法筷登,計(jì)算得到基于延遲的碼率Ar剃根;最終Ar和基于丟包率的碼率As進(jìn)行比較得到最終目標(biāo)碼率,作用到PacedSender和Codec模塊前方,形成一個(gè)完整的反饋回路狈醉。圖4中紅色線是GCC算法的數(shù)據(jù)控制流回路:發(fā)送端在發(fā)送RTP數(shù)據(jù)包時(shí),在RTP頭部擴(kuò)展中設(shè)置絕對(duì)發(fā)送時(shí)間AbsSendTime惠险;數(shù)據(jù)包到達(dá)接收端后記錄該絕對(duì)到達(dá)時(shí)間苗傅,然后基于此執(zhí)行GCC算法得到Ar,最后構(gòu)造REMB報(bào)文把Ar發(fā)送回發(fā)送端班巩;發(fā)送端基于Ar和As得到最終目標(biāo)碼率渣慕,作用到PacedSender和Codec模塊,形成一個(gè)完整的反饋回路。
從中可以看出逊桦,Sendside-BWE算法充分復(fù)用GCC算法的框架和實(shí)現(xiàn)眨猎,整個(gè)反饋回路基本類似:發(fā)送端在RTP頭部擴(kuò)展中記錄碼率估計(jì)元數(shù)據(jù),碼率估計(jì)模塊基于此元數(shù)據(jù)估計(jì)出碼率As强经,在發(fā)送端基于丟包率計(jì)算Ar睡陪,發(fā)送端綜合As和Ar得到最終目標(biāo)碼率,并作用于Codec和PacedSender模塊匿情。所不同的是:對(duì)于GCC算法兰迫,RTP報(bào)文頭部添加AbsSendTime擴(kuò)展,在接收端執(zhí)行基于延遲的碼率估計(jì)码秉,網(wǎng)絡(luò)延遲濾波器采用Kalman Filter逮矛,返回給發(fā)送端的是REMB報(bào)文;對(duì)于Sendside-BWE算法转砖,RTP報(bào)文頭部添加TransportSequenceNumber擴(kuò)展须鼎,在發(fā)送端執(zhí)行基于延遲的碼率估計(jì),網(wǎng)絡(luò)延遲濾波器采用Trandline府蔗,返回給發(fā)送端的是TransportCC報(bào)文晋控。表5總結(jié)出GCC算法和Sendside-BWE算法的異同。
需要注意的是姓赤,從WebRTC M55開始啟用Sendside-BWE后赡译,其GCC算法就只做前向兼容而沒有進(jìn)一步的功能開發(fā)、性能優(yōu)化和bug修正不铆。因此蝌焚,GCC是過去,Sendside-BWE是未來誓斥。
4 Sendside-BWE算法實(shí)現(xiàn)
本節(jié)論述Sendside-BWE算法的實(shí)現(xiàn)細(xì)節(jié)只洒,在論述上力求不過度注釋代碼,以免陷入細(xì)節(jié)無法自拔劳坑。本節(jié)按照如下順序論述Sendside-BWE的實(shí)現(xiàn)細(xì)節(jié):SDP協(xié)商毕谴,發(fā)送端發(fā)送RTP報(bào)文,接收端接受RTP報(bào)文及信息存儲(chǔ)距芬,接收端構(gòu)造TransportCC報(bào)文涝开,發(fā)送端解析TransportCC報(bào)文,發(fā)送端碼率估計(jì)框仔。
4.1 Sendside-BWE在SDP層協(xié)商
TransportCC和remb一樣都是Codec的feedback params的一部分舀武。為支持TransportCC,Codec在收集feedback params時(shí)需添加額外一條:
codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
其中离斩,TransportCC在最終生成的SDP中體現(xiàn)為如下一條attribute:
a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
然后银舱,SDP協(xié)商過程按照常規(guī)操作進(jìn)行衷旅。
4.2 發(fā)送端發(fā)送RTP報(bào)文
發(fā)送端在發(fā)送RTP報(bào)文時(shí),需要在RTP頭部添加新的擴(kuò)展TransportSequenceNumber纵朋,該擴(kuò)展格式如圖6所示。
注意這里的傳輸層序列號(hào)茄袖,和RTP報(bào)文格式中的媒體層序列號(hào)不是同一個(gè)東西操软。傳輸層序列號(hào)關(guān)注數(shù)據(jù)的傳輸特性,主要作用是碼率估計(jì)宪祥;媒體曾序列號(hào)關(guān)注數(shù)據(jù)的媒體特性聂薪,主要作用是組幀和抗丟包。它們的初始值不一樣蝗羊,賦值點(diǎn)也不一樣藏澳,其中媒體層序列號(hào)在RTPSender::AssignSequenceNumber()處賦值,而傳輸層序列號(hào)在RTPSender::UpdateTransportSequenceNumber()處賦值耀找。RTP報(bào)文在發(fā)送時(shí)構(gòu)造該頭部擴(kuò)展的函數(shù)調(diào)用棧如下:
=> RTPSender::TimeToSendPacket();
?=> RTPSender::PrepareAndSendPacket();
??=> RTPSender::UpdateTransportSequenceNumber();
???=> RTPSender::AddPacketToTransportFeedback();s
????=> SendSideCongestionController::AddPacket();
然后RTP報(bào)文走正常的構(gòu)造發(fā)送路徑發(fā)送到網(wǎng)絡(luò)翔悠。
4.3 接收端接收RTP并構(gòu)造TransportCC報(bào)文
接收端worker線程在收到RTP報(bào)文后,解析并檢查其頭部擴(kuò)展野芒,根據(jù)其是否有TransportSN擴(kuò)展蓄愁,決定采用Sendside-BWE還是GCC,注意這兩種擁塞控制器是互斥的狞悲。對(duì)于Sendside-BWE撮抓,接收端代理解析擴(kuò)展拿到傳輸層序列號(hào),并記錄RTP報(bào)文的到達(dá)時(shí)間摇锋,構(gòu)造(transport-sn丹拯,arrival_time_ms)鍵值對(duì),存儲(chǔ)在隊(duì)列中荸恕。整個(gè)過程的函數(shù)調(diào)用棧如下:
=> Call::DeliverRtp();
?=> NotifyBweOfReceivedPacket();
?=> RtpPacketReceived::GetHeader();
?=> ReceiveSideCongestionController::OnReceivedPacket();
??=> RemoteEstimatorProxy::IncomingPacket();
???=> OnPacketArrival(transport-sn, arrival_time_ms):
??????Packet_arrival_times_[seq] = arrival_time;
RemoteEstimatorProxy作為Sendside-BWE在接收端的代理乖酬,其實(shí)現(xiàn)遵從WebRTC的模塊機(jī)制,在Process線程以100ms為發(fā)送周期發(fā)送TransportCC報(bào)文[9]戚炫,發(fā)送周期會(huì)根據(jù)當(dāng)前碼率動(dòng)態(tài)調(diào)整剑刑,其取值范圍在[50ms, 250ms]之間,其本身可用的發(fā)送碼率為當(dāng)前可用碼率的5%双肤。TransportFeedback報(bào)文是一種RTP 傳輸層feedback報(bào)文(pt=205)施掏,F(xiàn)MT為15。其格式如圖7所示:
TransportCC報(bào)文采用base + bitmap的思想茅糜,其各個(gè)字段的具體解釋請(qǐng)參考文獻(xiàn)[9]七芭,一個(gè)TransportCC報(bào)文能最多攜帶16個(gè)RTP報(bào)文的有效信息,每個(gè)RTP報(bào)文信息包括其傳輸層序列號(hào)和包到達(dá)時(shí)間蔑赘。TransportCC報(bào)文在發(fā)送端構(gòu)造和發(fā)送的函數(shù)調(diào)用棧如下:
=> RemoteEstimatorProxy::Process();
?=> RemoteEstimatorProxy::BuildFeedbackPacket();
??=> TransportFeedback::AddReceivedPacket()
???=> PacketRouter::SendTransportFeedback(fbpacket);
????=> RTCPSender::SendFeedbackPacket(fbpacket);
然后按照常規(guī)RTCP報(bào)文流程發(fā)送到發(fā)送端狸驳。
4.4 發(fā)送端接收TransportCC報(bào)文并解析
接收端接收操作就是常規(guī)的RTCP接收预明、解析并回調(diào)的流程,在worker線程中:
=> WebRtcVideoChannel::OnRtcpReceived();
?=> Call::DeliverRtcp();
??=> RTCPReceiver::HandleTransportFeedback();
???=> RTCPReceiver::TriggerCallbacksFromRtcpPacket();
????=> TransportFeedbackObserver::OnTransportFeedback();
?????=> SendSideCongestionController::OnTransportFeedback();
然后就是Send-side BWE算法在發(fā)送端的核心實(shí)現(xiàn)耙箍。
4.5 SendSideCongestionController碼率估計(jì)
SendSideCongestionController是Sendside-BWE算法在發(fā)送端的核心實(shí)現(xiàn)撰糠,關(guān)于其的分析全部是細(xì)節(jié)描述。本節(jié)限于篇幅辩昆,僅勾勒出其大致的函數(shù)調(diào)用棧和流程說明阅酪。
?=> SendSideCongestionController::OnTransportFeedback();
?=> AcknowledBitrateEstimator::IncomingPacketFeedbackVector();
?=> DelayBasedBwe::IncomingPacketFeedbackVector();
?=> BitrateControllerImpl::OnDelayBasedBweResult();
?=> SendSideCongestionController::MaybeTriggerOnNetworkChanged();
?=> ProbeController::RequestProbe();
在SendSideCongestionController的OnTransportFeedback()函數(shù)中,首先調(diào)用ALR碼率估計(jì)器得到一個(gè)實(shí)時(shí)碼率汁针,然后以此為參數(shù)調(diào)用DelayBasedBwe計(jì)算得到最新的估計(jì)碼率Ar术辐,把Ar經(jīng)過BitrateController對(duì)象和As綜合,得到最新的目標(biāo)碼率施无。最后通過函數(shù)MaybeTriggerOnNetworkChanged()把最新目標(biāo)碼率作用到Codec和PacedSender模塊辉词。如果本次碼率估計(jì)從網(wǎng)絡(luò)過載中恢復(fù),則調(diào)用ProbeController對(duì)象發(fā)起下一次碼率探測(cè)猾骡。
DelayBasedBwe對(duì)象是真正實(shí)現(xiàn)碼率估計(jì)的地方瑞躺,其內(nèi)部調(diào)用函數(shù)棧如下:
=> DelayBasedBwe::IncomingPacketFeedbackVector();
=> DelayBasedBwe::IncomingPacketFeedback();
?=> InterArrival::ComputeDeltas();
?=> TrendlineEstimator::Update();
=> DelayBasedBwe::MaybeUpdateEstimate();
?=> ProbeBitrateEstimator::FetchAndResetLastEstimatedBitrateBps();
?=> AimdRateControl::SetEstimator();
DelayBasedBwe首先調(diào)用IncomingPacketFeedback針對(duì)每個(gè)RTP報(bào)文信息進(jìn)行碼率估計(jì),其內(nèi)部邏輯和GCC算法的相關(guān)步驟一致兴想,在此不再贅述隘蝎。需要注意的是,其內(nèi)部網(wǎng)絡(luò)延遲濾波器采用TrendlineEstimator襟企。然后DelayBasedBwe調(diào)用MaybeUpdateEstimate()根據(jù)本次判定的網(wǎng)絡(luò)狀態(tài)計(jì)算得到最終的Ar嘱么,如GCC算法一樣。
Trendline濾波器的原理就是最小二乘法線性回歸求得網(wǎng)絡(luò)延遲波動(dòng)的斜率顽悼,每個(gè)散列點(diǎn)表示為(arrival_time, smoothed_delay)曼振,其中arrival_time為RTP包到達(dá)時(shí)間,smoothed_delay為平滑后的發(fā)送接收相對(duì)延遲蔚龙。最后根據(jù)當(dāng)前散列點(diǎn)集合冰评,采用最小二乘法線性回歸計(jì)算得到本次估計(jì)的網(wǎng)絡(luò)延遲m(i)。其計(jì)算過程調(diào)用如下:
=> TrendlineEstimator::Update();
?=> LinearFitSlope();
?=> TrendlineEstimator::Detect();
??=> TrendlineEstimator::UpdateThreshold();
至此木羹,關(guān)于Sendside-BWE算法的實(shí)現(xiàn)初步分析完畢甲雅。
5 Sendside-BWE實(shí)測(cè)數(shù)據(jù)
實(shí)際測(cè)試表明,和GCC算法相比坑填,Sendside-BWE算法在快速碼率估計(jì)抛人、碼率估計(jì)準(zhǔn)確性、抗網(wǎng)絡(luò)抖動(dòng)等方面都具有非常大改善脐瑰。由于保密原因妖枚,此處不能發(fā)布內(nèi)部測(cè)試數(shù)據(jù),僅貼出一組公開渠道獲得的快速碼率估計(jì)比較圖[10]苍在。
該圖表明绝页,Sendside-BWE算法能夠在第一次TransportCC報(bào)文返回時(shí)即估計(jì)出實(shí)時(shí)網(wǎng)絡(luò)帶寬荠商,相比GCC算法更快速更準(zhǔn)確。
6 總結(jié)
本文在總結(jié)對(duì)比GCC和Sendside-BWE算法基礎(chǔ)上续誉,深入學(xué)習(xí)Sendside-BWE算法的框架和實(shí)現(xiàn)細(xì)節(jié)莱没,為進(jìn)一步學(xué)習(xí)WebRTC擁塞控制算法和優(yōu)化算法細(xì)節(jié)打下堅(jiān)實(shí)基礎(chǔ)。
參考文獻(xiàn)
[1] A Google Congestion Control Algorithm for Real-Time Communication. draft-alvestrand-rmcat-congestion-03
[2] Understanding the Dynamic Behaviour of the Google Congestion Control for RTCWeb.
[3] Experimental Investigation of the Google Congestion Control for Real-Time Flows.
[4] Analysis and Design of the Google Congestion Control for Web Real-time Communication (WebRTC). MMSys’16, May 10-13, 2016, Klagenfurt, Austria
[5] WebRTC視頻接收緩沖區(qū)基于KalmanFilter的延遲模型.http://www.reibang.com/p/bb34995c549a
[6] WebRTC基于GCC的擁塞控制(上) - 算法分析 http://www.reibang.com/p/0f7ee0e0b3be
[7] WebRTC基于GCC的擁塞控制(下) - 實(shí)現(xiàn)分析 http://www.reibang.com/p/5259a8659112
[8] WebRTC的擁塞控制和帶寬策略 https://mp.weixin.qq.com/s/Ej63-FTe5-2pkxyXoXBUTw
[9] RTP Extensions for Transport-wide Congestion Control
draft-holmer-rmcat-transport-wide-cc-extensions-01
[10] Bandwidth Estimation in WebRTC (and the new Sender Side BWE) http://www.rtcbits.com/2017/01/bandwidth-estimation-in-webrtc-and-new.html