WebRTC服务质量(01)- Qos概述
WebRTC服务质量(02)- RTP协议
WebRTC服务质量(03)- RTCP协议
WebRTC服务质量(04)- 重传机制(01) RTX NACK概述
WebRTC服务质量(05)- 重传机制(02) NACK判断丢包
WebRTC服务质量(06)- 重传机制(03) NACK找到真正的丢包
WebRTC服务质量(07)- 重传机制(04) 接收NACK消息
WebRTC服务质量(08)- 重传机制(05) RTX机制
WebRTC服务质量(09)- Pacer机制(01) 流程概述
WebRTC服务质量(10)- Pacer机制(02) RoundRobinPacketQueue
WebRTC服务质量(11)- Pacer机制(03) IntervalBudget
WebRTC服务质量(12)- Pacer机制(04) 向Pacer中插入数据
一、前言:
上一篇文章我们记录了丢包,但是这些包都是一些可疑丢包
,本文我们就分析下如何从可疑丢包
中找到真正丢包
。
二、OnReceivedPacket
先看下上一节的OnReceivedPacket
函数:
int DEPRECATED_NackModule::OnReceivedPacket(uint16_t seq_num,
bool is_keyframe,
bool is_recovered) {
// ...
// 此函数非常重要(拿到这个包到上一次的包newest_seq_num_中间所有丢失的包)
AddPacketsToNack(newest_seq_num_ + 1, seq_num);
// 这个就把这次的序列号seq_num赋值给newest_seq_num_,注意回影响后面逻辑
newest_seq_num_ = seq_num;
// Are there any nacks that are waiting for this seq_num.
// 判断真丢包还是假丢包(乱序),最终拿到真正的丢包
std::vector<uint16_t> nack_batch = GetNackBatch(kSeqNumOnly);
if (!nack_batch.empty()) {
// This batch of NACKs is triggered externally; the initiator can
// batch them with other feedback messages.
// 告诉对端,到底有哪些包丢失了,需要你重传
nack_sender_->SendNack(nack_batch, /*buffering_allowed=*/true);
}
return 0;
}
我们先分析下,什么情况下会走到这儿:
-
不是第一个包,不进行初始化;
-
不是一个重复的包;
-
不是在newest_seq_num_之前的包(不是乱序包);
-
不是一个恢复包;
-
那么只剩下两种情况:
- 这个包seq刚好是newest_seq_num_ + 1,
- 这个包seq序号为:newest_seq_num_ 隔了好几个包(这种情况,将中间隔的那几个包都得插入到nack_list当中)
1)逻辑说明:
这个时候我们的AddPacketsToNack
函数就天真地将所有跳过的包都加入重传列表nack_list
当中,认为是丢包,实际上,我们知道了传输层UDP的特点就是不靠谱
,都是分头行动,到目的地汇合,不会按照顺序来的,因此,我们首先要结合序列号
和时间戳
排除的就是这种情况,这些逻辑都在GetNackBatch
完成的。
三、GetNackBatch:
3.1、完整代码:
std::vector<uint16_t> DEPRECATED_NackModule::GetNackBatch(
NackFilterOptions options) {
bool consider_seq_num = options != kTimeOnly;
bool consider_timestamp = options != kSeqNumOnly;
Timestamp now = clock_->CurrentTime();
std::vector