因?yàn)楫?dāng)前版本使用發(fā)送端帶寬預(yù)測(SendSideBWE)匾七,所以接收端使用 RemoteEstimatorProxy 負(fù)責(zé)構(gòu)造 RTCP 包,并通知 TransportFeedbackSenderInterface 發(fā)送 RTCP 包。
// /modules/remote_bitrate_estimator/remote_estimator_proxy.cc
// 接收端發(fā)送RTCP
void RemoteEstimatorProxy::Process() {
BuildFeedbackPacket(&feedback_packet)
feedback_sender_->SendTransportFeedback(&feedback_packet);
}
// 構(gòu)造Feedback Packet
bool RemoteEstimatorProxy::BuildFeedbackPacket(
rtcp::TransportFeedback* feedback_packet) {
const int64_t first_sequence = it->first;
feedback_packet->SetMediaSsrc(media_ssrc_);
feedback_packet->SetBase(static_cast<uint16_t>(window_start_seq_ & 0xFFFF),
it->second * 1000);
feedback_packet->SetFeedbackSequenceNumber(feedback_sequence_++);
for (; it != packet_arrival_times_.end(); ++it) {
if (!feedback_packet->AddReceivedPacket(
static_cast<uint16_t>(it->first & 0xFFFF), it->second * 1000)) {
break;
}
window_start_seq_ = it->first + 1;
}
return true;
}
TransportFeedbackSenderInterface 作為父類煮盼,由 PacketRouter 繼承,并實(shí)現(xiàn)通知 RtpRtcp 發(fā)送 RTCP 包的成員函數(shù) SendTransportFeedback()哥童。
// src/modules/pacing/packet_router.cc
// 發(fā)送TransportFeedback包
bool PacketRouter::SendTransportFeedback(rtcp::TransportFeedback* packet) {
rtp_module->SendFeedbackPacket(*packet);
}
RtpRtcp 作為父類速缨,由 ModuleRtpRtcpImpl 繼承杏头,并實(shí)現(xiàn)通知 RTCPSender 發(fā)送 RTCP 包的成員函數(shù) SendFeedbackPacket()。
// src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
bool ModuleRtpRtcpImpl::SendFeedbackPacket(
const rtcp::TransportFeedback& packet) {
return rtcp_sender_.SendFeedbackPacket(packet);
}
RTCPSender 負(fù)責(zé)將 RTCP 包實(shí)際交給 Transport 進(jìn)行傳輸沸呐。
// src/modules/rtp_rtcp/source/rtcp_sender.cc
// 發(fā)送TransportFeedback包
bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
transport_->SendRtcp(packet.data(), packet.size());
return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
!sender.send_failure_;
}
Transport 作為父類醇王,由 WebRtcVideoChannel 繼承并實(shí)現(xiàn)成員函數(shù) SendRtcp(),將 RTCP 包交給 MediaChannel 發(fā)送崭添。
// src/media/engine/webrtcvideoengine.cc
bool WebRtcVideoChannel::SendRtcp(const uint8_t* data, size_t len) {
rtc::CopyOnWriteBuffer packet(data, len, kMaxRtpPacketLen);
return MediaChannel::SendRtcp(&packet, rtc::PacketOptions());
}
MediaChannel 執(zhí)行 SendRtcp 方法調(diào)用 MediaChannel::NetworkInterface 真正發(fā)送 RTCP 包
// src/media/base/mediachannel.h
bool SendRtcp(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options) {
return DoSendPacket(packet, true, options);
}
bool DoSendPacket(rtc::CopyOnWriteBuffer* packet,
bool rtcp,
const rtc::PacketOptions& options) {
rtc::CritScope cs(&network_interface_crit_);
if (!network_interface_)
return false;
return (!rtcp) ? network_interface_->SendPacket(packet, options)
: network_interface_->SendRtcp(packet, options);
}
MediaChannel::NetworkInterface 作為父類寓娩,由 BaseChannel 繼承并實(shí)現(xiàn)成員函數(shù) SendRtcp()
// src/pc/channel.cc
bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options) {
return SendPacket(true, packet, options);
}
bool BaseChannel::SendPacket(bool rtcp,
rtc::CopyOnWriteBuffer* packet,
const rtc::PacketOptions& options) {
// ...
// Bon voyage.
return rtcp ? rtp_transport_->SendRtcpPacket(packet, options, PF_SRTP_BYPASS)
: rtp_transport_->SendRtpPacket(packet, options, PF_SRTP_BYPASS);
}
//src/pc/rtptransportinternal.h