NackModule
一個包的最大請求次數是10次,最大請求時間是10*rtt,在這個時間內還沒有獲取到丟失的包則不再請求
對外提供的接口如下,源碼
int OnReceivedPacket(const VCMPacket& packet);
void ClearUpTo(uint16_t seq_num);
void UpdateRtt(int64_t rtt_ms);
void Clear();
int64_t TimeUntilNextProcess() override;
void Process() override;
- OnReceivedPacket
數據走向:RtpReceiverImpl::IncomingRtpPacket
->RTPReceiverVideo::ParseRtpPacket
->RtpVideoStreamReceiver::OnReceivedPayloadData
->NackModule::OnReceivedPacket
- IncomingRtpPacket
數據從網卡過來,經過上一層的分發(每個ssrc會對應一個RtpReceiver實例),這裏會根據payloadType得到對應的視頻編解碼類型
- IncomingRtpPacket
- ParseRtpPacket
根據視頻編解碼類型調用對應的RtpDepacketizer解析此包,得到幀類型(FrameType
)和幀信息(RTPTypeHeader
->RTPVideoHeader
)等信息 - OnReceivedPayloadData
添加ntp時間直接交付給nack模塊
- 所以到了nack模塊是可以知道此包是否是關鍵幀的包,是否是一幀的第一個包,包序號等信息。
- 例如收到
1 2 3 6 7 4 5
等包,那麼在收到序號爲6的包的時候就認爲4和5這兩個包丟失了,具體可以閱讀AddPacketsToNack
這個函數,然後把4和5兩個包加入到nack列表中(nack_list_),當收到5這個包的時候從nack列表中移除 - 調用
GetNackBatch(kSeqNumOnly)
找到缺失的包序號,kSeqNumOnly選項觸發第一次nack請求,所以nack請求是非常及時的
-
ClearUpTo
此函數最終是由幀緩觸發的FrameBuffer::InsertFrame
,幀緩衝只保留kMaxFramesBuffered
幀,並且當幀是亂序的時候也不要此幀。清除到此序號的nack列表和關鍵幀列表 -
UpdateRtt
更新rtt時間,第一個包的nack觸發以後,後面的9次觸發都是依據rtt時間而定的。也就是說nack請求的間隔是nack1 rtt nack2 rtt nack3 ...
-
Clear
清空nack列表和關鍵幀列表 -
TimeUntilNextProcess
獲取下一次執行Processc
的時間 -
Process
依據rtt找到當前需要發送的nack序號,並遞增nack的重試次數(retries),當超過最大重試次數時,不再請求此序號