网易干货 | 浅析视频Jitter Buffer
一、 什么是JitterBuffer
Jitter Buffer也叫做抖動緩沖區,它是實時音視頻里面的一個重要模塊,它對數據包丟失、亂序、延遲到達等情況進行處理,平滑的向解碼模塊輸出數據包/幀,抵抗各種弱網情況對播放/渲染造成的影響,降低卡頓,提高用戶的觀看體驗。
二、JitterBuffer在音視頻系統中的位置
JitterBuffer在實時音視頻系統中的位置如下所示:
?
三、 視頻JitterBuffer的工作原理
1. JitterBuffer的核心思想
Jitter buffer的核心思想是用時間換空間,以增大端到端的延遲為代價來換取視頻通話的流暢性。當網絡不穩定時(抖動發生),增加buffer的長度,多緩存一些數據,以應對將來可能發生的抖動;當網絡穩定下來時,減小buffer的長度,少緩存一些數據,降低視頻端到端的延遲,提高實時性。因此jitter buffer的運行過程是一個根據抖動來動態調整buffer長度的過程。好的jitter buffer能夠在保證盡量不卡的前提下降低端到端的延遲,即它能夠在延遲和卡頓率之間取得較好的平衡。
2. 產生抖動的原因
1) 網絡傳輸路徑改變。例如,當前的傳輸路徑是A,但是下一刻路徑A上的某個路由器出現了故障,這時候數據包的路徑就會發生改變,導致端到端的傳輸時長發生變化。
2) 網絡自身的抖動。很多情況下網絡有噪聲,產生抖動是很正常的。
3) 網絡發生擁塞。擁塞發生的時候,數據包會在路由器上排隊,導致端到端延遲變大。
4) 抗丟包手段帶來的額外抖動。網絡出現丟包的時候,我們一般會使用nack/arq去重傳數據,重傳會帶來額外的延遲。
3. 計算抖動的方法
數據包傳輸時長的變化就是抖動,假設相鄰的兩個數據包packet1和packet2,它們發送時間戳是send_timestamp1和send_ timestamp2,接收時間戳是recv_ timestamp1和recv_ timestamp2,那么它們之間的抖動可以按照下面的方法計算:
這是最簡單的計算方法,要想準確計算出網絡抖動還需要考慮很多因素,這里不再贅述。
4. JitterBuffer的工作原理
1) 接收側收到數據包,開始組幀,這一步是必須的,幀不完整會導致花屏。
2) 每個幀組好之后,放進buffer里,然后按照幀序號進行排序。
3) 檢查幀的參考關系。對于解碼器來說,如果一個幀的參考幀丟失了,那么這個幀將解碼失敗或者花屏,所以參考關系必須要滿足之后才能把數據送進解碼器里。
4) 根據每一幀的時間戳(采集時間戳或者發送時間戳)以及接收時間戳計算抖動。這里的難點在于如何精確計算抖動。
5) 根據抖動計算buffer的長度。
6) 根據抖動自適應的調整buffer長度。抖動越大,預留的buffer長度越大,這樣可以利用增加延遲的方式來降低卡頓;抖動越小,預留的buffer長度越小,這樣可以降低延遲。
四、淺析webrtc里的視頻JitterBuffer
1.WebRTC里視頻JitterBuffer的運行機制
Jitterbuffer被兩個線程操作,寫線程負責組幀完成之后把數據寫入JitterBuffer里,讀線程負責從JitterBuffer里讀取數據然后解碼。
寫線程:
1) 判斷當前視頻幀是否有效,把幀插入buffer里,然后移除buffer里過期的、無效的幀;
2) 判斷幀之間的參考關系是否已經滿足;
3) 如果當前幀可以解碼,那么激活解碼線程(讀線程)。
讀線程:
1) 找到buffer中第一個可以解碼的幀(假設它是frame):如果這個幀的渲染時間戳是無效的,那么根據當前的抖動(開始的時候抖動值是0,它在步驟3中被更新)計算每個幀的渲染時間戳(render timestamp),并保存在幀信息中,然后根據這個幀的渲染時間戳和當前時間計算最大需要等待的時間(最大的等待時間不會超過200毫秒),然后休眠等待;
2) 如果在等待的時間內還有新的可以解碼的幀到來,那么重復步驟2,直到超時;
3) 根據frame的時間信息以及幀大小計算新的抖動值,并用這個抖動更新當前的抖動。
2. 計算抖動延遲
抖動延遲由網絡抖動延遲、解碼延遲、渲染延遲構成。其中,解碼延遲和渲染延遲比較穩定,網絡抖動延遲是動態變化的。計算網絡抖動是Jitterbuffer的核心之一。webrtc認為網絡抖動由兩個部分構成:
1) 網絡噪聲帶來的抖動延遲,也叫做網絡排隊延遲
2) 傳輸大的視頻幀(特別是關鍵幀)對網絡造成沖擊帶來的抖動延遲
為了準確估算出抖動延遲,必須要估算出網絡排隊延遲和信道速率(通過信道速率可以計算大的視頻幀對網絡造成的沖擊所帶來的延遲) 。webrtc使用卡爾曼濾波估算網絡排隊延遲和信道速率。卡爾曼濾波是一種預測的算法,它以協方差為標準,根據上一時刻的系統狀態估算當前時刻系統的狀態,然后根據當前的測量值調整當前時刻系統的狀態,最后得到當前最優的系統狀態。它認為估算出來的值和測量出來值都是有偏差的,因此要根據一個偏好因子(卡爾曼濾波增益系數)來判斷我們最后需要的值更加偏向于估計值還是測量值。由于卡爾曼濾波比較復雜,這里并不打算深入探討,下面介紹一下使用卡爾曼濾波計算網絡抖動延遲的大致流程:
1) 抖動的計算與信道速率、網絡排隊延遲有關,因此要計算抖動,就必須先計算信道速度和網絡排隊延遲
2) 把信道速率和網絡排隊延遲當作系統狀態,算法的目標就是估算出最優的信道速度和網絡排隊延遲。假設系統是一個線性系統,如果網絡非常好,那么很容易估算出當前系統的狀態等于上一個時刻的系統狀態,也就是說信道速度和網絡排隊延遲保持不變
3) 但是實際上網絡是動態變化的,因此需要對估算出的這個系統狀態(即信道速度和網絡排隊延遲)進行調整
4) 調整的具體方式:
a) 根據抖動延遲的觀測值(兩幀傳輸時長的變化值)和預測值(根據上一個系統狀態推導出來),計算它們的殘差;
b) 利用殘差計算網絡噪聲;
c) 根據抖動延遲觀測值、前后兩幀大小差值、網絡噪聲、系統誤差協方差等計算卡爾曼增益系數
d) 利用卡爾曼增益系數更新系統狀態(即信道速率和網絡排隊延遲)
5) 根據更新后的系統狀態計算抖動延遲:
?
3. 根據抖動延遲計算視頻幀的渲染時間
得到網絡抖動延遲之后,計算總的抖動延遲:jitter_delay = net_jitter_delay + decode_delay + render_delay。然后根據抖動延遲和當前的時間,計算什么時候渲染當前的視頻幀,然后根據渲染時間和當前時間確定當前幀在解碼之前需要等待的時間(wait_time),通過wait_time保證了各個視頻之間是平滑的,減少了卡頓。另外在等待的時間內也可以緩存更多的視頻幀,避免了下一次遇到弱網時再次卡頓。
五、視頻JitterBuffer在云信NRTC中的應用
NRTC是網易云信自研的實時音視頻通信系統,NRTC的Jitterbuffer在計算網絡抖動的基礎上考慮了丟包帶來的影響。一般的抗丟包手段有FEC和NACK,兩種方法各有優劣,FEC延遲比較低,但是浪費帶寬,NACK可以節省帶寬,但是會帶來延遲。NRTC使用FEC+NACK作為抗丟包手段,當遇到突發丟包時,使用NACK請求發送方重發丟失的包,如果丟包持續,那么使用FEC增加冗余防止丟包。根據前面的分析我們知道,NACK作為抗丟包手段是會引入額外延遲的,這個延遲不是網絡自身的抖動,如果Jitterbuffer不把NACK帶來的延遲考慮進去,那么很容易導致卡頓,降低用戶的主觀體驗,因此NRTC的Jitterbuffer把網絡抖動和NACK帶來的延遲綜合考慮,通過實時監測網絡變化,在低延遲和流暢性上取得了比較好的平衡。
總結
以上是生活随笔為你收集整理的网易干货 | 浅析视频Jitter Buffer的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅谈MySQL数据库中的锁与事务
- 下一篇: 低延时直播与RTC融合架构设计②:直播与