WebRTC RTP/RTCP 源码分析(三):RTCP 的构造和发送

基于 Chromium M69版本

因为当前版本使用发送端带宽预测(SendSideBWE),所以接收端使用 RemoteEstimatorProxy 负责构造 RTCP 包,并通知 TransportFeedbackSenderInterface 发送 RTCP 包。

// /modules/remote_bitrate_estimator/remote_estimator_proxy.cc
// 接收端发送RTCP
void RemoteEstimatorProxy::Process() {
  BuildFeedbackPacket(&feedback_packet)
  feedback_sender_->SendTransportFeedback(&feedback_packet);
}
// 构造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(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(it->first & 0xFFFF), it->second * 1000)) {
            break;
        }
        window_start_seq_ = it->first + 1;
    }
    return true;
}

TransportFeedbackSenderInterface 作为父类,由 PacketRouter 继承,并实现通知 RtpRtcp 发送 RTCP 包的成员函数 SendTransportFeedback()。

// src/modules/pacing/packet_router.cc
// 发送TransportFeedback包
bool PacketRouter::SendTransportFeedback(rtcp::TransportFeedback* packet) {
  rtp_module->SendFeedbackPacket(*packet);
}

RtpRtcp 作为父类,由 ModuleRtpRtcpImpl 继承,并实现通知 RTCPSender 发送 RTCP 包的成员函数 SendFeedbackPacket()。

// src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
bool ModuleRtpRtcpImpl::SendFeedbackPacket(
    const rtcp::TransportFeedback& packet) {
  return rtcp_sender_.SendFeedbackPacket(packet);
}

RTCPSender 负责将 RTCP 包实际交给 Transport 进行传输。

// src/modules/rtp_rtcp/source/rtcp_sender.cc
// 发送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 继承并实现成员函数 SendRtcp(),将 RTCP 包交给 MediaChannel 发送。

// 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 执行 SendRtcp 方法调用 MediaChannel::NetworkInterface 真正发送 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 继承并实现成员函数 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

你可能感兴趣的:(WebRTC RTP/RTCP 源码分析(三):RTCP 的构造和发送)