NetEQ是WebRTC的音頻處理模塊,主要包含MCU和DSP兩大處理單元,包含自適應緩沖區、語音解碼器、抖動控制和丟包隱藏模塊及播放四大部分。MCU的主要作用的安排數據包的插入和控制數據包的輸出。插入的關注點是插入的位置,輸出的關注點是輸出的時間。抖動消除的算法思路在MCU控制模塊中得以體現。DSP模塊主要負責對從MCU中提取PCM進行數字信號處理,包括解碼,信號處理,數據輸出等部分。丟包隱藏操作在DSP模塊中完成。個人的理解,MCU和DSP其實就對應兩個線程,MCU對應audio rtp數據網絡讀取線程,DSP對應audio rtp從緩沖區讀取,解碼並顯示的線程。
一、自適應緩沖區(audio jitter buffer)
抖動是指接收端某個數據包到達間隔與平均數據包到達間隔之差。這個差值不管大於0還是小於0,均增大了端到端的丟包概率。抖動通常可以使用抖動緩沖區解決。在接收方開辟一個緩沖區,語音包首先進入緩沖區,隨后再以穩定平滑的速率提取並播放。
二、丟包隱藏(Packet Loss Concealment, PLC)
分為基於發送端補償和基於接收端補償。發送端補償就是FEC前向糾錯和重傳;接收端補償是指錯誤隱藏算法。接收端補償一般是指通過插值的技術得到與原來丟包相似的包,起到替代作用。
三、命令機制
分為以下幾種情況:
1. 過去幀、當前幀都接收正確:normal模式
2. 僅當前幀發生丟包或延遲:PLC重建丟包幀
3. 連續多幀發生丟失:多次進入PLC單元,注意越靠后面丟失的幀,越難以精確重建補償包,因此補償增益應該逐幀遞減,以避免引入更大失真。
4. 前一幀丟失、當前幀正常播放:說明上一幀是經過PLC產生的。
四、NetEQ四個緩沖區
packet_buffer_:抖動緩沖區
decoded_buffer_:解碼緩沖區,最大長度5760(120ms @ 48KHz)
algorithm_buffer_:DSP算法緩沖區,就是一個AudioMultiVector對象
sync_buffer_:語音播放緩沖區,分為兩塊,一塊是已經播放的數據,一塊是未播放的數據,curPosition變量作為分界點。看下這個緩沖區多大,及內部結構。
end_timestamp_用於記錄最后一個樣本的時間戳,並報告給MCU。MCU根據packet_buffer_中的timestamp來決定是否能夠繼續取出音頻包。
五、一點反思
5.1 關於代碼
WebRTC代碼目錄是webrtc\modules\audio_coding\neteq\。網上找了很多文檔,大部分都在說NetEQ的結構(包括本文),很少走讀NetEQ代碼。結構脈絡還是比較清晰的,就是原始RTP數據包依次經過幾個buffer,最終輸出的過程。但是內部實現,比如decision_logic, delay_manager_, expand.cc, merge.cc等,需要較強的理論基礎才能分析清楚。
5.2 關於移植
如果不修改NetEQ核心邏輯,只是添加讀寫線程。個人認為移植還算方便。
