在webrtc中,处理rtcp,目前的版本是在, rtcp_sender.h 和 rtcp_sender.cpp中实现;
当收到rtcp packet时,调用过程,主要是以下三个函数:
接收-》解析-》响应;
IncomingPacket -》{ ParseCompoundPacket -》 TriggerCallbacksFromRtcpPacket };
当然,还是实现了(根据rtcp)延时计算:
// Get rtt.
int32_t RTT(uint32_t remote_ssrc,
int64_t* last_rtt_ms,
int64_t* avg_rtt_ms,
int64_t* min_rtt_ms,
int64_t* max_rtt_ms) const;
void RTCPReceiver::IncomingPacket(const uint8_t* packet, size_t packet_size) {
if (packet_size == 0) {
RTC_LOG(LS_WARNING) << "Incoming empty RTCP packet";
return;
}
PacketInformation packet_information;
if (!ParseCompoundPacket(packet, packet + packet_size, &packet_information))
return;
TriggerCallbacksFromRtcpPacket(packet_information);
}
ParseCompoundPacket,是解析函数,直接看源码;
说明一下这个响应函数:
RTCPReceiver::TriggerCallbacksFromRtcpPacket;
这个函数,响应了,TMMBR and RTMB,NACK,和 Pli/Fir/Pli;
再说明一下 Pli/Fir/Pli:对关键帧的请求;
if (rtcp_intra_frame_observer_) {
RTC_DCHECK(!receiver_only_);
if ((packet_information.packet_type_flags & kRtcpPli) ||
(packet_information.packet_type_flags & kRtcpFir)) {
if (packet_information.packet_type_flags & kRtcpPli) {
RTC_LOG(LS_VERBOSE)
<< "Incoming PLI from SSRC " << packet_information.remote_ssrc;
} else {
RTC_LOG(LS_VERBOSE)
<< "Incoming FIR from SSRC " << packet_information.remote_ssrc;
}
rtcp_intra_frame_observer_->OnReceivedIntraFrameRequest(local_ssrc);
}
}
OnReceivedIntraFrameRequest函数会最后在本地产生一个相关的关键帧;
再看一个函数:
响应Fir,然后设置packet_type_flags;
void RTCPReceiver::HandleFir(const CommonHeader& rtcp_block,
PacketInformation* packet_information) {
rtcp::Fir fir;
if (!fir.Parse(rtcp_block)) {
++num_skipped_packets_;
return;
}
for (const rtcp::Fir::Request& fir_request : fir.requests()) {
// Is it our sender that is requested to generate a new keyframe.
if (main_ssrc_ != fir_request.ssrc)
continue;
++packet_type_counter_.fir_packets;
int64_t now_ms = clock_->TimeInMilliseconds();
auto inserted = last_fir_.insert(std::make_pair(
fir.sender_ssrc(), LastFirStatus(now_ms, fir_request.seq_nr)));
if (!inserted.second) { // There was already an entry.
LastFirStatus* last_fir = &inserted.first->second;
// Check if we have reported this FIRSequenceNumber before.
if (fir_request.seq_nr == last_fir->sequence_number)
continue;
// Sanity: don't go crazy with the callbacks.
if (now_ms - last_fir->request_ms < kRtcpMinFrameLengthMs)
continue;
last_fir->request_ms = now_ms;
last_fir->sequence_number = fir_request.seq_nr;
}
// Received signal that we need to send a new key frame.
packet_information->packet_type_flags |= kRtcpFir;
}
}
来源:CSDN
作者:chinabinlang
链接:https://blog.csdn.net/chinabinlang/article/details/80132380