前面我分享了一篇視頻從Android端采集到編碼發(fā)送模塊的博客,對于平滑發(fā)送模塊只是代碼略過,這篇博客我具體來分析一下webrtc中的pasedsender發(fā)送到底是如何調(diào)控的:
首先拋出一個(gè)問題,為什么需要平滑發(fā)送?
對于camera采集的數(shù)據(jù),經(jīng)過編碼器編碼之后,會經(jīng)過rtp組裝,可能切片為多個(gè)rtp包,此時(shí)下一步就應(yīng)該是送入發(fā)送模塊,發(fā)送到遠(yuǎn)端了,但是由于網(wǎng)絡(luò)是不斷變化的,假如網(wǎng)絡(luò)本來有點(diǎn)擁塞了,而此時(shí)一幀視頻,比如說I幀編碼后的數(shù)據(jù)很大,立馬全部發(fā)送到發(fā)送模塊進(jìn)行發(fā)送的話,這樣無疑會加大網(wǎng)絡(luò)擁塞,影響通信質(zhì)量,若視頻質(zhì)量相對較低,編碼出來的碼率相對較低,視頻較為流暢,而此時(shí)提高質(zhì)量,也有可能導(dǎo)致網(wǎng)絡(luò)利用率不夠而導(dǎo)致的丟包和擁塞,所以webrtc用到了pasedsender平滑發(fā)送,那么我們直接開始研究代碼模塊:
? ? 發(fā)送模塊在process_thread_impl.cc中ProcessThreadImpl::Process()函數(shù)中進(jìn)行處理
? ? --> GetNextCallbackTime() //獲取下一次發(fā)送時(shí)間
? ? --> PasedSender::TimeUntilNextProcess()??獲取下次Process()調(diào)用的時(shí)間
? ? --> BitrateProber::TimeUntiNextProbe() 獲取下次Process()調(diào)用的時(shí)間間隔? 在Process() 實(shí)現(xiàn)wake_up->Wait()
? ? -->PasedSender::Process() 平滑發(fā)送核心? 主要功能是SendPacket即更新預(yù)算,我寫出幾個(gè)重要流程
? ? ? ? {1.UpdateBugetWithElapsedTime()? 根據(jù)延時(shí)和碼率,結(jié)合發(fā)送隊(duì)列大小,更新預(yù)算
? ? ? ? ? ? 2.BitrateProber::RecommendedMinProbeSize() 計(jì)算出此次發(fā)送的數(shù)據(jù)總量
? ? ? ? ? ? 3.if(!packets->Empty()){//發(fā)送數(shù)據(jù)} else{setpadding() 發(fā)送padding數(shù)據(jù)以保持碼率的準(zhǔn)確}}
然后根據(jù)計(jì)算出的wait時(shí)間循環(huán)從packets取數(shù)據(jù),取多少數(shù)據(jù)由碼率,延時(shí)實(shí)時(shí)計(jì)算得到
上面是PasedSender發(fā)送的核心代碼解釋,這里我還想說明一下碼率的關(guān)系
我們這里的發(fā)送碼率是上行帶寬的碼率,是音視頻共同發(fā)送的碼率,這個(gè)在測試中其實(shí)是很重要的:
上行帶寬碼率 = 音頻上行碼率 + 視頻上行碼率 + rtcpSender碼率 + padding碼率
音頻上行碼率 = 音頻編碼碼率 + fec碼率
視頻上行碼率 = 視頻編碼碼率 + fec碼率
后面我在專門分享一篇關(guān)于fec和音視頻包的組合模塊,看在rtp組包時(shí)候,如何根據(jù)丟包率,延時(shí)和碼率來設(shè)置fec冗余度范圍,降低延時(shí)和丟包率,提高音視頻流暢