首页 > 编程知识 正文

webrtc视频解码,阅读的逻辑有配套视频吗

时间:2023-05-06 15:17:00 阅读:153466 作者:4842

本文组织了webrtc的Nack包发送机制,主要包括三个部分。

第一部分介绍了RTCP分组中Nack分组的规范。

第二部分介绍了WEBRTC中Nack发送机制的数据流图。

第三部分介绍了Nack在WEBRTC中处理的重要代码。

(一) RTCP Nack消息分析)0)2)4)8)9)1)3)5)8%1---------|v=2| p|fmt|pt|length------|5|v|v|v ssrcofmediasource---------------- 3360 feedbackcontrolinformation---- fci---330 nack2- 30: unassigned 31: reservedforfutureexpansionoftheidentifiernumberspacepayace PE (pt )为33608 bitsthisisthertcpppace tasbeinganrtcpfbmessage.twovaluesaredefinedbytheiana 3360 name|value | brief description-----------------------brief description------------------------------------ - ----------------------------------- - cFBmessageSSRCpacketsender :构成发送当前消息包的一方的SSRC ssrc source: NACK消息部分。 也是ssrc值。 这里可以称为媒体源标识符thefeedbackcontrolinformation (fci ) fieldhasthefollowingsyntax 012012345789013579457878901345781-----fci ----------------------------------- -

对于NACK message PT=RTPFB

FMT=1

丢包是10、20、30、40和50。 可以在三个int中清楚地表示,在rfc 4585的通用协议中表示如下

实时传输控制协议(genericrtpfeedback ) )。 3360 nack :2帧丢失: nack :2帧丢失:2帧丢失: nack :1帧丢失10 .=version : RFC 1889版本(2) ) ) .0.=padding : false . 00001=rtcpfeedbackmessagetype (fmt ) : genericnegativeacknowledgement (nack )1)包

(24 bytes) Sender SSRC: 0x00123456 (1193046) Media source SSRC: 0x00c0ffed (12648429) RTCP Transport Feedback NACK PID: 10 RTCP Transport Feedback NACK BLP: 0x0200 (Frames 20 lost) RTCP Transport Feedback NACK PID: 30 RTCP Transport Feedback NACK BLP: 0x0200 (Frames 40 lost) RTCP Transport Feedback NACK PID: 50 RTCP Transport Feedback NACK BLP: 0x0000 (No additional frames lost)

PID为10,表示sequence为10的包,BLP的第10位为1,表示10之后第10个包,即sequence num为20的包,所以一个int可以表示17个连续包的丢包情况。

二:Nack包发送流程图

三:Nack在webrtc中的计算 VideoStream接收端的处理

添加Nack 包到nack_list_中去

void NackModule::AddPacketsToNack(uint16_t seq_num_start, uint16_t seq_num_end) { // Remove old packets. auto it = nack_list_.lower_bound(seq_num_end - kMaxPacketAge); nack_list_.erase(nack_list_.begin(), it); // If the nack list is too large, remove packets from the nack list until // the latest first packet of a keyframe. If the list is still too large, // clear it and request a keyframe. uint16_t num_new_nacks = ForwardDiff(seq_num_start, seq_num_end); if (nack_list_.size() + num_new_nacks > kMaxNackPackets) { while (RemovePacketsUntilKeyFrame() && nack_list_.size() + num_new_nacks > kMaxNackPackets) { } if (nack_list_.size() + num_new_nacks > kMaxNackPackets) { nack_list_.clear(); LOG(LS_WARNING) << "NACK list full, clearing NACK" " list and requesting keyframe."; keyframe_request_sender_->RequestKeyFrame(); return; } } //在Start 和 End之间的RTP包,就是需要发Nack的包。 for (uint16_t seq_num = seq_num_start; seq_num != seq_num_end; ++seq_num) { NackInfo nack_info(seq_num, seq_num + WaitNumberOfPackets(0.5)); RTC_DCHECK(nack_list_.find(seq_num) == nack_list_.end()); nack_list_[seq_num] = nack_info; } }

根据不同的kSeqNumOnly, kTimeOnly模式,来选择需要重发的包

std::vector<uint16_t> NackModule::GetNackBatch(NackFilterOptions options) { bool consider_seq_num = options != kTimeOnly; bool consider_timestamp = options != kSeqNumOnly; int64_t now_ms = clock_->TimeInMilliseconds(); std::vector<uint16_t> nack_batch; auto it = nack_list_.begin(); while (it != nack_list_.end()) { if (consider_seq_num && it->second.sent_at_time == -1 && AheadOrAt(newest_seq_num_, it->second.send_at_seq_num)) { nack_batch.emplace_back(it->second.seq_num); ++it->second.retries; it->second.sent_at_time = now_ms; if (it->second.retries >= kMaxNackRetries) { LOG(LS_VERBOSE) << "Sequence number " << it->second.seq_num << " removed from NACK list due to max retries." << " newest_seq_num " << newest_seq_num_ << " it->second.send_at_seq_num " << it->second.send_at_seq_num ; it = nack_list_.erase(it); } else { ++it; } continue; } if (consider_timestamp && it->second.sent_at_time + rtt_ms_ <= now_ms) { nack_batch.emplace_back(it->second.seq_num); ++it->second.retries; it->second.sent_at_time = now_ms; if (it->second.retries >= kMaxNackRetries) { LOG(LS_VERBOSE) << "Sequence number " << it->second.seq_num << " removed from NACK list due to max retries." << " rtt_ms " << rtt_ms_ ; it = nack_list_.erase(it); } else { ++it; } continue; } ++it; } return nack_batch; } VideoSendStream端的处理

收到OnReceivedNack事件

int32_t RTPSender::ReSendPacket(uint16_t packet_id, int64_t min_resend_time) { // 根据RTT,去从队列里找到还能发送的RTP包 std::unique_ptr<RtpPacketToSend> packet = packet_history_.GetPacketAndSetSendTime(packet_id, min_resend_time, true); if (!packet) { // Packet not found. LOG(LS_VERBOSE) << "ResendPacket packet not found " << " pktid " << packet_id << " min_resend_time " << min_resend_time ; return 0; } 。。。。。。 if (paced_sender_) { // Convert from TickTime to Clock since capture_time_ms is based on // TickTime. int64_t corrected_capture_tims_ms = packet->capture_time_ms() + clock_delta_ms_; // 添加到Pace Sender里去发送 paced_sender_->InsertPacket(RtpPacketSender::kNormalPriority, packet->Ssrc(), packet->SequenceNumber(), corrected_capture_tims_ms, packet->payload_size(), true); 。。。。。。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。