網(wǎng)絡(luò)的波動(dòng)帶來的卡頓直接影響著用戶的體驗(yàn),在WebRTC中設(shè)計(jì)了一套基于延遲和丟包反饋的擁塞機(jī)制(GCC)和帶寬調(diào)節(jié)策略來保證延遲、質(zhì)量和網(wǎng)路速度之間平衡。
在視頻通信的技術(shù)領(lǐng)域WebRTC已成為主流的技術(shù)標(biāo)準(zhǔn),WebRTC包涵了諸多優(yōu)秀的技術(shù),譬如:音頻數(shù)字信號(hào)處理技術(shù)(AEC, NS, AGC)、編解碼技術(shù)、實(shí)時(shí)傳輸技術(shù)、P2P技術(shù)等,這些技術(shù)目的都是為了實(shí)現(xiàn)更好實(shí)時(shí)音視頻方案。但是在高分辨率視頻通信過程中,通信時(shí)延、圖像質(zhì)量下降和丟包卡頓是經(jīng)常發(fā)生的事,甚至在WiFi環(huán)境下,一次視頻重發(fā)的網(wǎng)絡(luò)風(fēng)暴可以引起WiFi網(wǎng)絡(luò)間歇性中斷,通信延遲和圖像質(zhì)量之間存在的排斥關(guān)系是實(shí)時(shí)視頻過程中的主要矛盾。
分析WebRTC是如何解決這個(gè)矛盾之前,先來看看我們?cè)谠诰€教育互動(dòng)的生產(chǎn)環(huán)境統(tǒng)計(jì)到的視頻延遲和人感官的關(guān)系,大致如下:
0 ~ 400毫秒 | 人感覺不到視頻在通信過程中的延遲 |
400 ~ 800毫秒 | 人能感覺到輕微延遲,但不影響通信互動(dòng) |
800毫秒以上 | 人能感覺到延遲而且影響通信互動(dòng) |
也就是說,通信過程中最好將視頻延遲控制在800毫秒以內(nèi)。除了延遲,視頻圖像質(zhì)量也是個(gè)對(duì)人感官產(chǎn)生差異的關(guān)鍵因素,我們以640x480分辨率每秒24幀的H264編碼情況下視頻碼率和人感官之間的關(guān)系(這組數(shù)據(jù)是我們通過小范圍線上用戶投票打分的數(shù)據(jù)):
800kbps以上 | 人對(duì)視頻清晰度滿意,感覺不到視頻圖像中的信息丟失 |
480 ~ 800kbps | 人對(duì)視頻清晰度基本滿意,有時(shí)能感覺到視頻圖像中的信息丟失 |
480kbps以下 | 人對(duì)視頻清晰度不滿意,大部分時(shí)候無法辨認(rèn)圖像中的細(xì)節(jié)信息 |
從上面的描述可以知道視頻質(zhì)量保持在一個(gè)可讓人接受的質(zhì)量范圍是需要比較大的帶寬碼率支持的,如果加上控制延遲,則更需要網(wǎng)絡(luò)有很好速度和穩(wěn)定性。但是很不幸,我們現(xiàn)階段的移動(dòng)網(wǎng)絡(luò)和家用WiFi并不是我們想象中的那么好,很難做到在實(shí)時(shí)視頻通信中一個(gè)讓人非常滿意的程度。為了解決以上幾個(gè)問題,WebRTC設(shè)計(jì)了一套基于延遲和丟包反饋的擁塞機(jī)制(GCC)和帶寬調(diào)節(jié)策略來保證延遲、質(zhì)量和網(wǎng)路速度之間平衡,這是一個(gè)持續(xù)循環(huán)過程,如下圖:
圖1:擁塞控制循環(huán)示意圖
1)estimator通過RTCP的feedback反饋過來的包到達(dá)延遲增量和丟包率信息計(jì)算出網(wǎng)絡(luò)擁塞狀態(tài)并評(píng)估出適合當(dāng)前網(wǎng)絡(luò)傳輸?shù)拇a率,根據(jù)這個(gè)碼率改變視頻編碼器碼率,然后改變pacer的碼率
2)pacer會(huì)根據(jù)這個(gè)碼率改變pacer的網(wǎng)絡(luò)發(fā)送速度和padding比例,并用新的網(wǎng)絡(luò)發(fā)送速度來定時(shí)觸發(fā)發(fā)包事件。
3)sender收到pacer的發(fā)送事件,進(jìn)行RTP報(bào)文發(fā)送。
4)receiver接收到RTP報(bào)文,進(jìn)行arrival time統(tǒng)計(jì)和丟包統(tǒng)計(jì)
5)feedback定時(shí)對(duì)receiver統(tǒng)計(jì)的信息進(jìn)行RTCP編碼,并反饋到發(fā)送端的estimator進(jìn)行新一輪的碼率評(píng)估。
以上是整個(gè)WebRTC擁塞控制和帶寬調(diào)節(jié)過程,下面這個(gè)示意圖是這個(gè)過程涉及到WebRTC內(nèi)部模塊關(guān)系。
圖2:WebRTC的擁塞控制模塊關(guān)系圖
需要說明的是紅框中基于接收端的kalman filter帶寬評(píng)估模型已經(jīng)在新版本的WebRTC中不采用了,只做了向前版本兼容,新版本的WebRTC都是采用發(fā)送端的trendline濾波器來做延遲帶寬評(píng)估,本文中重點(diǎn)是介紹基于trendline濾波的評(píng)估模型,下面依次來分析WebRTC的這五個(gè)過程。
1 estimator
estimator的功能就是通過接收端反饋過來的包到達(dá)時(shí)刻信息、丟包信息和REMB信息進(jìn)行當(dāng)前網(wǎng)絡(luò)狀態(tài)的碼率評(píng)估,WebRTC擁塞控制有兩部分:基于延遲的擁塞控制和基于丟包的擁塞控制,它是一個(gè)盡力而為的擁塞控制算法,犧牲了擁塞控制的公平性換取盡量大的吞吐量。從設(shè)計(jì)結(jié)構(gòu)來描述向它輸入延遲和丟包信息,它就會(huì)輸出一個(gè)適應(yīng)當(dāng)前網(wǎng)絡(luò)狀態(tài)的碼率值。示意圖如下:
圖3:WebRTC的CC estimator輸入與輸出
從上圖可以看出,estimator基于延遲的擁塞控制是通過trendline濾波再進(jìn)行過載判斷,最后根據(jù)過載情況進(jìn)行aimd碼率調(diào)控評(píng)估出一個(gè)bwe bitrate碼率,這個(gè)碼率會(huì)合丟包評(píng)估出來的碼率和remb來決定最后的碼率。
1.1 基于延遲的擁塞控制
基于延遲的擁塞控制是通過每組包的到達(dá)時(shí)間的延遲差(delta delay)的增長趨勢來判斷網(wǎng)絡(luò)是否過載,如果過載進(jìn)行碼率下調(diào),如果處于平衡范圍維持當(dāng)前碼率,如果是網(wǎng)絡(luò)承載不飽滿進(jìn)行碼率上調(diào)。這里有幾個(gè)關(guān)鍵技術(shù):包組延遲評(píng)估、濾波器趨勢判斷、過載檢測和碼率調(diào)節(jié)。
1.1.1 包組與延遲
WebRTC在評(píng)估延遲差的時(shí)候不是對(duì)每個(gè)包進(jìn)行估算,而是采用了包組間進(jìn)行延遲評(píng)估,這符合視頻傳輸(視頻幀是需要切分成多個(gè)UDP包)的特點(diǎn),也減少了頻繁計(jì)算帶來的誤差。那么什么是包組呢?就是距包組中第一個(gè)包的發(fā)送時(shí)刻t0小于5毫秒發(fā)送的所有的包成為一組,第一個(gè)超過5毫秒的包作為下一個(gè)包組第一個(gè)包。為了更好的說明包組和延遲間的關(guān)系,先來看示意圖:
圖4:包組與延遲示意圖
上圖中有兩個(gè)包組G1和G2, 其中第100號(hào)包與103號(hào)包的時(shí)間差小于5毫秒,那么100 ~ 103被劃作一個(gè)包組。104與100之間時(shí)間超過5毫秒,那么104就是G2的第一個(gè)包,它與105、106、107劃作一個(gè)包組。知道了包組的概念,那么我們?cè)趺赐ㄟ^包組的延遲信息得到濾波器要的評(píng)估參數(shù)呢?濾波器需要的三個(gè)參數(shù):發(fā)送時(shí)刻差值(delta_timestamp)、到達(dá)時(shí)刻差值(delta_arrival)和包組數(shù)據(jù)大小差值(delta_size)。從上圖可以得出:
1.1.2 濾波器
我們通過包組信息計(jì)算到了delta_timestamp、delta_arrival和delta_size,那么下一步就是進(jìn)行數(shù)據(jù)濾波來評(píng)估延遲增長趨勢。在WebRTC實(shí)現(xiàn)了兩種濾波器來進(jìn)行延遲增長趨勢的評(píng)估,分別是:kalman filter和trendline filter, 從圖2中我們知道kalman filter是運(yùn)行在接收端的,我在這里以不做介紹,有興趣的可以參考https://www.jianshu.com/p/bb34995c549a。
這里介紹trendline filter,我們知道如果平穩(wěn)網(wǎng)速下傳輸數(shù)據(jù)的延遲時(shí)間就是數(shù)據(jù)大小除以速度,如果這數(shù)據(jù)塊很大,超過恒定網(wǎng)速下延遲上限,這意味著要它要占用其他后續(xù)數(shù)據(jù)塊的傳輸時(shí)間,那么如此往復(fù),網(wǎng)絡(luò)就產(chǎn)生了延遲和擁塞。Trendline filter通過到達(dá)時(shí)間差、發(fā)送時(shí)間差和數(shù)據(jù)大小來得到一個(gè)趨勢增長值,如果這個(gè)值越大說明網(wǎng)絡(luò)延遲越來越嚴(yán)重,如果這個(gè)值越小,說明延遲逐步下降。以下是計(jì)算這個(gè)值的過程。
先計(jì)算單個(gè)包組傳輸增長的延遲,可以記作:
然后做每個(gè)包組的疊加延遲,可以記作:
在通過累積延遲計(jì)算一個(gè)均衡平滑延遲值,alpha=0.9可以記作:
然后統(tǒng)一對(duì)累計(jì)延遲和均衡平滑延遲再求平均,分別記作:
我們將第i個(gè)包組的傳輸持續(xù)時(shí)間記作:
趨勢斜率分子值為:
趨勢斜率分母值為:
最終的趨勢值為:
1.1.3過載檢測
在計(jì)算得到trendline值后WebRTC通過動(dòng)態(tài)閾值gamma_1進(jìn)行判斷擁塞程度,trendline乘以周期包組個(gè)數(shù)就是m_i,以下是判斷擁塞程度的偽代碼:
通過以上偽代碼就可以判斷出當(dāng)前網(wǎng)絡(luò)負(fù)載狀態(tài)是否發(fā)生了過載,如果發(fā)生過載,WebRTC是通過一個(gè)有限狀態(tài)機(jī)來進(jìn)行網(wǎng)絡(luò)狀態(tài)遷徙,關(guān)于狀態(tài)機(jī)細(xì)節(jié)可以參看下圖:
圖5:過載檢測狀態(tài)機(jī)
從上圖可以看出,網(wǎng)絡(luò)狀態(tài)機(jī)的狀態(tài)遷徙是由于網(wǎng)絡(luò)過載狀態(tài)發(fā)生了變化,所以狀態(tài)遷徙作為了aimd帶寬調(diào)節(jié)的觸發(fā)事件,aimd根據(jù)當(dāng)前所處的網(wǎng)絡(luò)狀態(tài)進(jìn)行帶寬調(diào)節(jié),其過程是處于Hold狀態(tài)表示維持當(dāng)前碼率,處于Decr狀態(tài)表示需要進(jìn)行碼率遞減,處于Incr狀態(tài)需要進(jìn)行碼率遞增。那他們是怎么遞增和遞減的呢?WebRTC引入了aimd算法解決這個(gè)問題。
1.1.4 AIMD碼率調(diào)節(jié)
aimd的全稱是Additive Increase Multiplicative Decrease,意思是:和式增加,積式減少。aimd controller是TCP底層的碼率調(diào)節(jié)概念,但是WebRTC并沒有完全照搬TCP的機(jī)制,而是設(shè)計(jì)了套自己的算法,用公式表示為:
如果處于Incr狀態(tài),增加碼率的方式分為兩種:一種是通信會(huì)話剛剛開始,相當(dāng)于TCP慢啟動(dòng),它會(huì)進(jìn)行一個(gè)倍數(shù)增加,當(dāng)前使用的碼率乘以系數(shù),系數(shù)是1.08;如果是持續(xù)在通信狀態(tài),其增加的碼率值是當(dāng)前碼率在一個(gè)RTT時(shí)間周期所能傳輸?shù)臄?shù)據(jù)速率。
如果處于Decrease狀態(tài),遞減原則是:過去500ms時(shí)間窗內(nèi)的最大acked bitrate乘上系數(shù)0.85,acked bitrate通過feedback反饋過來的報(bào)文序號(hào)查找本地發(fā)送列表就可以得到。
aimd根據(jù)上面的規(guī)則最終計(jì)算到的碼率就是基于延遲擁塞評(píng)估到的bwe bitrate碼率。
1.2基于丟包的擁塞控制
除了延遲因素外,WebRTC還會(huì)根據(jù)網(wǎng)絡(luò)的丟包率進(jìn)行擁塞控制碼率調(diào)節(jié),描述如下:
解釋下上面的公式:
當(dāng)丟包率>2%時(shí),這個(gè)時(shí)候會(huì)將碼率(base bitrate)增長5%,這個(gè)碼率(base bitrate)并不是當(dāng)前及時(shí)碼率,而是單位時(shí)間窗周期內(nèi)出現(xiàn)的最小碼率,WebRTC將這個(gè)時(shí)間窗周期設(shè)置在1000毫秒內(nèi)。因?yàn)閘oss fraction是從接收端反饋過來的,中間會(huì)有時(shí)間差,這樣做的目的是防止網(wǎng)絡(luò)間歇性統(tǒng)計(jì)造成的網(wǎng)絡(luò)碼率增長過快而網(wǎng)絡(luò)反復(fù)波動(dòng)。
當(dāng) 2% < 丟包率 < 10%,維持當(dāng)前的碼率值
當(dāng) 丟包率 >= 10%, 按丟包率進(jìn)行當(dāng)前碼率遞減,等到新的碼率值
丟包率決策出來的碼率(base bitrate)只是一個(gè)參考值,WebRTC實(shí)際采用的帶寬是base bitrate、remb bitrate和bwe bitrate中的最小值,這個(gè)最小值作為estimator最終評(píng)估出來的碼率
2 pacer
在estimator根據(jù)網(wǎng)絡(luò)狀態(tài)決策出新的通信碼率(target bitrate),它會(huì)將這個(gè)碼率設(shè)置到pacer當(dāng)中,要求pacer按照新的碼率來計(jì)算發(fā)包頻率。因?yàn)樵谝曨l通信中,單幀視頻可能有上百KB,如果是當(dāng)視頻幀被編碼器編碼出來后,就立即進(jìn)行RTP打包發(fā)送,瞬時(shí)會(huì)發(fā)送大量的數(shù)據(jù)到網(wǎng)絡(luò)上,可能會(huì)引起網(wǎng)絡(luò)衰減和通信惡化。WebRTC引入pacer,pacer會(huì)根據(jù)estimator評(píng)估出來的碼率,按照最小單位時(shí)間(5ms)做時(shí)間分片進(jìn)行遞進(jìn)發(fā)送數(shù)據(jù),避免瞬時(shí)對(duì)網(wǎng)絡(luò)的沖擊。pacer的目的就是讓視頻數(shù)據(jù)按照評(píng)估碼率均勻的分布在各個(gè)時(shí)間片里發(fā)送,所以在弱網(wǎng)的WiFi環(huán)境,pacer是個(gè)非常重要的關(guān)鍵步驟。以下WebRTC中pacer的模型關(guān)系:
圖6:pacer模型圖
WebRTC中pacer的流程比較清晰,分為三步:
1)如果一幀圖像被編碼和RTP切分打包后,先會(huì)將RTP報(bào)文存在待發(fā)送的隊(duì)列中,并將報(bào)文元數(shù)據(jù)(packet id, size, timestamp, 重傳標(biāo)示)送到pacer queue進(jìn)行排隊(duì)等待發(fā)送,插入隊(duì)列的元數(shù)據(jù)會(huì)進(jìn)行優(yōu)先級(jí)排序。
2)pacer timer會(huì)觸發(fā)一個(gè)定時(shí)任務(wù)事件來計(jì)算budget,budget會(huì)算出當(dāng)前時(shí)間片網(wǎng)絡(luò)可以發(fā)送多少數(shù)據(jù),然后從pacer queue當(dāng)中取出報(bào)文元數(shù)據(jù)進(jìn)行網(wǎng)絡(luò)發(fā)送。
3)如果pacer queue沒有更多待發(fā)送的報(bào)文,但budget卻還可以發(fā)送更多的數(shù)據(jù),這個(gè)時(shí)候pacer會(huì)進(jìn)行padding報(bào)文補(bǔ)充。
從上面的步驟描述中可以看出pacer有幾個(gè)關(guān)鍵技術(shù):pace queue、padding、budget。
2.1 pace queue與優(yōu)先級(jí)
pace queue是一個(gè)基于優(yōu)先級(jí)排序的多維鏈表,它并不是一個(gè)先進(jìn)先出的fifo,而是一個(gè)按優(yōu)先級(jí)排序的list。
報(bào)文優(yōu)先級(jí)規(guī)則
1)優(yōu)先級(jí)高的報(bào)文排在fifo的前面,低的排在后面。
2)優(yōu)先級(jí)是最先判斷報(bào)文的QoS等級(jí),等級(jí)越小的優(yōu)先級(jí)越高
3)其次是判斷重發(fā)標(biāo)示,重發(fā)的報(bào)文比普通報(bào)文的優(yōu)先級(jí)更高
4)再次是判斷視頻幀timestamp,越早的視頻幀優(yōu)先級(jí)更高。
pacer每次觸發(fā)發(fā)送事件時(shí)是先從queue的最前面取出優(yōu)先級(jí)最高的報(bào)文進(jìn)行發(fā)送,這樣做的目的是讓視頻在傳輸?shù)倪^程中延遲盡量小,重傳的報(bào)文盡快能到達(dá)防止等待卡頓。pace queue還可以設(shè)置最大延遲,如果超過最大延遲,會(huì)計(jì)算queue中數(shù)據(jù)發(fā)送所需要的碼率,并且會(huì)把這個(gè)碼率替代target bitrate作為budget參考碼率來加速發(fā)送。
2.2 budget
budget是個(gè)評(píng)估單位時(shí)間內(nèi)可以發(fā)送多少數(shù)據(jù)量的一個(gè)機(jī)制,因?yàn)閜acer是會(huì)根據(jù)pace timer定時(shí)來觸發(fā)發(fā)送檢查。Budget會(huì)根據(jù)評(píng)估出來的參考碼率計(jì)算這次定時(shí)事件能發(fā)送多少字節(jié),可以表示為:
delta time是上次檢查時(shí)間點(diǎn)和這次檢查時(shí)間點(diǎn)的時(shí)間差。
target bitrate是pacer的參考碼率,是由estimator根據(jù)網(wǎng)絡(luò)狀態(tài)評(píng)估出來的。
remain_bytes每次觸發(fā)發(fā)包時(shí)會(huì)減去發(fā)送報(bào)文的長度size,如果remain_bytes > 0,繼續(xù)從pace queue中取下一個(gè)報(bào)文進(jìn)行發(fā)送,直到remain_bytes <=0 或者 pace queue沒有更多的報(bào)文。
2.3 pacer延遲
那么肯定有人會(huì)有疑問pacer queue和budget進(jìn)定量計(jì)算來發(fā)送網(wǎng)絡(luò)報(bào)文,相當(dāng)于cache等待發(fā)送,難道不會(huì)引起延遲嗎?可以肯定的說會(huì)引起延遲,但延遲不嚴(yán)重。pacer產(chǎn)生的延遲可以表示為:
假如評(píng)估出來的碼率是10mbps, 一個(gè)視頻關(guān)鍵幀的大小是300KB,那么這個(gè)關(guān)鍵幀造成的pacer delay是240毫秒。從實(shí)際應(yīng)用觀察到的關(guān)鍵幀引起的pace delay在200 ~ 400毫秒之間,這個(gè)值相對(duì)于視頻傳輸來說是比較大的,但是不嚴(yán)重。WebRTC為了減少這個(gè)延遲,會(huì)評(píng)估出盡量大的bitrate。那么怎么評(píng)估出盡量大的碼率呢?從前面的estimator描述中我們知道要發(fā)送出盡量多的數(shù)據(jù)才能評(píng)估盡量大的碼率,但是視頻編碼器不會(huì)發(fā)送多余的數(shù)據(jù),所以WebRTC引入了padding機(jī)制來保障發(fā)送盡量大的數(shù)據(jù)來探測網(wǎng)絡(luò)帶寬上限。
2.4 padding
pace padding除了保障能pace delay盡量小外,它可以讓有限的帶寬獲得盡可能好的視頻質(zhì)量。padding的工作原理很簡單,就是在單位時(shí)間片內(nèi)把budget還剩余的空閑用padding數(shù)據(jù)填滿。我個(gè)人認(rèn)為padding只是適合點(diǎn)對(duì)點(diǎn)通信,一旦涉及到多點(diǎn)分發(fā),會(huì)因?yàn)閜adding占用很多服務(wù)轉(zhuǎn)發(fā)帶寬,這并不是一件好事情。
3 sender
WebRTC的發(fā)送模塊和擁塞控制控制相關(guān)的主要是增加了附加的RTP擴(kuò)展來攜帶便宜接收端統(tǒng)計(jì)丟包率和延遲間隔的信息、配合pacer的發(fā)包策略、帶寬分配和FEC策略的信息。
3.1 RTP擴(kuò)展
WebRTC為了配合接收端進(jìn)行延遲包序列和丟包統(tǒng)計(jì)做了下列擴(kuò)展:
transport sequence傳輸通道的只增sequence,每次發(fā)送報(bào)文時(shí)自增長,配合接收端統(tǒng)計(jì)丟包、通過反饋這個(gè)sequence可以計(jì)算得到發(fā)包的時(shí)刻。
TransmissionOffset 發(fā)送報(bào)文的相對(duì)時(shí)刻,這個(gè)相對(duì)時(shí)刻值t是發(fā)送報(bào)文的絕對(duì)時(shí)刻T1和視頻幀時(shí)間戳T0差值。早期的WebRTC是在接收端進(jìn)行estimate bitrate,所以過載判斷是在接收端完成的,這個(gè)值就是為了kalman filter計(jì)算發(fā)包造成的延遲用的,新版本還攜帶這個(gè)值以便低版本的WebRTC能兼容。
3.2 packet cache
packet cache是一個(gè)key/value結(jié)構(gòu)的包緩沖池,視頻幀在進(jìn)行RTP分片打包后不會(huì)立即發(fā)送出去,而是要等待pacer的發(fā)送信號(hào)進(jìn)行發(fā)送。所以打包后會(huì)按[id,packet]鍵值對(duì)插入到packet cache中。一般packet cache會(huì)保存600個(gè)分片報(bào)文,最大9600個(gè),插入新的會(huì)將最舊的報(bào)文刪除,packet cache這樣做的目的除了配合pacer發(fā)送外,也為了后面響應(yīng)nack的丟包重傳。
3.3 NACK與丟包重傳
圖7:RTP NACK過程的示意圖
WebRTC在評(píng)估到收發(fā)端之間RTT延遲比較小的時(shí)候會(huì)采用NACK來進(jìn)行丟包補(bǔ)償,NACK是一個(gè)請(qǐng)求重發(fā)過程,其流程如上圖所示。這個(gè)過程有一個(gè)問題是在網(wǎng)絡(luò)抖動(dòng)和丟包很厲害的情況下有可能造成同一時(shí)刻收到很多NACK的重傳請(qǐng)求,發(fā)送端瞬間把這些重傳請(qǐng)求放入pacer中進(jìn)行重發(fā),這樣pacer的延遲會(huì)增大,而且pace的參考碼率會(huì)隨著pace queue的延遲控制變的很大而出現(xiàn)間歇性網(wǎng)絡(luò)風(fēng)暴。WebRTC在處理NACK重傳時(shí)設(shè)計(jì)了一個(gè)重傳碼率控制器,其設(shè)計(jì)原理是通過統(tǒng)計(jì)單位時(shí)間窗口周期中發(fā)送的字節(jié)數(shù)據(jù)來限流,如果這個(gè)時(shí)間窗內(nèi)發(fā)送的數(shù)據(jù)的碼率大于estimator評(píng)估的碼率,不進(jìn)行當(dāng)前NACK請(qǐng)求的重傳,等待下一個(gè)NACK。
3.4 FEC與碼率分配
WebRTC應(yīng)對(duì)丟包時(shí)除了NACK方式,在收發(fā)端之間RTT很大時(shí)候會(huì)開啟FEC來進(jìn)行丟包補(bǔ)償,我們?cè)谶@里不介紹FEC具體算法,只介紹FEC的碼率分配策略。從整個(gè)通信機(jī)制我們很容易得出這樣一個(gè)共識(shí):
FEC bitrate到底應(yīng)該設(shè)置多大呢?它先根據(jù)feedback中反饋過來的丟包率(loss fraction)來確定使用哪一種FEC,在根據(jù)每中FEC和丟包率來確定FEC使用的碼率,但需要滿足一下條件:
feedback的碼率被設(shè)定為target bitrate的5%,WebRTC是通過控制feekback的頻率來進(jìn)行調(diào)控分配的。padding bitrate是通過pacer queue和budget來控制的。Target bitrate減去這些碼率之和就是給視頻編碼器的碼率。每次estimator評(píng)估出來碼率后,會(huì)先進(jìn)行這些計(jì)算得到最后的video bitrate,并將這個(gè)值作為編碼器的編碼碼率,以此來達(dá)到防止擁塞的目的。
4 receiver
receiver模塊的工作相對(duì)來說比較簡單,它就做三件事情:記錄每個(gè)報(bào)文的到達(dá)時(shí)刻(arrival timestamp)、丟包率(lost fraction)和receiver bitrate。早期的WebRTC提供了圖2紅框當(dāng)中kalman filter評(píng)估碼率的評(píng)估器,因?yàn)閗alman filter怕抖動(dòng)特性且需要借助remb心跳進(jìn)行反饋,remb的反饋周期是1秒,在收發(fā)端網(wǎng)絡(luò)間歇性斷開或者大抖動(dòng)下,容易失效,所以WebRTC采用了在發(fā)送端進(jìn)行估算,整個(gè)邏輯也更加簡便。
4.1 報(bào)文到達(dá)時(shí)間
圖8:到達(dá)報(bào)文統(tǒng)計(jì)圖
上圖是一個(gè)統(tǒng)計(jì)RTP報(bào)文到達(dá)時(shí)刻的序列圖,圖中的seq是RTP擴(kuò)展中的transport sequence,接收端用一個(gè)k/v([seq,arrival timestamp])鍵值對(duì)數(shù)據(jù)結(jié)構(gòu)來保存最近500毫秒未反饋的到達(dá)時(shí)刻信息,通過時(shí)間窗口周期來進(jìn)行淘汰老的到達(dá)時(shí)刻記錄。
4.2 丟包率計(jì)算
丟包率計(jì)算過程是這樣的,我們把上次統(tǒng)計(jì)丟包率時(shí)刻的最大sequence記著prev_seq, 把當(dāng)前收到的最大sequence記著cur_seq,當(dāng)前統(tǒng)計(jì)丟失的報(bào)文記著count,WebRTC在RTCP中描述丟包率采用的是uint8,為了保證精確度將256記著100%的丟包率,那么很容易得:
這里需要提的是WebRTC在統(tǒng)計(jì)報(bào)文是否丟失是通過sequence的連續(xù)性和網(wǎng)絡(luò)的jitter時(shí)間來確定的,只有落在jitter抖動(dòng)范圍之外的丟包才是算是作丟包。
4.3 接收碼率統(tǒng)計(jì)
接收端碼率統(tǒng)計(jì)采用的是最近單位時(shí)間窗(1000毫秒)周期內(nèi)收到的的字節(jié)數(shù)來計(jì)算,WebRTC設(shè)計(jì)了一個(gè)1毫秒為最小單位的窗口數(shù)組來進(jìn)行統(tǒng)計(jì),每個(gè)最小單位是數(shù)字,這個(gè)數(shù)字是在這個(gè)時(shí)刻收到的網(wǎng)絡(luò)數(shù)據(jù)大小,大致的示意圖如下:
圖9:接收碼率統(tǒng)計(jì)示意圖
計(jì)算碼率只需要將紅框中所有的數(shù)字加起來,當(dāng)時(shí)間發(fā)生改變后,就紅框就向右移動(dòng)并且填寫新時(shí)刻接收到的數(shù)據(jù)大小,等下一個(gè)統(tǒng)計(jì)時(shí)刻既可。
5 feedback
前面介紹的estimator依賴于feedback反饋的報(bào)文到達(dá)時(shí)刻和丟包率來進(jìn)評(píng)估碼率的,也就是說feedback需要將這些信息及時(shí)反饋給接收端,主要是記錄的報(bào)文到達(dá)時(shí)刻、通道丟包率和remb帶寬。因?yàn)閳?bào)文到達(dá)時(shí)刻和丟包率統(tǒng)計(jì)都是多個(gè)數(shù)據(jù)項(xiàng),WebRTC利用了report block來進(jìn)行編碼存放。為了有效的利用RTCP的report block空間,WebRTC采用了相對(duì)時(shí)間轉(zhuǎn)換和位壓縮算法來對(duì)到達(dá)時(shí)間序列做編碼壓縮。
除了report編碼,feedback的周期也很重要,如果是單純的remb反饋,一般是1秒一次反饋。但如果是需要反饋報(bào)文的到達(dá)時(shí)間,它會(huì)根據(jù)占用5%的target bitrate來計(jì)算發(fā)送feedback的時(shí)間間隔,計(jì)算流程如下:
feedback interval需要滿足一個(gè)條件:50ms < interval < 250ms,這個(gè)條件中的 50ms< internal是為了防止interval太小造成發(fā)送feedback太過頻繁而消耗網(wǎng)絡(luò)性能,而interval < 250ms是為了防止feedback頻次太低造成estimator反應(yīng)遲鈍。
6 總結(jié)
以上就是WebRTC擁塞控制和碼率調(diào)節(jié)策略的5個(gè)過程,里面涉及到很多傳輸相關(guān)的技術(shù),我在這里也是簡單介紹了下其工作原理,很多細(xì)節(jié)的并沒有描述出來,也很難描述出來,有興趣的同學(xué)可以翻看WebRTC的源代碼。如果覺得webRTC代碼費(fèi)勁,我照虎畫貓將WebRTC的擁塞控制用C重新實(shí)現(xiàn)了個(gè)簡易版本,但是去掉了padding,可到https://github.com/yuanrongxi/razor下載。
6.1 效果
WebRTC的GCC在網(wǎng)絡(luò)適應(yīng)上表現(xiàn)還是比較良好的,既然兼顧延遲,也能兼顧丟包,網(wǎng)絡(luò)發(fā)生擁塞時(shí)在2 ~ 3秒內(nèi)能評(píng)估出相對(duì)的碼率來適應(yīng)當(dāng)前的網(wǎng)絡(luò)狀態(tài),但是會(huì)造成短時(shí)間的卡頓。對(duì)于網(wǎng)絡(luò)發(fā)生間歇性丟包,在2秒左右能將傳輸碼率適配到當(dāng)前網(wǎng)絡(luò)狀態(tài)。它在網(wǎng)絡(luò)相對(duì)穩(wěn)定且延遲較大的網(wǎng)絡(luò)進(jìn)行高分辨率傳輸時(shí),視頻很穩(wěn)定,適合長距離延遲穩(wěn)定的網(wǎng)絡(luò)環(huán)境。在弱網(wǎng)環(huán)境下,WebRTC容易將碼率降到很低而造成圖像失真。
6.2 網(wǎng)絡(luò)大抖動(dòng)
對(duì)于亂序和抖動(dòng)WebRTC的擁塞控制顯得有點(diǎn)無力,如果抖動(dòng)超過rtt*2/3時(shí),基于kalman filter的帶寬評(píng)估機(jī)制不起作用(不知道是不是我用錯(cuò)了);基于trendline濾波的評(píng)估機(jī)制波動(dòng)很大,敏感度不夠,不能完全反應(yīng)當(dāng)前的網(wǎng)絡(luò)過載狀態(tài),尤其是在終端Wi-Fi擁擠的情況下,比較容易造成間歇性風(fēng)暴。
6.3 延遲問題
WebRTC的pacer在傳輸大分辨率視頻時(shí),關(guān)鍵幀會(huì)引起大約200毫秒的延時(shí),尤其是在移動(dòng)4G網(wǎng)絡(luò)下這個(gè)問題更加明顯,海康威視工程師鄭鵬提出了用H.264的intre_refresh模式來應(yīng)對(duì),在測試過程中確實(shí)比較適合WebRTC用來減少關(guān)鍵幀造成的延遲,但是intre_refresh是普通模式編碼CPU的3倍左右,而且很多移動(dòng)設(shè)備的編碼器不一定支持。
總之,WebRTC的擁塞控制存在反應(yīng)慢、怕抖動(dòng)的特性,但是這塊也是WebRTC改進(jìn)最為頻繁的模塊,幾乎每個(gè)版本都有新的改進(jìn)。要徹底解決這樣的問題,需要從視頻編碼器和網(wǎng)絡(luò)傳輸進(jìn)行融合來解決,以后我用單獨(dú)的篇幅來介紹下這樣的解決方案。
-
擁塞控制
+關(guān)注
關(guān)注
0文章
14瀏覽量
8468 -
WebRTC
+關(guān)注
關(guān)注
0文章
56瀏覽量
11203
原文標(biāo)題:WebRTC的擁塞控制和帶寬策略
文章出處:【微信號(hào):livevideostack,微信公眾號(hào):LiveVideoStack】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論