背景介紹
實時音視頻(pin)通話(hua)在當前的生活中是(shi)無時不刻(ke)存(cun)在的,包括(kuo)社交(jiao)、安(an)防、交(jiao)通等等各個(ge)方面都(dou)需(xu)要(yao)。用戶(hu)場景復雜多變、要(yao)求(qiu)嚴(yan)苛、網絡(luo)環境不一致等給實時音視頻(pin)通話(hua)帶來(lai)很大條件。我們在這方向稍微做(zuo)了一些(xie)工作,雖然和(he)(he)(he)其他大廠的優化工作相比,我們還處于(yu)劣勢(shi),還有(you)很多可以優化和(he)(he)(he)改(gai)進的,但是(shi)目(mu)前的一些(xie)進展和(he)(he)(he)工作內容和(he)(he)(he)大家(jia)分享一下(xia)。
0.1 網絡傳輸:
我們知道(dao)網(wang)絡(luo)(luo)傳輸目前有(you) TCP 和 UDP 兩種,相關(guan)優缺點(dian)如(ru)下腦圖;而(er)影響網(wang)絡(luo)(luo)傳輸質量也(ye)有(you)很(hen)多原(yuan)(yuan)因(yin):包括網(wang)絡(luo)(luo)擁塞(sai)、網(wang)絡(luo)(luo)丟包等(deng)等(deng)。這些(xie)因(yin)素直接決定當前實(shi)時視頻(pin)通(tong)話的質量,也(ye)會給用戶帶(dai)來很(hen)大的體驗影響。這也(ye)是我們為什么要進行優化的基本(ben)原(yuan)(yuan)因(yin)了(le)。

0.2 弱網定義:
對(dui)于實時音視(shi)頻(pin)(pin)通話來(lai)說(shuo):網(wang)(wang)絡(luo)的復雜(za)性(xing)、異構性(xing)、協議部分不(bu)規范性(xing)、網(wang)(wang)絡(luo)異常,網(wang)(wang)絡(luo)錯誤等(deng)各種網(wang)(wang)絡(luo)環境被破壞的特性(xing)都稱之為(wei)弱網(wang)(wang)。弱網(wang)(wang)環境無法(fa)提供高質量的網(wang)(wang)絡(luo)傳輸,對(dui)于接(jie)收端就是無法(fa)收到連續(xu)的媒(mei)體包,造(zao)成聲音異常、視(shi)頻(pin)(pin)馬賽克、花屏(ping)、黑屏(ping)等(deng)現象,對(dui)于音視(shi)頻(pin)(pin)實時通話來(lai)說(shuo)是非(fei)常致命的,直接(jie)影響(xiang)到用(yong)戶的體驗,造(zao)成產品質量問題(ti)或者客訴問題(ti)。

0.3 實(shi)時音視(shi)頻特(te)點
對(dui)(dui)于(yu)(yu)實時(shi)(shi)音視(shi)頻(pin)通(tong)話來說(shuo)要(yao)求(qiu)最高(gao)(gao)的(de)(de)(de)條(tiao)件低(di)(di)延(yan)遲和高(gao)(gao)質(zhi)(zhi)(zhi)量(liang)(liang)(liang)(liang),這(zhe)(zhe)一對(dui)(dui)特(te)性(xing)的(de)(de)(de)存(cun)在就(jiu)是天生(sheng)的(de)(de)(de)矛盾結合體(ti)。高(gao)(gao)質(zhi)(zhi)(zhi)量(liang)(liang)(liang)(liang)就(jiu)要(yao)求(qiu)發送(song)端盡可能(neng)發送(song)高(gao)(gao)分辨率,高(gao)(gao)質(zhi)(zhi)(zhi)量(liang)(liang)(liang)(liang)的(de)(de)(de)音視(shi)頻(pin)流(liu),對(dui)(dui)于(yu)(yu)帶(dai)寬和網絡環(huan)(huan)境要(yao)求(qiu)比較高(gao)(gao),不允(yun)許有(you)各種丟(diu)(diu)包、高(gao)(gao)抖(dou)動(dong)的(de)(de)(de)現象(xiang)存(cun)在;而低(di)(di)延(yan)遲則對(dui)(dui)于(yu)(yu)網絡環(huan)(huan)境沒有(you)那么嚴苛(ke),是允(yun)許存(cun)在一定丟(diu)(diu)包量(liang)(liang)(liang)(liang)、允(yun)許一定范(fan)圍內的(de)(de)(de)接收抖(dou)動(dong)的(de)(de)(de),否則只能(neng)用空間換時(shi)(shi)間,導致(zhi)音視(shi)頻(pin)實時(shi)(shi)性(xing)時(shi)(shi)效,無法達(da)到低(di)(di)延(yan)遲的(de)(de)(de)要(yao)求(qiu)。所以(yi)這(zhe)(zhe)是一對(dui)(dui)矛與盾的(de)(de)(de)故事。只能(neng)在矛上尋求(qiu)突破(po),在盾上給予保(bao)護(hu),才(cai)能(neng)滿足這(zhe)(zhe)樣苛(ke)刻的(de)(de)(de)條(tiao)件。

