将 当前收包序列号:sequence_number 从丢包集合 nack_list_ 中剔除;
将 sequence_number 与 最近收到的新包:sequence_num_last_received_rtp_ 对比,判断当前包是否为重传或乱序包。如若是的话,直接终止判断,否则继续;
对比 当前包 与 最新收到的包 的序列号与时间戳,更新每个包的样本数:samples_per_packet_;
更新 nack_list_ 中部分包的丢包状态:is_missing = true,这些包我们之前认为后续再考虑,现在需要把它们当做丢包。这些包满足:序列号 在 sequence_number - nack_threshold_packets_ 之前(nack_threshold_packets_ = 2);
如果 最新收到的包 与 当前包 不连续,则区间内的包都要被放到 nack_list_,其中那些太旧的包(判断标准同上一步)会被直接认为丢包,剩下的包当后续包达到时,会在上一步中再明确是否为丢包;
将 最近收到的新包 的序列号: sequence_num_last_received_rtp_ 与时间戳更新为 当前包 的序列号与时间戳;
丢弃掉集合 nack_list_ 中不能重传的包信息,同时保证集合容量不超过限制(最大容量 max_nack_list_size_ = 500,即对于单位长度为 20ms 的帧,保留 10s 长度)。不能重传的包满足序列号在 最新收到的包序列号 - static_cast
本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓
- /*
- sequence_number:当前收到的包的序列号
- timestamp:当前收到的包的时间戳
- */
- void NackTracker::UpdateLastReceivedPacket(uint16_t sequence_number, uint32_t timestamp)
- {
- /*
- 如果这是第一个包
- any_rtp_received_ = true,表示收到了任意包
- */
- if (!any_rtp_received_)
- {
- /* 第一个包仅仅记录序列号与时间戳 */
- sequence_num_last_received_rtp_ = sequence_number;
- timestamp_last_received_rtp_ = timestamp;
- any_rtp_received_ = true;
-
- // If no packet is decoded, to have a reasonable estimate of time-to-play
- // use the given values.
- if (!any_rtp_decoded_)
- {
- sequence_num_last_decoded_rtp_ = sequence_number;
- timestamp_last_decoded_rtp_ = timestamp;
- }
-
- return;
- }
-
- /* 如果是上一个包, */
- if (sequence_number == sequence_num_last_received_rtp_)
- return;
-
- /* nack_list_:丢包集合 */
- nack_list_.erase(sequence_number);
-
- /*
- 将当前包 与 最近收到的新包 对比,判断当前包是否为重传或乱序包
- 是的话,直接返回
- */
- if (IsNewerSequenceNumber(sequence_num_last_received_rtp_, sequence_number))
- return;
-
- /* 对比 当前包 与 最新收到的包 的序列号与时间戳,更新每个包的样本数:samples_per_packet_ */
- UpdateSamplesPerPacket(sequence_number, timestamp);
-
- /* 更新丢包集合:nack_list_ */
- UpdateList(sequence_number);
-
- /* 更新最新收包的序列号与时间戳 */
- sequence_num_last_received_rtp_ = sequence_number;
- timestamp_last_received_rtp_ = timestamp;
-
- /* 丢弃掉集合 nack_list_ 中不能重传的包信息,同时保证集合容量不超过限制 */
- LimitNackListSize();
- }
- void NackTracker::UpdateList(uint16_t sequence_number_current_received_rtp)
- {
- /*
- 更新 nack_list_ 中部分包的丢包状态:is_missing = true,
- 这些包我们之前认为后续再考虑,现在需要把它们当做丢包
- */
- ChangeFromLateToMissing(sequence_number_current_received_rtp);
-
- /*
- 如果当前收到的包 比 sequence_num_last_received_rtp_ + 1 新,
- 即:最近收到的新包 与 当前收到的包 不连续
- */
- if (IsNewerSequenceNumber(sequence_number_current_received_rtp,
- sequence_num_last_received_rtp_ + 1))
- AddToList(sequence_number_current_received_rtp);
- }
- void NackTracker::ChangeFromLateToMissing(uint16_t sequence_number_current_received_rtp)
- {
- /*
- nack_threshold_packets_ = 2,表示:
- 当序列号为 N 的包到达时,序列号在 ( , N - |nack_threshold_packets_| ) 区间、所有未到达的包,都会被认为丢失
- 而对于序列号在 [ N - |nack_threshold_packets_| , N-1 ] 区间、所有未达到的包,后面再考虑
- */
- /* 查找 大于等于 N - |nack_threshold_packets_| 的第一个元素 */
- NackList::const_iterator lower_bound =
- nack_list_.lower_bound(static_cast<uint16_t>(
- sequence_number_current_received_rtp - nack_threshold_packets_));
-
- for (NackList::iterator it = nack_list_.begin(); it != lower_bound; ++it)
- it->second.is_missing = true;
- }
- void NackTracker::AddToList(uint16_t sequence_number_current_received_rtp)
- {
- assert(!any_rtp_decoded_ ||
- IsNewerSequenceNumber(sequence_number_current_received_rtp,
- sequence_num_last_decoded_rtp_));
-
- /*
- 序列号在 upper_bound_missing 之前的包(不包括 upper_bound_missing),都认为是丢包,添加到 nack_list_
- upper_bound_missing 以及之后的包,一并添加到 nack_list_,但后面再考虑
- */
- uint16_t upper_bound_missing =
- sequence_number_current_received_rtp - nack_threshold_packets_;
-
- /*
- 最近收到的新包 到 当前收到的包 区间内的包,都可能是丢包,都会被添加到 nack_list_
- 但只有在 upper_bound_missing 之前的包,才直接认为丢包
- */
- for (uint16_t n = sequence_num_last_received_rtp_ + 1;
- IsNewerSequenceNumber(sequence_number_current_received_rtp, n); ++n)
- {
- bool is_missing = IsNewerSequenceNumber(upper_bound_missing, n);
- uint32_t timestamp = EstimateTimestamp(n);
- NackElement nack_element(TimeToPlay(timestamp), timestamp, is_missing);
- nack_list_.insert(nack_list_.end(), std::make_pair(n, nack_element));
- }
- }
- void NackTracker::LimitNackListSize()
- {
- /* max_nack_list_size_ = 500 */
- uint16_t limit = sequence_num_last_received_rtp_ - static_cast<uint16_t>(max_nack_list_size_) - 1;
-
- /* 删除 [ start, end ) 区间内的节点 */
- nack_list_.erase(nack_list_.begin(), nack_list_.upper_bound(limit));
- }
本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