弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)

融雲RongCloud 發表於 2022-05-22
演算法

通過上次的《RTC 系統音視訊傳輸弱網對抗技術概覽》,我們知道 RTC 的三大核心指標為實時性、清晰度、流暢度。在整個通話過程中核心表現達標,才能給使用者一個基本的良好體驗。關注【融雲全球網際網路通訊雲】瞭解更多

然而音視訊資料在網路中傳輸時,網路是變化多端和不可預知的,比如地鐵、公交、 家裡、公司公用 WiFi,以及不同時間段流量高峰等造成的網路變化都不一樣,這些都會造成網路的抖動、頻寬容量動態變化等,最終影響音視訊的體驗。

因此,我們需要對網路頻寬變化進行有效的動態探測和評估,保證音視訊鏈路上傳送的音視訊資料流不超過鏈路容量上限。否則,就會帶來大量丟包,難以恢復,最終造成通訊一端或雙方視訊卡頓、語音卡頓、丟字等問題。

本文主要分享音視訊傳輸弱網問題中,針對網路擁塞的對抗技術。


典型動態頻寬探測方法

網路擁塞研究不是一個新的話題,前後有近四十年的歷史,由於以前記憶體比較昂貴,傳統的動態頻寬探測一般是基於丟包擁塞的方法,這種方法不能在丟包之前發現網路已經處於擁塞狀態,當探測到丟包時,實際上音視訊體驗就已經出現了卡頓問題,不太適合音視訊應用。

隨著記憶體價格的降低,現在當網路擁塞時,一般會把傳送不過來的資料包先暫存到網路佇列記憶體 buffer 中,待後續傳送,只有當 buffer 滿了才會丟棄包。

利用網路佇列 buffer 較大這個特性,現在比較典型的方法是基於延遲梯度估計和丟包相結合的頻寬估計方法。

有三種比較經典方案:
GCC 演算法[1] 是出自 Google 的一種延時估計和丟包相結合的擁塞控制演算法,在 WebRTC 中被預設使用。

NADA 演算法[2] 是思科公司提出的一種基於延時估計的方法,這種演算法頻寬利用率高,跟蹤頻寬變化方面表現很優秀。

SCReAM 演算法[3] 是愛立信公司提出的一種基於延時估計的演算法,在 OpenWebRTC 中被採用。

這篇論文[4] 比較了以上三種演算法的效果:
多路 GCC 能夠均衡利用整個頻寬,但在動態連結中具有鋸齒特徵,收斂比 NADA 緩慢;在有損鏈路方面具有更好的效能,這也使得它特別適用於無線網路。

NADA 可以在動態鏈路中快速穩定速率,收斂較快,在鏈路不受隨機丟包影響時,頻寬利用率高,但若遇隨機丟包情況,頻寬利用率會變得很低;同時受“後來者效應”影響,表現為後來者會使用更多的頻寬,在頻寬均衡使用方面不如 GCC。

SCReAM 將鏈路佇列延遲保持在低水平,但頻寬利用率低,且對頻寬變化比較遲鈍。
總體來說,GCC 更優越一些。

GCC 演算法為 Google 提出的基於延時梯度估計和丟包的擁塞控制演算法,在 WebRTC 中得到了⼴泛利用,目前為 WebRTC 預設使用的演算法。

該演算法有兩個版本,一個版本是分佈在傳送端和接收端,接收端通過對延遲進行估計,並通過 REMB RTCP 報文反饋評估出來的頻寬;傳送端則根據丟包率和接收端反饋的頻寬來計算最終的程式碼位元速率,進而調整編碼器編碼位元速率,這個框架將其稱之為 REMB- GCC
另一個版本是所有估算都放在傳送端,即基於延遲頻寬估計和丟包率估計都放在傳送端,接收端通過定時向傳送端反饋 Transport-wide RTCP 包,告知傳送端的收包情況,這個方法一般稱之為 TFB-GCC

兩種演算法的框架原理基本一致。TFB-GCC 比 REMB-GCC 更優,也是 WebRTC 後續推薦使用的擁塞控制演算法,下面對這兩種演算法做詳細分析。


REMB-GCC 演算法

弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)
(REMB-GCC 演算法架構圖)

基於 REMB 方式的 GCC 演算法,分為兩大部分,傳送端部分和接收端部分。

