/*
sequence_number:当前收到的包序列号
*/
bool VCMJitterBuffer::UpdateNackList(uint16_t sequence_number) {
if (nack_mode_ == kNoNack) {
return true;
}
// Make sure we don't add packets which are already too old to be decoded.
if (!last_decoded_state_.in_initial_state()) {
/* latest_received_sequence_number_:上一次收到的最新RTP包序列号 */
latest_received_sequence_number_ = LatestSequenceNumber(
latest_received_sequence_number_, last_decoded_state_.sequence_num());
}
/* 判断当前RTP包是否是新的数据包,而不是重传或者乱序包 */
if (IsNewerSequenceNumber(sequence_number, latest_received_sequence_number_))
{
/*
从 latest_received_sequence_number_ + 1 开始判断是否满足 IsNewerSequenceNumber,
即:判断当前包的序列号 sequence_number 是不是比排在 i 的后面,
是的话,说明 [latest_received_sequence_number_ + 1, latest_received_sequence_number_] 区间的包丢了
*/
for (uint16_t i = latest_received_sequence_number_ + 1; IsNewerSequenceNumber(sequence_number, i); ++i) {
/* 将序列号 i 添加到 missing_sequence_numbers_(std::set类型),被认为包已经丢失 */
missing_sequence_numbers_.insert(missing_sequence_numbers_.end(), i);
TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "AddNack", "seqnum", i);
}
/*
判断集合 missing_sequence_numbers_ 的容量是否超过最大限制
是的话,通过调用 RecycleFramesUntilKeyFrame 不断丢包来减少集合中的序列号
*/
if (TooLargeNackList() && !HandleTooLargeNackList())
{
LOG(LS_WARNING) << "Requesting key frame due to too large NACK list.";
return false;
}
/*
判断集合 missing_sequence_numbers_ 里的包是否太旧了
判断依据:当前包的序列号 sequence_number 与 集合 missing_sequence_numbers_ 中第一个包的序列号之间的差值是否超过限制
是的话,通过调用 RecycleFramesUntilKeyFrame 不断丢包来减少集合中的序列号
*/
if (MissingTooOldPacket(sequence_number) && !HandleTooOldPackets(sequence_number)) {
LOG(LS_WARNING) << "Requesting key frame due to missing too old packets";
return false;
}
}
else
{
/* 当前包是重传或者乱序包,直接从丢包集合中剔除 */
missing_sequence_numbers_.erase(sequence_number);
TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RemoveNack",
"seqnum", sequence_number);
}
return true;
}
判断 missing_sequence_numbers_ 容量是否超过限制:
注意:
max_nack_list_size_ = 250
bool VCMJitterBuffer::TooLargeNackList() const
{
return missing_sequence_numbers_.size() > max_nack_list_size_;
}
判断 missing_sequence_numbers_ 里的包是否太旧了:
注意:
max_packet_age_to_nack_ = 450
bool VCMJitterBuffer::MissingTooOldPacket(uint16_t latest_sequence_number) const
{
if (missing_sequence_numbers_.empty())
{
return false;
}
const uint16_t age_of_oldest_missing_packet =
latest_sequence_number - *missing_sequence_numbers_.begin();
// Recycle frames if the NACK list contains too old sequence numbers as
// the packets may have already been dropped by the sender.
return age_of_oldest_missing_packet > max_packet_age_to_nack_;
}
当 missing_sequence_numbers_ 容量超过限制或 序列号太久时,会循环调用 RecycleFramesUntilKeyFrame:
bool VCMJitterBuffer::HandleTooLargeNackList()
{
/*
回收 fames,直至 NACK list 足够的小
请求一个 key frame 比重传这么多丢失的包代价要小得多
*/
LOG_F(LS_WARNING) << "NACK list has grown too large: "
<< missing_sequence_numbers_.size() << " > "
<< max_nack_list_size_;
bool key_frame_found = false;
while (TooLargeNackList())
{
key_frame_found = RecycleFramesUntilKeyFrame();
}
return key_frame_found;
}
bool VCMJitterBuffer::HandleTooOldPackets(uint16_t latest_sequence_number)
{
bool key_frame_found = false;
const uint16_t age_of_oldest_missing_packet =
latest_sequence_number - *missing_sequence_numbers_.begin();
LOG_F(LS_WARNING) << "NACK list contains too old sequence numbers: "
<< age_of_oldest_missing_packet << " > "
<< max_packet_age_to_nack_;
while (MissingTooOldPacket(latest_sequence_number))
{
key_frame_found = RecycleFramesUntilKeyFrame();
}
return key_frame_found;
}
// Recycle oldest frames up to a key frame, used if jitter buffer is completely
// full.
bool VCMJitterBuffer::RecycleFramesUntilKeyFrame()
{
FrameList::iterator key_frame_it;
bool key_frame_found = false;
int dropped_frames = 0;
/*
释放不完整的 frames:
释放 incomplete_frames_(std::map类型)头部所有节点,直至遇到 kVideoFrameKey 类型的 frame
dropped_frames:释放的节点个数
key_frame_it:指向 incomplete_frames_ 中 kVideoFrameKey 类型的 frame,若不存在这样的节点,则 == map.end()
free_frames_:存储被释放的节点
key_frame_it != incomplete_frames_.end(),表示 incomplete_frames_ 存在 kVideoFrameKey 类型的 frame
key_frame_it == incomplete_frames_.end(),表示不存在这样的 frame,并且 incomplete_frames_ 中所有节点都被释放了
*/
dropped_frames += incomplete_frames_.RecycleFramesUntilKeyFrame(&key_frame_it, &free_frames_);
key_frame_found = key_frame_it != incomplete_frames_.end();
/* 不存在不完整的 frames,则释放可解码的 frames */
if (dropped_frames == 0)
{
dropped_frames += decodable_frames_.RecycleFramesUntilKeyFrame(&key_frame_it, &free_frames_);
key_frame_found = key_frame_it != decodable_frames_.end();
}
TRACE_EVENT_INSTANT0("webrtc", "JB::RecycleFramesUntilKeyFrame");
/* incomplete_frames_ 或 decodable_frames_ 中存在 kVideoFrameKey 类型的 frame */
if (key_frame_found)
{
LOG(LS_INFO) << "Found key frame while dropping frames.";
/*
重置 最近的解码状态,以保证下一个被解码的是 key frame,并从这里
*/
// Reset last decoded state to make sure the next frame decoded is a key
// frame, and start NACKing from here.
last_decoded_state_.Reset();
/*
将 missing_sequence_numbers_ 开头到 EstimatedLowSequenceNumber 区间所有空间释放
*/
DropPacketsFromNackList(EstimatedLowSequenceNumber(*key_frame_it->second));
}
else if (decodable_frames_.empty())
{
/*
所有 frames 都释放了
重置解码状态,并清空丢失的包序列号
*/
last_decoded_state_.Reset();
missing_sequence_numbers_.clear();
}
return key_frame_found;
}