一 FEC
webrtc FEC 的實現(xian)方式有三種:RED(rfc2198)、ULPFEC(rfc5109)、FLEXFEC(還未(wei)通(tong)過)。但是 Ulpfec 是套用了(le) RED 的殼進(jin)行(xing)傳輸的,所以我們采用的是 ULPFEC 進(jin)行(xing) FEC 保(bao)護。

其基本原理是:在(zai)發送端,針對媒(mei)體(ti)包增加一(yi)(yi)定冗(rong)余 FEC 包,FEC 包是通過異或(huo) XOR 得到的。如(ru)果在(zai)網絡傳輸過程(cheng)中丟掉了一(yi)(yi)部分媒(mei)體(ti)包,則在(zai)接收端通過接收到的媒(mei)體(ti)包和 FEC 包進行異或(huo) XOR 得到丟失的媒(mei)體(ti)包,這(zhe)樣就不用(yong)發送 NACK 重發包占用(yong)網絡資源了。
由于這部(bu)分在 WebRTC 中已(yi)經實現的比較好,只需要進行兼容(rong)性測試即可,這部(bu)分沒(mei)有作為(wei)重點優化(hua)對象(xiang),沿用(yong) WebRTC 中內(nei)容(rong)即可。
二 NACK
2.1 NACK 介紹:
NACK 代表否(fou)定(ding)確(que)認(ren)。 它是 WebRTC 中的(de)錯誤恢復機制之一(yi)。NACK 是接收(shou)端表明它沒有收(shou)到特定(ding)數據包的(de)一(yi)種方式。
NACK 消息通過 RTCP 發送(song)給媒體的(de)發送(song)方,后者需要根據(ju)(ju)其在緩存(cun)中的(de)可用(yong)性(xing)以(yi)及(ji)對(dui)重(zhong)傳(chuan)有用(yong)性(xing)的(de)估(gu)計(是否可以(yi)使用(yong))來(lai)決定是否重(zhong)傳(chuan)丟失的(de)數據(ju)(ju)包(bao)(bao) 它曾(ceng)經收到。發送(song)端(duan)維(wei)護一個緩沖隊(dui)列(lie)(lie),如果(guo)重(zhong)發包(bao)(bao)在緩沖隊(dui)列(lie)(lie)中則(ze)從緩沖隊(dui)列(lie)(lie)中取出(chu)再次發送(song);如果(guo)沒有在緩沖隊(dui)列(lie)(lie)中,則(ze)不再發送(song),這樣解(jie)碼端(duan)就(jiu)無法(fa)收到重(zhong)發包(bao)(bao)了。