接收端部分負責基於時間延時梯度的變化來評估接收端的頻寬變化,這部分主要分五個子部分, Arrival filter、Adaptive threshold、Overuse Detector、Remote Rate Controller、Remb Processing;

接收端最終評估出來的頻寬將通過 REMB RTCP 包反饋到傳送端,傳送端結合丟包率及反饋的頻寬計算最終的頻寬,這個最終頻寬將用來調整傳送端編碼器編碼頻寬,FEC 和 pacing 頻寬及重傳包的頻寬,下面詳細介紹各個模組。

接收端模組

Arrival filter

以 RTP 傳輸的包,每幀可能被分成多個 RTP 包傳送,每個傳送的 RTP 包攜帶了一個 RTP 擴充套件,稱其為 abs-send-time 擴充套件,這個擴充套件記錄了傳送端傳送該包時的時間資訊;接收端在接收每個 RTP 包時,也會記錄該包的到達時間。

該演算法將通過如下(公式 1)計算相鄰兩幀的接收時間差和傳送時間差之間的間隔,這個間隔即為該幀在網路傳輸的時間上的⼀個變化,這個變化包含如下三個部分內容:

① 該幀資料在網路傳輸時間相對於上⼀幀在網路傳輸時間的變化,這是包 size 變化方面的度量
② 包在網路佇列排隊的時間變化
③ 網路噪聲干擾

這三個方面的變化,在測量上來看,都體現在以下公式 1 及示意圖中。
公式 1:dmi = ti − ti -1 − (Ti − Ti-1 )
弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)


(公式 1 示意圖)

需要說明的是:
① ti 表示第 i 幀的最後⼀個 RTP 包收到的時間
② ti-1 表示第 i-1 幀的最後⼀個 RTP 包收到的時間
③ Ti 表示第 i 幀的第⼀個 RTP 包傳送的時間
④ Ti-1 表示第 i-1 幀的第⼀個 RTP 包傳送的時間
⑤ RTP 包的傳送時間都是攜帶在 RTP 包的 abs-send-time 擴充套件中

延時梯度估計的另一個表示方法為:

公式 2:dmi = dLi/Ci + mi + ni

Ci 為接收第 i 幀時刻的鏈路容量估計,dLi/Ci 為接收第 i 幀時刻包在網路中傳輸的時間變化,主要受包 size 大小的變化和鏈路容量變化影響,這個也可以作為評估抖動的⼀個關鍵指標。

ni 為接收第 i 幀時刻網路 jitter 引入的噪聲,mi 為接收第 i 幀時刻網路佇列延時深度變化估計,dLi 表示第 i 幀和 i − 1 幀兩相鄰包的大小差,按如下公式 3 計算:

公式 3:dLi = Li −Li-1

獲取到 dmi 和 dLi 兩個樣本資料後,將它們作為 kalman 濾波器的輸入,利用 kalman 濾波器來估測延時梯度的變化 mi。

補充說明:
在延時頻寬估計中, 使⽤ kalman 濾波器對輸入樣本進行估計,但只用到了網路佇列延時變化這⼀個指標。

其實,還可以估計網路抖動,在 video jitter buffer 中就使用同樣的方法進行了網路抖動的估計,只是延時頻寬估計這塊只用了“包在網路佇列排隊延時的變化這⼀個指標而已”,沒有用抖動;而 jitter buffer 中只⽤ kalman 濾波器估算抖動。
所以在抗抖動問題上,可以嘗試使用這些指標進行相關優化⼯作,融雲也將在這方面進行持續優化。

因此,Arrival filter 的功能就是利用 kalman 濾波器,通過測量得到的 dmi 和 dLi 估算出 mi,它反應了網路鏈路包進入 buffer 佇列變化情況;同時 mi 也將作為 Adaptive threshold 和 Overuse Detector 兄弟模組的輸入。

卡爾曼濾波(Kalman filter)是一種⾼效率的遞迴濾波器(自迴歸濾波器),它能夠從一系列的不完全及包含噪聲的測量中,估計動態系統的狀態。
卡爾曼濾波會根據各測量量在不同時間下的值,考慮各時間下的聯合分佈,再產生對未知變數的估計,因此會比只以單一測量量為基礎的估計方式要準。

Adaptive threshold

該模組根據 Arrival filter 估測的 mi 來定時更新閾值 γi,mi 和 γi 將作為 Overuse Detector 模組的輸入,評估當前網路是否處於過載狀態。

閾值 γi 是⼀個動態調整的過程,計算如下:

