本文來自即構科技技術副總裁冼牛在LiveVideoStackCon 2019上海大會的演講,詳細介紹了即構科技在實時流媒體傳輸協議選擇,抖動處理,擁塞控制等多方面的實踐。
文 / 冼牛
整理 / LiveVideoStack
大家好,我是冼牛,此次分享和實時音視頻、流媒傳輸的思考與實踐有關。主要會為大家介紹實時音視頻的超低延遲架構并簡要闡述實時視頻調度系統,同時結合擁塞控制策略和信道糾錯策略,進一步探索解決網絡延遲的最優方法。

分享內容包括四個方面,第一方面簡要說明一下低延遲的架構,第二是關于實時視頻調度系統方面的問題,第三和第四點是擁塞控制和信道糾錯方面對于解決延遲重要性的問題。

1. 實時音視頻的超低延遲架構
1.1 實時架構的關鍵點
在討論實時語音和視頻通訊的問題時,怎樣做到低延遲便是其中不可回避的問題之一。延遲的產生包括網絡傳輸,網絡渠道不良的原因,同時也不能忽略整個視頻傳輸的鏈條包括采集,前處理,編碼,推流,拉流,解碼和渲染,這其中各個環節出現問題都有可能帶來延遲的增加。

實時架構可以簡單的分為兩個方面。其中負載均衡、就“近”接入、質量評估和動態路由這四點屬于調度方面的問題,算法流控屬于流媒體傳輸方面的問題。前四點又可以劃分為兩個方面,第一個方面,負載均衡和就“近”接入屬于第一公里和最后一公里的處理,質量評估和動態路由屬于網絡調度與路由。
負載均衡指的是對包括網絡邊緣節點和傳輸終節點的容量管理,確保每一個節點的容量不會出現空置或被擠爆。就“近”接入指的是網絡邏輯上的就近接入,我們可以從兩個緯度來考慮,一個是確保用戶接入了同一個運營商的網絡,另外要確保用戶接入的地域。
質量評估是一種事后的做法,根據網絡長期運營下來的數據積累作為策略來指導寫入的路由。如果這些基建綜合起來還是不能夠實現良好的用戶體驗時,我們就會在上行的推流和下行的拉流做一些算法上的流控。
1.2 調度系統&傳輸算法

流媒體傳輸之中包含調度系統與傳輸算法,那么兩者相比誰更加重要?簡單的說調度系統所做的事情就是告訴每一個節點傳輸的方向。在實時網絡傳輸中,調度系統相當于一個Leader,能夠指導每一個節點往哪去傳,該怎么去傳,采取什么樣的策略。調度系統與傳輸算法兩者之間的關系我通過下圖來做一個簡單的比喻。

調度系統能夠充分利用基建資源,在優質的基礎條件下保證相對較好的傳輸質量,從而提供更好的用戶體驗,此時對于算法的要求就沒有那么苛刻。但在實際情況下,網絡資源并不能夠實現良好的傳輸質量,因此用戶體驗也無法保證,那么在這種情況下傳輸算法就變得尤為重要。
2. 實時視頻調度系統
2.1 調度系統的拓撲圖

實時調度系統中需要關注的有幾個方面。上行的推流,其中比較重要的兩個部分之前已經提到過,即就近接入與負載均衡。同時在上行推流時我們還會做一些碼率自適應的工作,在 “最后一公里”,上行拉流的時候則會進行分層編碼的工作。傳輸的過程分為兩層,調度中心會幫助并指導節點進行動態回源;服務節點,負責節點跟節點之間的轉碼工作。
2.1.1 單節點調度模式(成本優先)

調度的模式有兩種。一種是單節點調度模式。一種是多節點調度模式。
2.1.2 單節點調度模式(體驗優先)

單節點的調度模式是成本優先的,在國內一般采取的都是單點的調度模式,而在跨國的環境中才會考慮用到多點的調度模式。
2.2 什么是擁塞?

