https://blog.csdn.net/ljh081231/article/details/78892217
實(shí)時(shí)音視頻領(lǐng)域UDP才是王道 ? ? ??
? ? ? ?在?Internet?上進(jìn)行音視頻實(shí)時(shí)互動(dòng)采用的傳輸層方案有TCP(如:RTMP)和UDP(如:RTP)兩種。TCP協(xié)議能為兩個(gè)端點(diǎn)間的數(shù)據(jù)傳輸提供相對(duì)可靠的保障,這種保障是通過一個(gè)握手機(jī)制實(shí)現(xiàn)的。當(dāng)數(shù)據(jù)傳給接收者時(shí),接收者要檢查數(shù)據(jù)的正確性。發(fā)送者只有接到接收者的正確性認(rèn)可才能發(fā)送下一個(gè)數(shù)據(jù)塊。如果沒有接到確認(rèn)報(bào)文,這個(gè)數(shù)據(jù)塊就得重傳。盡管這種機(jī)制對(duì)傳送數(shù)據(jù)來說是非常合理的,但當(dāng)用它在Internet傳輸實(shí)時(shí)音視頻數(shù)據(jù)時(shí)就會(huì)引發(fā)很多問題。首先就是延遲問題,在傳輸信道丟包率較高時(shí),TCP的傳輸質(zhì)量下滑嚴(yán)重,重傳擁塞導(dǎo)致音視頻延時(shí)非常大,失去實(shí)時(shí)互通的意義。特別是無線信道(WIFI、4G、3G)下,使用TCP做雙向互通通訊穩(wěn)定性欠佳,易出現(xiàn)音視頻長(zhǎng)時(shí)間卡住不動(dòng)然后快放的現(xiàn)象。?
? ? ? 更多的產(chǎn)品選擇采用的協(xié)議是UDP(一般上層應(yīng)用層協(xié)議為RTP,以提供序號(hào)和音視頻同步的服務(wù))。UDP同?TCP?相比能提供更高的吞吐量和較低的延遲,非常適合低延時(shí)的音視頻互動(dòng)場(chǎng)合。
UDP傳輸存在的問題:
UDP性能的提高是以不能保障數(shù)據(jù)完整性為代價(jià)的,它不能對(duì)所傳數(shù)據(jù)提供擔(dān)保,常見的問題有包亂序、包丟失、包重復(fù)。無線信道(WIFI、4G、3G)下,UDP包亂序和包丟失可以說是常態(tài)。
關(guān)于包亂序和包丟失的原因,參考諸多文獻(xiàn)總結(jié)如下:
亂序原因:
? ?(A) 路由器的存儲(chǔ)隊(duì)列導(dǎo)致的包亂序。
???(B) UDP包據(jù)經(jīng)過不同的路由造成了發(fā)送數(shù)據(jù)的混亂。?
丟包原因:
(A) 當(dāng)路由器和網(wǎng)關(guān)發(fā)生擁塞時(shí),某些包可能被丟棄,發(fā)生這種情況一般是由于網(wǎng)絡(luò)中傳輸?shù)臄?shù)據(jù)包大于網(wǎng)絡(luò)信道的承載能力。
(B) 分組數(shù)據(jù)在傳送時(shí)有生存時(shí)間限制以避免路由中死循環(huán)的出現(xiàn),網(wǎng)絡(luò)狀況惡劣時(shí),分組可能超時(shí)丟失。
(C) 接收端工作超載運(yùn)行時(shí)可能因調(diào)度困難而不能及時(shí)處理網(wǎng)口數(shù)據(jù)。
? ? ? ?視頻碼流的少量丟失都會(huì)導(dǎo)致解碼后的視頻出現(xiàn)花屏的現(xiàn)象。H264、HEVC這樣的高壓縮率視頻壓縮標(biāo)準(zhǔn)使得壓縮的冗余度非常低,碼流的丟失除了影響本幀的解碼外,還將影響以此為參考的視頻幀解碼,導(dǎo)致花屏的累積擴(kuò)散,直至下一個(gè)關(guān)鍵幀的到來視頻畫面方能恢復(fù)。雖然解碼器內(nèi)部會(huì)做一定的錯(cuò)誤掩蓋處理,但效果并不理想,特別是采用ffmpeg這類開源的解碼器,其錯(cuò)誤掩蓋算法做得比較簡(jiǎn)單。為此,在很多產(chǎn)品中不得不采用較小的GOP(較小的I幀間隔),以期在出現(xiàn)丟包花屏后能盡快的用I幀碼流刷新畫面。這種方法副作用較大,而且某些場(chǎng)合下甚至?xí)m得其反。因?yàn)镮幀壓縮效率遠(yuǎn)不如P幀、B幀,I幀往往比P幀、B幀大很多,頻繁的I幀將給傳輸信道帶來持續(xù)的波動(dòng)壓力,造成更嚴(yán)重的丟包、亂序。另外,因?yàn)榫幋a器碼率控制的緣故,I幀占用較多的碼流后,緊接著的P、B幀將不得不采用較大的QP量化參數(shù)(較差的圖像質(zhì)量)以保證碼率的局部可控,這樣帶來的直觀感受是圖像隨著I幀間隔周期性的發(fā)虛、馬賽克。亂序的UDP包不經(jīng)過順序恢復(fù)直接送解碼器同樣會(huì)導(dǎo)致解碼花屏,因?yàn)榻獯a器內(nèi)部會(huì)將遲到的數(shù)據(jù)包丟棄。
? ? ? ?綜上所述,工程中急需一種抗丟包、抗亂序的增強(qiáng)型UDP方案來提升實(shí)時(shí)音視頻傳輸效果,經(jīng)過多年的積累與完善,我們推出了一套基于RTP并采用FEC前向糾錯(cuò)和后端QOS處理的完整解決方案,效果非常明顯。
使用FEC\QOS武裝RTP
?對(duì)于丟包,我們采用改進(jìn)型的vandermonde矩陣FEC(Forward?Error/Erasure?Correction)前向糾錯(cuò)技術(shù)來進(jìn)行丟包恢復(fù),由發(fā)送方進(jìn)行FEC編碼引入冗余包,接收方進(jìn)行FEC解碼并恢復(fù)丟失的數(shù)據(jù)包。
對(duì)于包亂序和包重復(fù),我們采用QOS亂序恢復(fù)處理,該QOS方案特點(diǎn)是在沒有丟包的情況下,不引入任何系統(tǒng)延時(shí),并且可以通過可控的丟包等待時(shí)延來適應(yīng)不同的信道亂序程度。QOS需要在接收端進(jìn)行FEC解碼前進(jìn)行,確保送FEC解碼模塊的數(shù)據(jù)包序號(hào)是正確的(不存在亂序,僅存在丟包)。
眾多產(chǎn)品案例表明:采用FEC+QOS+RTP的組合,能顯著提升UDP傳輸?shù)膩G包、亂序抵抗力,為上層音視頻服務(wù)提供有力保障。下圖1是各模塊在系統(tǒng)中的位置說明。
圖1?FEC、QOS在RTP系統(tǒng)中的位置
需要說明如下幾點(diǎn):
(A)從差錯(cuò)控制角度看,傳輸信道可以分為隨機(jī)信道、突發(fā)信道和混合信道。在隨機(jī)信道中,丟包出現(xiàn)是隨機(jī)的,且相互統(tǒng)計(jì)獨(dú)立,滿足正態(tài)分布。在突發(fā)信道中,丟包是集中出現(xiàn)的,在一些短促的時(shí)間區(qū)間會(huì)出現(xiàn)大量的丟包,而在這些時(shí)間區(qū)間之外又存在較長(zhǎng)的無丟包區(qū)間。混合信道則是上述二者的合體。本方案?jìng)?cè)重于對(duì)具備隨機(jī)信道特性的傳輸鏈路進(jìn)行改進(jìn)優(yōu)化。
? ? ? ?對(duì)?Internet信道的丟包特性研究發(fā)現(xiàn),大多數(shù)情況下其滿足隨機(jī)信道的特點(diǎn),丟失的都是單個(gè)包。連續(xù)兩個(gè)或以上包同時(shí)丟失的概率雖然比純隨機(jī)過程要高,但發(fā)生的概率還是要比單包丟失低,發(fā)生連續(xù)丟失10個(gè)以上包的概率就更低了。由于單包丟失出現(xiàn)的最頻繁,我們的抗丟包方案主要側(cè)重于對(duì)單包丟失的修復(fù),同時(shí)也應(yīng)該兼顧連續(xù)丟失的少量包的修復(fù)。對(duì)大量連續(xù)丟失的包的修復(fù)相對(duì)來說就顯得不那么重要了(出現(xiàn)概率低,修復(fù)的代價(jià)大)。
(B)當(dāng)然,任何差錯(cuò)控制方案都是有其最大糾錯(cuò)能力限制,當(dāng)丟包率超出當(dāng)前系統(tǒng)的糾錯(cuò)能力時(shí),丟包無法恢復(fù),對(duì)于視頻應(yīng)用來說意味著視頻將出現(xiàn)花屏。
? ? ? 為了改善系統(tǒng)在高丟包率下的用戶體驗(yàn),避免長(zhǎng)時(shí)間花屏無法刷新的現(xiàn)象,我們建議使用者采用ARQ(自動(dòng)請(qǐng)求重發(fā))+FEC機(jī)制,這里的ARQ請(qǐng)求并不是請(qǐng)求遠(yuǎn)端重發(fā)丟失的數(shù)據(jù)包,因?yàn)槟菢酉喈?dāng)于走了TCP這類內(nèi)嵌ARQ功能協(xié)議的老路,必然引入不可控的延時(shí)。這里的ARQ只是請(qǐng)求遠(yuǎn)端即刻編碼視頻關(guān)鍵幀,避免長(zhǎng)時(shí)間花屏無法刷新的現(xiàn)象,ARQ請(qǐng)求一般通過額外的TCP信道發(fā)出(在絕大多數(shù)的系統(tǒng)中,通訊雙方一般會(huì)有TCP的信令通道,用于雙方業(yè)務(wù)層信令的交互)。ARQ的發(fā)起是根據(jù)FEC解碼輸出視頻碼流是否丟包作為判斷依據(jù),發(fā)送端和接收端都需要對(duì)ARQ的頻率做一定的保護(hù)措施,避免頻繁的發(fā)起和響應(yīng),造成過多的I幀(過多I幀的副作用前面已有列舉)。
測(cè)試效果
本方案為C++開發(fā),提供PC、Android(JNI)、IOS跨平臺(tái)的支持。為了方便測(cè)試,我們?cè)赑C下開發(fā)了幾個(gè)簡(jiǎn)易測(cè)試DEMO用于驗(yàn)證演示。
(A)數(shù)據(jù)驗(yàn)證DEMO
下圖所示為數(shù)據(jù)驗(yàn)證DEMO界面,它以指定的數(shù)據(jù)作為測(cè)試源,可幫助用戶更好的理解處理流程。
圖2 ?數(shù)據(jù)流程驗(yàn)證DEMO
測(cè)試工具為點(diǎn)對(duì)點(diǎn)工作模式,可在兩臺(tái)PC上各自運(yùn)行(同時(shí)也支持單機(jī)模式,只需將收發(fā)IP地址均設(shè)置為本地IP即可),以實(shí)現(xiàn)雙方之間RTP(FEC+QOS)通訊。
? ? ? ?軟件收發(fā)自定義的測(cè)試包數(shù)據(jù),提供了模擬丟包功能,支持按固定間隔丟包或者按隨機(jī)比率丟包;支持設(shè)置FEC冗余度或者選擇冗余度自適應(yīng),支持設(shè)置QOS丟包等待時(shí)延等參數(shù)。
? ? ? ?測(cè)試工具內(nèi)部默認(rèn)使用10個(gè)媒體包外加冗余度(數(shù)量由選擇的冗余度決定)作為一個(gè)GROUP,當(dāng)選擇冗余度20%時(shí),一個(gè)GROUP由10個(gè)媒體包附加2個(gè)冗余包組成。下圖是Wireshark的觀察情況,10個(gè)媒體包后面緊接著2個(gè)冗余包。
圖3 Wireshark觀察冗余包情況
需要說明的是:程序主動(dòng)丟包是在UDP發(fā)送層進(jìn)行,所以即可能丟媒體包也可能丟冗余包。
下面我們以20%冗余度為例說明系統(tǒng)對(duì)各類丟包率的抵抗能力。
? ? ? ?當(dāng)選擇每10個(gè)包丟1個(gè)包時(shí)(丟包率10%),一個(gè)GROUP中最多只會(huì)丟棄1個(gè)包,20%的冗余度足夠抵抗這一丟包率,測(cè)試結(jié)果也驗(yàn)證了這一結(jié)論,接收到的所有媒體包序號(hào)均保持連續(xù),丟包率從10%降為0%,實(shí)驗(yàn)情況如上圖2所示。
當(dāng)選擇每5個(gè)包丟棄1個(gè)包時(shí)(丟包率20%),丟包情況如下圖4所示:
圖4每5個(gè)包丟棄1個(gè)包時(shí)的情況
對(duì)于第一個(gè)GROUP,一共丟棄了三個(gè)包,包括0號(hào)媒體包、5號(hào)媒體包、0號(hào)冗余包。因?yàn)榻邮盏拿襟w包數(shù)為8個(gè)加接收的冗余包數(shù)1個(gè),總數(shù)小于總媒體包數(shù)(10個(gè)),因此接收端FEC無法恢復(fù)。對(duì)于第二個(gè)GROUP,只丟失了兩個(gè)媒體包,可以正常恢復(fù)。實(shí)驗(yàn)結(jié)果如下圖5所示,說明了推斷的正確性,0號(hào)媒體包、5號(hào)媒體包丟失,13號(hào)、18號(hào)媒體包被成功恢復(fù),系統(tǒng)丟包率從20%降低到10%左右。
圖5 ?20%冗余度時(shí),每5個(gè)包丟棄1個(gè)包時(shí)的恢復(fù)情況
(B)音視頻實(shí)測(cè)DEMO
圖6 音視頻實(shí)測(cè)DEMO
本DEMO支持如下特性:
(1)使用Direct進(jìn)行攝像頭、麥克風(fēng)的采集和輸出
(2)使用ffmpeg進(jìn)行高效圖像縮放等前置filter
(3)視頻H264?HighProfile編碼、解碼
(4)音頻AAC-LC、AAC-LD、AAC-ELD編碼、解碼(三種標(biāo)準(zhǔn)可選,44.1KHZ?16bit?2通道立體聲)
(5)音視頻RTP傳輸(帶FEC\QOS功能)
(6)人為丟包測(cè)試功能
(7)實(shí)時(shí)統(tǒng)計(jì)輸出線路丟包延時(shí)情況
DEMO的內(nèi)部框架如下圖7所示:
圖7 ?DEMO內(nèi)部線程框架
在視頻采集縮放線程與視頻編碼線程之間,我們采用高效的雙隊(duì)列機(jī)制(隊(duì)列元素為指針,進(jìn)出隊(duì)列無數(shù)據(jù)拷貝),如果視頻編碼性能非常充足的情況下,我們也可以將二者合并為一個(gè)線程。編碼線程與網(wǎng)絡(luò)發(fā)送線程分離,避免網(wǎng)絡(luò)擁塞影響編碼線程(這個(gè)對(duì)于UDP來說不成立,但對(duì)于RTMP這類TCP系統(tǒng)來說,網(wǎng)絡(luò)收發(fā)線程與音視頻編解碼線程的分離是必須的,因?yàn)榫W(wǎng)絡(luò)的抖動(dòng)將影響音視頻處理環(huán)節(jié)。站在系統(tǒng)設(shè)計(jì)的角度,我們?yōu)閁DP和TCP統(tǒng)一使用上述架構(gòu))。
在音視頻發(fā)送模塊內(nèi),我們都配有定時(shí)握手包發(fā)送線程,這個(gè)線程與音視頻使用相同的發(fā)送通道(端口),僅在包頭上予以區(qū)別。它的作用非常重要,主要包括兩個(gè)方面:為NAT穿越提供保障,當(dāng)我們的客戶端(內(nèi)網(wǎng)IP)向服務(wù)器(公網(wǎng)IP)發(fā)送數(shù)據(jù)時(shí),鏈路路由器會(huì)為該通訊鏈路映射“端口”,這樣服務(wù)器(公網(wǎng)IP)向該客戶端發(fā)送數(shù)據(jù)時(shí),只需將收到的數(shù)據(jù)包的IP地址和端口翻轉(zhuǎn)作為發(fā)送目標(biāo)IP和端口便能向其發(fā)送數(shù)據(jù)。路由器在收到服務(wù)器的數(shù)據(jù)包時(shí),檢查本地存在對(duì)應(yīng)的映射“端口”,予以放行,否則將丟棄這一數(shù)據(jù)包(這是基于安全的考慮,外網(wǎng)向內(nèi)網(wǎng)發(fā)送數(shù)據(jù)不得不防)。值得注意的是,路由器上“端口”是有時(shí)效性的,超過一定時(shí)間即會(huì)失效,為了保證服務(wù)器能持續(xù)有效的向客戶端發(fā)送數(shù)據(jù),客戶端必須以心跳包的方式向服務(wù)器發(fā)送數(shù)據(jù)以保持“端口”的有效性(客戶端根據(jù)業(yè)務(wù)情況不一定向服務(wù)器持續(xù)發(fā)送數(shù)據(jù)包,可能只作為接收者)。以上是對(duì)C/S模式下NAT的簡(jiǎn)要描述,P2P模式等其他情況請(qǐng)參考專門的資料。定時(shí)握手包的另一個(gè)作用是傳輸自定義的信道統(tǒng)計(jì)數(shù)據(jù),這個(gè)類似于RTCP協(xié)議,接收方統(tǒng)計(jì)出下行丟包率后可以通過本握手包告知發(fā)送方,以便通知對(duì)方調(diào)整發(fā)送甚至編碼策略。
音頻的處理流程與視頻類似,因?yàn)橐纛l編碼耗時(shí)非常低,我們一般將音頻采集與編碼放到一個(gè)線程內(nèi)進(jìn)行。音頻的輸出與視頻不同,因?yàn)樗枰垂潭ǖ妮敵鲱l率工作,驅(qū)動(dòng)將發(fā)起定時(shí)輸出線程,我們只需要在該線程內(nèi)向指定內(nèi)存存入指定數(shù)量的PCM數(shù)據(jù)即可。(輸出頻率、存放數(shù)量由音頻輸出通道數(shù)、采樣率、采樣點(diǎn)字節(jié)數(shù)的配置而定)
若本地IP與遠(yuǎn)端IP設(shè)置一樣,DEMO則進(jìn)入本地回環(huán)模式,此時(shí)將不存在任何網(wǎng)絡(luò)丟包,我們可以通過設(shè)置手動(dòng)丟包來模擬測(cè)試。若本地IP與遠(yuǎn)端IP不同,且不屬于同一網(wǎng)段,我們可以使用開源的WANEM來進(jìn)行模擬丟包、延時(shí)、抖動(dòng)、重復(fù)包等情況,這一方式后面我們將專門予以介紹。
注意:真實(shí)的視頻對(duì)比效果請(qǐng)?zhí)D(zhuǎn)視頻對(duì)比效果觀看
?圖8 使用4%隨機(jī)丟包,關(guān)閉FEC時(shí)經(jīng)常性花屏,聲音間歇斷續(xù)
當(dāng)使用4%隨機(jī)丟包時(shí),若關(guān)閉發(fā)端FEC功能,接收端視頻將出現(xiàn)經(jīng)常性花屏,聲音出現(xiàn)丟失斷續(xù)。若使用20%冗余度,視頻花屏概率將大幅降低(不會(huì)完全消除,因?yàn)閬G包是隨機(jī)的,短時(shí)間內(nèi)可能出現(xiàn)連續(xù)大量丟包的情況,超過20%冗余度的無失真抗丟包率是16.67%即會(huì)出現(xiàn)花屏)
若使用按間隔丟包,每6個(gè)包丟一個(gè)(丟包率將恒定為16.67%),此時(shí)選擇20%冗余度可以實(shí)現(xiàn)無失真恢復(fù),視頻流暢無花屏,音質(zhì)良好無斷續(xù)。
圖7 使用16.67%恒定丟包,F(xiàn)EC使用20%冗余度時(shí)音視頻效果良好