公式 4:γi = γi + ∆T ⋅ kγi(∣mi∣−γi)
公式 5:∆T = ti − ti -1
公式 6:kd 建議值為 0.039,ku 建議值為 0.0087
弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)

Overuse Detector

該子模組根據前兩個模組輸出的閾值和佇列延時變化估計來評估當前網路是否處於過載狀態。

mi 大於 0,表示網路中的佇列深度正在增加,說明鏈路中的包傳送量在增加,延時變大,當不做任何處理時,將出現網路佇列變滿而導致大量丟包;
mi 等於 0,表示當前網路傳送延時沒有變化,網路傳送量沒有佇列;
mi 小於 0, 表示當前網路佇列正在減少,網路擁塞在改善。

演算法通過比較 mi 和 的 γi 值來判斷當前網路負載狀況,如下公式 7 和圖所示:
弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)


弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)
(公式 7 示意圖)

Remote Rate Controller

該子模組將根據 Overuse Detector 模組輸出的網路過載狀態來調整頻寬。

GCC 維護了 increase、decrease 、hold 三個狀態,三個狀態的轉換關係如下圖所示:
弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)
(GCC 維護的三個狀態關係)

這三種狀態下的頻寬調整策略如下公式 8 所示:
弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)

Ri 表示接收第 i 幀時刻,統計出來的接收端實際收包頻寬
Ari 表示接收第 i 幀時, 基於延時估計估算出來的網路頻寬

在 increase 狀態時,在上⼀次估算頻寬基礎上提升 8%,但實際值不超過接收位元速率的 1.5 倍,即不超過 1.5 ∗ Ri;

在過載情況下,需要降低位元速率,並且以實際接收端接收的位元速率為參考,按其 0.85 倍為當前估算頻寬,即 0.85 ∗ Ri。
這樣可快速降低傳送端頻寬,恢復網路擁塞狀態。

Remb Processing[5]

Remote Rate Controller 子模組計算出最終的接收端的評估頻寬後,將通過 REMB RTCP 報文反饋到傳送端,用來告知傳送端接收端評估的鏈路頻寬。REMB 的報文格式如下所示:
弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)
該訊息中包含如下幾個資訊:

  • 反饋訊息型別(FMT)為 15
  • 有效載荷型別(PT)為 206
  • 該報文傳送端的 SSRC
  • 媒體源 SSRC, 一般為 0
  • 標識為“REMB”
  • 接收包的 SSRC 條數
  • 估算頻寬值
  • 估算該頻寬鏈路上接收的媒體流 SSRC,1 個或多個

GCC 演算法在反饋 REMB RTCP 報文時,一般是每隔 200ms 傳送一次,當探測到頻寬過載時,探測的頻寬小於上次頻寬的 95%, 則立即反饋。目的是快速降低,平穩上升。

傳送端模組

傳送端主要是根據丟包率修正頻寬,目的是:當延遲估計模組頻寬沒有及時調整傳送端頻寬,擁塞還存在時,能夠基於丟包來調整頻寬。

傳送端最終的頻寬將結合丟包調整的頻寬和 REMB 反饋過來的頻寬,取兩者中較小的值。基於丟包率調整頻寬的邏輯如下公式 9 及公式 10:
弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)

公式 10:Ai = min(Asi, Ari)

Ai 為第 i 幀時刻最終 GCC 根據傳送端和接收端估算出來的頻寬,併為傳送端基於丟包計算的頻寬和接收端基於延時估計的頻寬的較小值。

編碼器頻寬、傳送端 pacing 頻寬、重傳頻寬都將參考該頻寬進行調整,一般編碼器頻寬為:max(0.5 ∗ Ai,Ai − FecRi − RtxRi) , pacing 頻寬為 2.0 ∗ Ai,重傳頻寬為 1.5 ∗ Ai。
注 : Asi 為第 i 幀時刻傳送端根據丟包率估算的頻寬值,fli 為第 i 幀時刻接收到接收端反饋的丟包率。

REMB-GCC 演算法總結

REMB-GCC 演算法目前已經被 Google 放棄維護,由於其分佈釋出端和接收端, 需要傳送端和接收端相互配合,而且使用了 kalman 濾波估算延時梯度變化,實際使用中存在一些問題,如 kalman 濾波估算不夠準確且複雜,接收端和傳送端同時參與頻寬估算不如都放在一端進行估算方便、準確和快速。