3. 擁塞控制策略
在討論擁塞控制策略之前,首先介紹下什么叫做“擁塞”?下面以漏斗的模型為例來進行說明。我們可以將漏斗看作信道,如果漏斗中堆積的液體越來越多,我們就認為它出現了擁塞。如果說液體可以穩定的從漏斗中穿過,漏斗內沒有任何液體堆積的現象發生,保持一種穩定、平衡的狀態,那么我們認為它現在是正常狀態。如果漏斗中的液體沒有滿也沒有增加,或者說漏斗中的液體變得越來越少則表明處于空載狀態。擁塞控制被定義了三個狀態,分別是:Normal,Underuse,Overuse。其中Underuse并不表示目前的狀況是良性的,它往往表示擁塞發生以后的恢復階段,處于一種不穩定階段。此時的碼率肯定要被提高,但提高的具體數值不能確定,所以應適當采取一些保守的策略。
3.1 如何評估擁塞狀態

評估擁塞的方法有兩種,一種是基于丟包率的擁塞控制,一種是基于延遲的丟包控制。通過這兩種方法進行評估,可以清楚地判斷當前網絡狀況處于Underuse還是Overuse的狀態。
3.2 如何控制擁塞

在做控制擁塞時有三件事情要處理,第一要發現擁塞,發現擁塞以后去解決擁塞,解決擁塞以后把梳理給調上來。那么就說呢,在實際網絡里如果發現丟包的情況出現,其實擁塞已經發生了,此時再去執行解決辦法已經為時過晚,所以往往會傾向于通過觀察排隊延遲來發現擁塞。發現擁塞以后有兩個處理方法,一個方法是擴大間距,保證安全距離。第二種方法是降低碼率。
最后一個環節在于擁塞緩解之后,對Underuse如何處理。首先當務之急是提高碼率恢復清晰度,但調節的速率問題也是需要考慮的。
擁塞控制的方法有兩種,一種是基于丟包的擁塞控制,一種是基于排隊延遲的擁塞控制,這兩種方法孰優孰劣很難比較,一般都是采用兩種方法相結合的形式。
基于丟包的擁塞控制的優勢是比較簡單,只需要知道丟包率,就可以根據丟包率確認碼率調整的方向與大??;劣勢就是當我們發現丟包的時候,擁塞已經發生,在此基礎上進行控制為時已晚。
而基于延遲的擁塞控制,排隊延遲本質上就是抖動,是擁塞的一種征兆。這種方法的劣勢之一是比較復雜,必須經過很多步驟才能做出判斷,在此之前需要從接收端評估出抖動的程度,確定當前網絡的狀態,擁塞、Underuse還是Overuse,然后根據情況評估如何調整碼率,整體來說是比較復雜的。

第二個缺點,抖動本質上就是路由器上排隊延遲隊列的長短變化。基于延遲的擁塞控制存在的缺點很明顯,以上圖為例如果允許的抖動緩沖隊列的長度很長,很容易就能看出擁塞正在發生。但如果長度很短,不管有沒有擁塞都很難看的出來。但如果隊列很長,那么相對應的延遲也會很高

接下來詳細介紹如何控制擁塞。如上圖,左邊是發送端,右邊是接收端。在這里需要解決兩個問題,在哪里做評估?在哪里做控制?評估時需要得到兩方面的信息,一個是丟包率,另外一個是抖動情況,也就是排隊延遲的情況。做評估最適合的地方是接收端,接收端的緩沖隊列里面可以獲取這些信息。而發送端則比較適合做控制,因為最終碼率大小的控制權在編碼器,評估出的目標碼率要交由編碼器來進行編碼。

基于延遲的Congestion Control以及基于丟包的擁塞控制這兩種方法。通過逆向思維的方式進行推理,擁塞控制的最終目標都是要得到一個目標碼率(在擁塞控制發生的時候,碼率需要調到什么樣的數值),在得到碼率之后就要考慮用什么樣的速率調整到目標碼率。 而調整碼率的方式需要評估目前網絡的狀況再做決定,這是第三步。第二步是如何評估負載狀態,是按照Underuse、Normal還是Overuse,怎樣利用排隊的延遲等一系列數值來做評估。這個評估是基于排隊延遲的,所以第一步就要監控排隊延遲,獲得一系列排隊延遲的時間,然后去評估它處于什么樣的狀態。
3.3 擁塞控制的步驟
3.3.1 監控排隊延遲