2.2 優化和改(gai)進:
由于當前系(xi)統中采用的仍然是(shi)舊版本中的 NACK 流程,具體(ti)流程如下:
RTP 模塊解封包后(hou),將數據包按(an)照(zhao)到(dao)達順序(xu)依次傳送到(dao) JitterBuffer 模塊中;
每個數據包(bao)在插入(ru) JitterBuffer 模塊時都需要進行序列(lie)號(hao)(hao)的(de)比(bi)較(jiao)和排序,如果序列(lie)號(hao)(hao)比(bi)較(jiao)新(xin)的(de)數據包(bao),則進行 NACK 構建,以(yi)上次保存的(de)序列(lie)號(hao)(hao)+1 為(wei)(wei)起始值(zhi),以(yi)新(xin)收到的(de)序列(lie)號(hao)(hao)為(wei)(wei)結束,將之間的(de)序列(lie)號(hao)(hao)先(xian)緩存到 missing_sequence_numbers 中;
WebRTC 在 JitterBuffer 中采用線程查詢的方式,每(mei)個(ge)一(yi)定時間進(jin)行(xing)一(yi)次遍歷,確(que)認當(dang)前 nack List 中是否存(cun)在當(dang)前時間節點沒(mei)有按(an)照順序收(shou)(shou)到的數據包,如果(guo)存(cun)在就會組裝并發送 NACK RTCP 包到發送端,請求發送對應的為接收(shou)(shou)到的數據包。
NACK 是一個未(wei)到達數據包(bao)的(de)確認過(guo)程(cheng)(cheng),原先流程(cheng)(cheng)中有很多嵌套功(gong)能,或者(zhe)流程(cheng)(cheng)復雜的(de)地(di)方,因此我們再理解的(de)基礎(chu)上做了兩次優(you)化,其兩輪優(you)化的(de)大(da)概流程(cheng)(cheng)圖如下:

還有一個 NACK 無法回避的問(wen)題時:如(ru)(ru)果網(wang)(wang)絡(luo)(luo)(luo)丟包率比(bi)(bi)較高,或者(zhe)網(wang)(wang)絡(luo)(luo)(luo)抖動,網(wang)(wang)絡(luo)(luo)(luo)異構(gou)導(dao)致網(wang)(wang)絡(luo)(luo)(luo)各種亂序到(dao)達(da)情況比(bi)(bi)較嚴重(zhong),比(bi)(bi)如(ru)(ru)抖動超過 200ms 時,某些丟失的數據包遲(chi)遲(chi)不(bu)到(dao)達(da),則該(gai)包會(hui)重(zhong)復(fu)發送多次,這樣會(hui)導(dao)致網(wang)(wang)絡(luo)(luo)(luo)擁塞(sai)的現象,特別(bie)是分辨率比(bi)(bi)較高時,極容易(yi)造成視(shi)頻幀無法完整(zheng)解(jie)碼,出現馬賽(sai)克或者(zhe)黑(hei)屏現象。
因此我們再(zai)次(ci)基礎上增加和(he)(he)修改了一些(xie)判斷(duan)條(tiao)件,進行緩(huan)存隊列和(he)(he)清空隊列判斷(duan)條(tiao)件優(you)化(hua),以及獲取完整(zheng)視(shi)頻幀流(liu)程部分(fen)調整(zheng)和(he)(he)優(you)化(hua),盡量減緩(huan)以上情況的影響(xiang),提(ti)升用戶(hu)體驗。
三 帶寬自適應
3.1 帶寬自適應(ying):
我們在(zai)進(jin)行(xing)(xing)視頻實時(shi)通話時(shi),在(zai)設(she)備(bei)端(duan)按(an)照(zhao)不同的(de)幀(zhen)(zhen)率(lv)采集(ji)(ji)數據設(she)置(zhi)的(de)參(can)(can)數,這(zhe)樣發送(song)端(duan)就維(wei)護一(yi)個最大幀(zhen)(zhen)率(lv)參(can)(can)數集(ji)(ji)。之后采集(ji)(ji)的(de)圖像進(jin)行(xing)(xing)編碼,分包發送(song)到網絡(luo)中(zhong)。但是(shi)如果網絡(luo)發生了(le)變化,仍然(ran)按(an)照(zhao)當前的(de)碼率(lv)逐幀(zhen)(zhen)發送(song)到上行(xing)(xing)網絡(luo)時(shi),亦或(huo)者采集(ji)(ji)端(duan)編碼性能不穩定無(wu)法消耗采集(ji)(ji)的(de)圖像幀(zhen)(zhen)序列,發送(song)端(duan)將采取降幀(zhen)(zhen)率(lv)或(huo)者丟幀(zhen)(zhen)的(de)方式緩解發送(song)端(duan)的(de)發送(song)壓力。
在 WebRTC 中當(dang)編碼(ma)(ma)后的傳(chuan)輸(shu)碼(ma)(ma)率過載或負(fu)載不均時,通過調用 MediaOptimization 類(lei)相關(guan)接口降低或升(sheng)高幀率進而減小或者升(sheng)高碼(ma)(ma)率,從而有效利用當(dang)前帶(dai)寬,防止網(wang)絡更差(cha),或者網(wang)絡帶(dai)寬負(fu)載不夠,影(ying)響用戶體驗。
3.2 框架圖
發(fa)送端:基(ji)于丟包率估算(suan)當前可用(yong)帶寬
接受端:基于包(bao)到達時間計(ji)算可用帶(dai)寬(kuan)
綜(zong)合:接收端發(fa)送(song) REMB 反饋(kui)給(gei)發(fa)送(song)端,然后基(ji)于發(fa)送(song)端的帶寬(kuan)估(gu)算和(he)接收端的帶寬(kuan)估(gu)算決定最終(zhong)的發(fa)送(song)速率。