因此,Google 在 WebRTC 後續版本中使用了 TFB-GCC 替代 REMB-GCC。


TFB-GCC 演算法

弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)
(TFB-GCC 演算法架構圖)

從上圖可以看到,對頻寬的估算大部分工作都放在傳送端,接收端僅做兩件事,一個是定期反饋 transport-wide-seqnumber rtcp 包和丟包率 fl,fl 這裡描述的丟包率是 RR 反饋的,當有多路流時實際計算是有 SR 和 RR ⼀起計算出來的。基於延遲估計和基於丟包估計都放在傳送端處理了,基於丟包估計和 REMB-GCC 一樣,沒有變化;基於延遲估計主要是用 TrendLine filter 替換了 kalman filter。

Transport-wide sequence number[7]

傳送端傳送的 RTP 包會攜帶⼀個擴充套件頭 Transport-wide sequence number,擴充套件頭內容如下:
弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)
這裡是單個位元組表示擴充套件頭(0xBEDE)為識別符號,length = 1,表示該擴充套件佔有 4 個位元組,L=1,表示 Transport-wide sequence number 佔 2 個位元組。

當傳送端每發出一個包,都會將該包的該擴充套件欄位的 Transport-wide sequence number 累加 1,需要注意的是,當傳送端傳送多路流時(每路流的 SSRC 不⼀樣),所有流的 RTP 包的該擴充套件欄位都是連續計數的,不會分開獨立計數。該擴充套件頭的作用是為了標識傳送的包和反饋的包對應關係。

接收端反饋 Transport-wide RTCP 包[6]

接收端在 TFB-GCC 框架下,主要是定期傳送 Transport-wide 反饋包,用來告知傳送端,接收端收包相關資訊,包括包的到達情況及包的到達時間等資訊,其訊息格式及核心欄位解析如下:
弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)

base sequence number:此反饋中第⼀個資料包的傳輸範圍序列號,該數字不⼀定會隨著每個反饋增加,在重新排序的情況下,它可能會減少。

packet status count:此反饋包含多少個 RTP 資料包的數量,從由基本序列號標識的資料包開始;比如記錄的第一個 RTP 包的 transport sequence number 為 base sequence number,那麼記錄的第二個 RTP 包 transport sequence number 為 base sequence number + 1。

reference time:表示參考時間,以 64ms 為單位,RTCP 包記錄的 RTP 包到達時間資訊以這個 reference time 為基準進行計算。此資料包中的第⼀個 recv 增量是相對於參考時間的。即使某些反饋資料包丟失,參考時間也可以計算反饋之間的增量,因為它始終使用相同的時基。

feedback packets count:用於記錄接收端傳送的 Transport-wide 反饋包的個數,每傳送⼀個反饋資料包,計數器就加一。這個欄位可用於檢測反饋包是否丟失。

packet chunk:資料包狀態塊列表,用來指示資料包到達的狀態,指示的 RTP 資料包範圍是從基本序列號標識的資料包開始的多個資料包。

recv delta:對於 packet chunk 中的“packet received”狀態的包,也就是收到的 RTP 包,在 recv delta 列表中新增對應的的到達時間間隔資訊,用於記錄 RTP 包到達時間資訊。通過前面的基整時間以及 recv delta,傳送端可以計算出該 RTP 包在接收端的到達時間。

Delay-based controller

該模組為基於延時估計頻寬模組,等同於 REMB-GCC 的接收端部分。
具體包含了 ATF(等同於 REMB-GCC 中的 Arrival filter/Adaptive threshold)/Overuse Dectector/Remote Rate Controller。

ATF

其主要功能是估算延時梯度變化 mi,它根據輸入 dmi,利用 Trendline 濾波器中的最小二乘法對 mi 做最優估計 , Trendline 最小二乘法過程如下:

公式 11:dmi = ti − ti -1 − (Ti − Ti-1 )

注:ti 和 ti -1是通過客戶端反饋的 Transport-wide RTCP 包的到達時間獲取,傳送端在傳送 RTP 資料包時,會為每個 Transport-wide sequence number RTP 包記錄⼀個傳送時間 T。

以下公式 12 描述累計的佇列時間延時:
弱網優化,GCC 動態頻寬評估演算法(內附詳細公式)
以下公式 13 為平滑累計佇列時間延時:

公式 13:
smoothedDelayi =smoothingCoef∗smoothedDelayi_1 +(1−smoothingCoef)∗accuDelayi