接下來詳細介紹擁塞控制的四個步驟。第一步,監控排隊延遲,如上圖左邊是發送段,右邊是接收端,發送端的大T是發送的時間,接收端的小t是包到達的時間,可以看大T的Ti-T(i-1),這是兩個包發送的時間差,T1是到達的時間差。如果用下面小T的差減去大T的差可以得到排隊延遲的差,這是觀察得到的數據,做數據分析的時候需要考慮觀察到的東西永遠和實際客觀的東西是有差別的,一方面得到的這些排隊,抖動里面排隊的延遲存在異常值,另外一方面,發送的每個幀長度不一定是一樣的,要做到消除幀的差別。最后網絡本身它是有噪音的,需要通過這一系列的去除以后才能得到比較接近網絡排隊延遲的抖動數值。

以上公式就表示接收端的包到達兩個幀之間的時間差,減去發送端的包發送出去的時間差的差,這是觀察到的數據,數據里面是有正常的差和網絡噪音帶來的異常值,可以通過kalman濾過器去掉異常的值,kalman濾過器它能做的事情就是把M一系列的值里面的一些比較異常的值抹掉,留下其他正常的值。那么正常的DL(i)除去C(i)得到是正常之間的差異所帶來的時間的差異。最終把這兩個公式結合,就可以得到一系列的在路由器這一側排隊的延遲,最終的數據也只是接近結果,永遠不是真實的數值。
3.3.2 評估負載狀態

第一步最終得到結果是一系列M的值,M1,M2,M3,M4在路由器排隊的時間的延遲,根據這些時間延遲去判斷它處于Underuse,Normal還是Overuse狀態。一般的做法是,如果排隊的延遲超過了一個域值,就判斷它是Overuse狀態,如果是低于某個域值的話就是Underuse狀態,處于某個域值之間為Normal狀態。域值有兩種方法定義,一種是規定一個固定值,固定值往往是根據經驗摸索出來的結果。另外一種做法是讓域值變得能夠自適應,這兩種方法各有優劣點。

上圖為評估負載狀態列了兩個圖和公式,其中解決了兩個問題,一個問題是評估出網絡狀態是按照Underuse、Normal還是Overuse。另外一個事情是把域值gamma做成自適應的。第一個問題,可以把左邊圖跟右邊圖結合起來看,它解決的是M和gamma之間的關系,紅色的線是gamma的正值和它的負值,加起來就是一個通道。其實它就是一個管道,在管道中間處于一種比較正常的狀態,是可以接受的Normal值,如果在通道上面就是Overuse值,再下面是Underuse值。
反映到代碼上面來說,一般IF語句,我就先看else,else如果是負值的話,對應的就在右邊圖的最下面,此時它處于一種Underuse的狀態,如果按照use的狀態應該是Normal,同時把等待的時間給清零。如果說它應該是處于中間管道以內的全Normal的狀態,如果它的MR大于gamma,說明它在上面,或者在下面,我們首先看在下面的情況。如果在下面的情況,M是一個負值的,負值的情況下應該把等待的時間清零,變成-1 Underuse的狀態。
自適應的基本的原理是讓gamma值以上一個時刻的值做為基礎,不斷地去微調。如果gamma是正數,就往上調,如果是負數的話,就往下調,一般上調的時候是采取一種比較保守的狀態慢慢上調,如果往下調就調的比較快,最終拿到的結果就是gamma值,它會跟著網絡抖動的延遲不斷地調整,而且是相對平滑的去波動。
3.3.3 評估網絡負載狀態

上一步最終的結果是得出了目前網絡狀況的三種情況,分別是Normal、Underuse和Overuse,根據這三種情況去做下一步的動作,這里用GCC的自動機來表征下一步該做什么,即構科技采用的方法不見得完全跟它一樣,但思路基本上是比較接近的。
如果是在正常的情況下,自動機總是會不斷去嘗試把碼率調高,這是在Normal的情況下,如果是在Overuse的情況下,基于把碼率調低的這種趨勢它會表現的比較激進。如果處于Normal情況下,自動機會處于Underuse的情況下不斷地調高。即構科技在細節上的處理有些不一樣,在Normal情況下有兩種方法,一種方法是根據網絡狀況,如果網絡狀況處于逐步恢復的狀態,它會比較保守的來提高,如果發現網絡狀況一下子變得很好,丟包率很低且沒有抖動的情況下會把碼率在短時間內調的很高。在Overuse情況下,GCC的建立逐步向上的,即構科技的做法是直接降到可用的目標碼率之下,甚至更低,具體變得多低要根據擁塞的情況來具體分析,如果擁塞很嚴重的話就降的很低,就要給足夠的時間做緩沖去恢復帶寬,如果擁塞不是那么嚴重的話,就降到比實際可用帶寬低一些就可以了。
Underuse的狀態是一種不穩定的狀態,這時候采取的策略一般是比較保守的,在Underuse的狀態下是可以把碼率調上去的,但是能調多少,往上調多久,都是有一定不確定因素存在的,需要要一步一步去試探。
3.3.4 評估調整碼率的方式