3.3 發送端
發送端的帶寬(kuan)估計算法(fa)基本(ben)原理(li):是讀取 RTCP 中的丟包率信息,進而(er)通(tong)過算法(fa)來動態計算當前網絡中基本(ben)情況(kuang),并判斷(duan)是否(fou)增加或(huo)減(jian)少(shao)帶寬(kuan)資源。如果判斷(duan)需(xu)要減(jian)少(shao)帶寬(kuan)時,則(ze)采(cai)用 TFRC 算法(fa)來平滑處理(li),減(jian)弱(ruo)突然增加或(huo)者減(jian)少(shao)的風(feng)險(xian)。

3.4 接收端
接(jie)收(shou)端(duan)的帶寬估(gu)計(ji)算(suan)法基(ji)本(ben)(ben)原理:讀取收(shou)到 RTP 數據統計(ji)進而(er)估(gu)算(suan)當(dang)前網絡(luo)帶寬;WebRTC 中(zhong)采用卡爾曼濾波幀對當(dang)前幀的接(jie)收(shou)時間戳(chuo)和發送時間戳(chuo)完成基(ji)本(ben)(ben)統計(ji)和計(ji)算(suan),從而(er)估(gu)算(suan)當(dang)前網絡(luo)帶寬擁塞情(qing)況和利用率,評估(gu)和修正(zheng)帶寬大小,進而(er)影響網絡(luo)帶寬。

四 優化和改進:
4.1 優化和改進
我們(men)做(zuo)的工(gong)作主要的優化點(dian)如(ru)下:
NACK 兩輪優(you)化:包括(kuo)之(zhi)前(qian)版(ban)本算(suan)法(fa)的(de)整(zheng)體提升(重構原來 R4X 相(xiang)關(guan)代碼(ma)(ma),采用和 iOS 相(xiang)同(tong)的(de) NACK 獲(huo)取算(suan)法(fa),并在此(ci)基礎上進(jin)行緩存(cun)隊列(lie)和清(qing)空判(pan)斷條件(jian)調(diao)整(zheng)優(you)化、獲(huo)取完整(zheng)解碼(ma)(ma)幀(zhen)相(xiang)關(guan)流(liu)程優(you)化、長時(shi)間(jian)緩存(cun)幀(zhen)丟棄策略(lve)調(diao)整(zheng)等(deng)方案(an))、Jitterbuffer 參數的(de)優(you)化調(diao)整(zheng);
FEC、動(dong)態分辨(bian)率、NACK 整體策略(lve)優化:針對不(bu)同的(de)網絡(luo)條件,依據丟包(bao)(bao)率、RTT 等(deng)相關參(can)數,以及(ji) 5s 內的(de)抖動(dong)平均值(zhi)等(deng),設計一(yi)套動(dong)態調整當前組合的(de)整體方案,既增加一(yi)定(ding)冗余防止(zhi) FEC 高丟包(bao)(bao)時時效現象,也可(ke)以在高丟包(bao)(bao)時逐(zhu)步降低(di)分辨(bian)率達到流(liu)暢播放的(de)體驗。
網絡風暴抑(yi)制(zhi)優化:WebRTC 中有重(zhong)發(fa)包(bao)(bao)的網絡抑(yi)制(zhi)策(ce)略(lve),重(zhong)發(fa)包(bao)(bao)占(zhan)比(bi)為(wei) 35%時(shi)(shi)候不再發(fa)送 NACK 重(zhong)發(fa)包(bao)(bao)和 FEC 冗(rong)余包(bao)(bao),但是這個占(zhan)比(bi)對于 720P、30%以上丟包(bao)(bao)時(shi)(shi)非常不友好,因此大量(liang)實(shi)際驗證測試,重(zhong)發(fa)包(bao)(bao)和 FEC 冗(rong)余包(bao)(bao)占(zhan)比(bi)為(wei) 30%時(shi)(shi),能夠(gou)合理規(gui)避(bi)網絡風暴現(xian)象,同時(shi)(shi)滿(man)足 NACK 請求重(zhong)發(fa)的策(ce)略(lve),達到 720P、30%丟包(bao)(bao)仍然可以獲取 15~25 幀率,實(shi)現(xian)流暢播放(fang)。
4.2 優化結果