以下公式 14 按照第 i 幀的收包相對時間和平滑時間延遲來構造了⼆元組:

(xi, yi) ⇒ (ti − t1 , smoothedDelayi)

二元組將按照以下公式 15 來估算 mi
圖片
這裡的 TrendlineSlope 即為 mi。

趨勢線斜率是鏈路佇列狀態的反映。當鏈路佇列長度增加時,資料包到達間隔也趨於增加,當小於 0 時,表明鏈路佇列正在縮小;資料包到達間隔也在減少;等於 0 表示資料包到達間隔恆定。
Adaptive threshold 和 REMB-GCC ⼀樣,即同公式 4。

Overuse Detector

根據上節計算出來的 mi 和閾值 γi 判斷當前網路的狀態,是否過載、低負載還是正常,根據網路狀態確定接下來對頻寬估計的調整,是增加、降低還是儲存不變,這個和 REMB-GCC ⼀樣。

Remote Rate Controller

這⾥根據 Overuse Detector 輸出的結果,來調整估算頻寬。與 REMB-GCC 不同的是,這裡主要使用 AIMD 方式調整頻寬,即當增加估算頻寬時,可以柔和⼀些,也可以激進⼀些。

由於 TFB-GCC 會跟蹤每次鏈路過載時的頻寬,噹噹前實際接收頻寬離之前鏈路估算頻寬近時,需要增加頻寬時,就使用柔和方式增加一些頻寬,增加幅度小;

噹噹前實際接收頻寬離鏈路頻寬變差很大時,採用激進方式增加頻寬,即增加幅度大;

當識別網路過載時,需要降低頻寬,以當前實際頻寬的 0.85 倍作為估算頻寬。
最終基於延時估計計算出來的頻寬為 Ari

基於丟包的網路擁塞頻寬估計

這裡和 REMB-GCC 的丟包網路擁塞估計一樣, 為了防止基於延時估計失效,通過接收端反饋的 RR 來計算丟包率 fli,利用 fli 來估計擁塞狀態,這裡同樣使用公式 9 來確定最終頻寬 Asi,最終估算的頻寬 Ai 計算如下:

公式 16:Ai = min(Asi, Ari)

TFB-GCC 演算法總結

採用此架構的 GCC 演算法,由於估算頻寬都放在傳送端,不需要接收端的同步優化,方便後續版本的部署和優化。準確性和及時性相對更高更好,同時使用 Trendline 濾波器,較 kalman 濾波器簡單且準確性更高,靈敏性也更高。
由於考慮了對每次過載時鏈路頻寬的估計,在增加頻寬時,表現得更加靈活和安全。

論文[4] 給出了 TFB-GCC 和 REMB-GCC 的一個頻寬受限的比較,可以看出 TFB-GCC 效果較 REMB-GCC 恢復更快,跟隨鏈路頻寬更準確,整體效果更好。
圖片
(TFB-GCC 與 REMB-GCC 比較)


GCC 演算法優化點

REMB-GCC 優化點

  • 接收端使用 TrendLine 中的濾波器替換 kalman 濾波器
  • 過載邏輯判斷優化,剔除噪點引入誤判
  • 實際接收頻寬優化
  • 基於丟包擁塞估計分場景優化
  • 基於延遲估計頻寬增加或降低計算演算法優化
  • 針對過載可能不會降頻寬進行優化
  • 針對當延時估計頻寬一直處於上升,而實際接收頻寬卻起伏波動,可能造成加大累計誤差問題進行優化
  • ……

TFB-GCC 優化點

  • 根據 Transport-wide RTCP 報文,估算接收頻寬優化
  • Trendline 濾波器優化
  • 根據 Transport-wide RTCP 包統計丟包率優化
  • 延時估計中使用 RTT 優化
  • 過載邏輯優化及閾值優化
  • 過載可能被忽略邏輯優化
  • AIMD 頻寬計算等相關邏輯優化
  • 鏈路頻寬估計優化
  • 基於丟包擁塞頻寬估計優化
  • TFB-GCC 傳送端⽀持接收 REMB 優化
  • ……

參考資料:

[1] https://datatracker.ietf.org/...
[2] https://datatracker.ietf.org/...
[3] https://www.rfc-editor.org/rf...
[4] Congestion Control for RTP Media: a Comparison on Simulated Environment
[5] https://tools.ietf.org/id/dra...