上圖是GCC評估調整碼率的方式。第一行的公式闡述是1.05,它表示的是逐步緩慢的上調。右邊的R是過去五百毫秒里面接受抖動緩沖隊列里面的包數,實際上表示過去五百毫秒里的最大碼率,乘上α就是0.85,這是GCC的做法。
其實上述公式所表示的下降也是逐步下降的,如果之后的狀態碼率不會發生變化,根據具體不同的情況下會采取一些比較激進的做法。

網絡擁塞的情況下追丟包需要處理三個問題,第一個問題,首先要基于丟包率獲得碼率,因為需要根據已有碼率才能調整碼率,這是最重要的信息。在接收端根據抖動緩沖隊列里面統計得到丟包率,通過RTC包反過來給到發送端,發送端繼續判斷究竟碼率應該是多少,最終得到想要的碼率。

這里列了GCC做的公式,GCC公式第一行列了兩個例子,一個是丟包率10%,一個是丟包率2%,超過10%的話我們一般認為已經發生了擁塞,網絡處于比較差的狀態。低于2%我們認為網絡處于比較好的狀態。GCC采用(1 - 0.5)丟包率表示是比較緩慢在上調碼率,如果網絡處于一個比較好的狀態,丟包率低于2%,上調的幅度也不會太大,這是GCC的做法。即構科技的做法相對會比較激進。
基于丟包的擁塞控制還有一個情況需要去考慮,就是根據不同的網絡它會有不同的表現,如果是有線網絡的話,數據一般比較可靠,但如果是無線的網絡的情況下,或者說跨國網絡的情況推算出來的結果往往是不準的,這時候需要把這種方法和剛才說的delay Congestion Control 結合起來使用。
3.4 擁塞控制總結

最后總結一下,之前的公式的最終目標就是上限以下的最低碼率,因為我們最終可以得到兩個碼率,一個是基于丟包,一個是基于延遲,然后加起開發者設置的上下限,就得到一個最終碼率。基于丟包和基于延遲都存在一定的優缺點,可以將它們結合起來使用。
4. 信道糾錯策略
4.1 前向糾錯

前向糾錯的缺點是不精準,比較低效,最重要的是費用較高。它的好處是不受RTT的影響,只需要發送一次。
4.2 丟包重傳

ARQ的劣勢是受RTT的影響較為明顯,需要重傳并且有可能引起重傳風暴。ARQ的好處是實現比較簡單,算法復雜度較低并且十分精準,最重要的一點是省錢。
4.3 ARQ vs FEC

即構科技在比較之下偏好使用ARQ,這很大部分歸結于成本的原因,但是ARQ不能解決所有的問題,RTT比較小的情況下,它可以做到精準和低延遲,但RTT很大的時候,例如跨國的情況下,需要結合FEC來用。即構科技關于結合的做法是盡量的使用ARQ,如果發現當前情況ARQ解決不了,需要重傳的時候要保證重傳這次必須成功,我們的做法是加冗余,重復發兩次,或者說用FEC來保證這次重傳必須是成功的。

關于RTT判斷的問題,RTT在國內一般是在一百毫秒以內,普遍認為是比較小的??鐕那闆r下,比如從深圳到紐約,RTT會達到140左右,這個情況下算比較大的。冗余會降到可用的帶寬,所以做冗余的時候需要慎重。
4.4 Takeaway

總結以上分享內容,關于實時網絡傳輸延遲和實時RTC通信,它的延遲不僅僅是來自延遲傳輸,終端處理也十分重要。對網絡傳輸調控的主要手段包括剛調度系統、擁塞控制以及信道糾錯,同時在下行要結合分層編碼。在網絡方面,碼率取決于用戶是否有一個良好的網絡環境。