整體(ti)方(fang)(fang)案(an)進(jin)行了部分實驗(yan)室場景的(de)測試和(he)(he)(he)驗(yan)收:包括 IP 和(he)(he)(he) SIP 通話,720P 和(he)(he)(he) VGA 分辨(bian)率(lv)驗(yan)證,相比之前的(de)版本(ben),在一(yi)定程度上(shang)提高的(de)用(yong)戶體(ti)驗(yan)。特(te)別是有線網絡(luo)條件下(xia) IP 直播時提升(sheng)明顯,總體(ti)主觀的(de)分有了明顯提升(sheng)。同時對(dui)抗延遲也從(cong)無(wu)到(dao)有,能夠覆(fu)蓋 300ms 一(yi)下(xia)環境。該方(fang)(fang)案(an)得(de)到(dao)用(yong)到(dao)實際環境中,得(de)到(dao)用(yong)戶認可,并在和(he)(he)(he)競(jing)爭(zheng)對(dui)手 PK 過程中,全面領先。
五 問題和措施:
5.1 擁塞檢測:
需要更加(jia)快(kuai)速準確(que)定位(wei)到當前網絡狀態(tai),一(yi)旦出(chu)現擁塞(sai)可以快(kuai)速調(diao)整當前發送策(ce)略。已經有視頻專項開始預研。
5.2 最新 WebRTC 中弱網控(kong)制
WebRTC 中 NACK 模(mo)塊(kuai)作(zuo)為獨(du)立(li)的 module 集成到 VIE 模(mo)塊(kuai)中,和 Jitterbuffer 模(mo)塊(kuai)解耦,實(shi)現實(shi)時監(jian)控網(wang)絡丟包,并獨(du)立(li)發送。
優點(dian):可(ke)以實時(shi)獲取(qu)到 NACK 列表; 和 JitterBuffer 解耦,獲取(qu)更便捷、更迅速。已經有視(shi)頻專項開(kai)始預研。
5.3 弱網前沿
2020-10-24 參加聲(sheng)網 RTE2020 互聯網實時互聯網大(da)會,聲(sheng)網已經實現 720P 2.0M 帶寬下 65%的丟包,流暢播(bo)放(fang)了。

1.深度強化(hua)算法那在(zai)擁(yong)塞控制中的應用;
2.實時(shi) H264 視頻編碼(ma)器(qi)算法的深度優化。


這些是(shi)我們之(zhi)后(hou)要去(qu)調研學習的(de)地方,也(ye)期(qi)待有(you)相關經驗的(de)童鞋可以一起探討學習。
————————————————
版權聲明:本文為CSDN博主「聲網」的(de)原創文章(zhang),遵循CC 4.0 BY-SA版權協議,轉載請附上原文出(chu)處鏈接及(ji)本聲明。
原(yuan)文鏈接://blog.csdn.net/agora_cloud/article/details/120832250