WebRTC RTP/RTCP 源码分析(一):RTP 的发送

基于 Chromium M69版本

一、 RTP 发包的上层通知

  • PacedSender (最慢)每30ms就执行一次 Process(),即调用 PacketSender 发送。
// src/modules/pacing/paced_sender.cc
const int64_t kMaxIntervalTimeMs = 30;
bool PacedSender::SendPacket(const PacketQueueInterface::Packet& packet,
                             const PacedPacketInfo& pacing_info) {
  const bool success = packet_sender_->TimeToSendPacket(
     packet.ssrc, packet.sequence_number, packet.capture_time_ms,
     packet.retransmission, pacing_info);
}
  • PacketSender 作为父类,其定义如下:
// src/modules/pacing/paced_sender.h
class PacketSender {
 public:
  virtual bool TimeToSendPacket(uint32_t ssrc,
                                uint16_t sequence_number,
                                int64_t capture_time_ms,
                                bool retransmission,
                                const PacedPacketInfo& cluster_info) = 0;
  virtual size_t TimeToSendPadding(size_t bytes,
                                   const PacedPacketInfo& cluster_info) = 0;

 protected:
  virtual ~PacketSender() {}
};
  • PacketRouter 继承了 PacketSender 并实现其虚函数。PacedSender中调用的函数由此响应。 此处通知了 RtpRtcp 来实现发送。
// src/modules/pacing/packet_router.h
class PacketRouter : public PacedSender::PacketSender,
                     public TransportSequenceNumberAllocator,
                     public RemoteBitrateObserver,
                     public TransportFeedbackSenderInterface {};
// src/modules/pacing/packet_router.cc
bool PacketRouter::TimeToSendPacket(uint32_t ssrc,
                                    uint16_t sequence_number,
                                    int64_t capture_timestamp,
                                    bool retransmission,
                                    const PacedPacketInfo& pacing_info) {
  return rtp_module->TimeToSendPacket(ssrc, sequence_number,
                                      capture_timestamp, retransmission,
                                      pacing_info);
}
  • RtpRtcp 作为父类,其定义如下:
// src/modules/rtp_rtcp/include/rtp_rtcp.h
class RtpRtcp : public Module, public RtcpFeedbackSenderInterface {
  virtual bool TimeToSendPacket(uint32_t ssrc,
                                uint16_t sequence_number,
                                int64_t capture_time_ms,
                                bool retransmission,
                                const PacedPacketInfo& pacing_info) = 0;
};
  • ModuleRtpRtcpImpl 继承了 RtpRtcp,并实现其虚函数。此处通知 RTPSender 实现发送。
// src/modules/rtp_rtcp/source/rtp_rtcp_impl.h
class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp {};
// src/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
bool ModuleRtpRtcpImpl::TimeToSendPacket(uint32_t ssrc,
                                         uint16_t sequence_number,
                                         int64_t capture_time_ms,
                                         bool retransmission,
                                         const PacedPacketInfo& pacing_info) {
  return rtp_sender_->TimeToSendPacket(ssrc, sequence_number, capture_time_ms,
                                       retransmission, pacing_info);
}

二、 RTP 发送的总体流程

  • RTPSender 负责发送 RTP 包, 其中的关键步骤:
  1. 从发送缓存取包,包括普通 RTP 包和 FEC 包
  2. 给 RTP 包添加头部扩展
  3. 通知 TransportFeedbackObserver 记录 RTP 包的发送时间
  4. 通知 SendPacketObserver 记录 RTP 发送延迟的 Stats
  5. 通知 Transport 发送 RTP 包
// src/modules/rtp_rtcp/source/rtp_sender.cc
bool RTPSender::TimeToSendPacket(uint32_t ssrc,
                                 uint16_t sequence_number,
                                 bool retransmission,
                                 const PacedPacketInfo& pacing_info) {
  // ...
  // 从发送缓存队列获取要发送的包,若为 FEC 则另从 FEC 缓存队列获取
  // ...
  return PrepareAndSendPacket(
      std::move(packet),
      retransmission && (RtxStatus() & kRtxRetransmitted) > 0, retransmission,
      pacing_info);
}
bool RTPSender::PrepareAndSendPacket(std::unique_ptr packet,
                                     bÂool send_over_rtx,
                                     bool is_retransmit,
                                     const PacedPacketInfo& pacing_info) {
  // ...
  // 给 packet 添加头部扩展(包括序列号)
  // 如果不是重传包则更新发送延迟
  // ...
  AddPacketToTransportFeedback(options.packet_id, *packet_to_send,
                               pacing_info);
  UpdateOnSendPacket(options.packet_id, packet->capture_time_ms(),
                     packet->Ssrc());
  SendPacketToNetwork(*packet_to_send, options, pacing_info);
}
void RTPSender::AddPacketToTransportFeedback(
    uint16_t packet_id,
    const RtpPacketToSend& packet,
    const PacedPacketInfo& pacing_info) {
  transport_feedback_observer_->AddPacket(SSRC(), packet_id, packet_size,
                                          pacing_info);
}
void RTPSender::UpdateOnSendPacket(int packet_id,
                                   int64_t capture_time_ms,
                                   uint32_t ssrc) {
  send_packet_observer_->OnSendPacket(packet_id, capture_time_ms, ssrc);
}
bool RTPSender::SendPacketToNetwork(const RtpPacketToSend& packet,
                                    const PacketOptions& options,
                                    const PacedPacketInfo& pacing_info) {
  // ...
  // 更新 rtp 头部开销
  // ...
  bytes_sent = transport_->SendRtp(packet.data(), packet.size(), options)
                   ? static_cast(packet.size())
                   : -1;
}

三、 记录 RTP 发送时间

  • TransportFeedbackObserver 作为父类,其定义如下:
// src/modules/rtp_rtcp/include/rtp_rtcp_defines.h
class TransportFeedbackObserver {
 public:
  TransportFeedbackObserver() {}
  virtual ~TransportFeedbackObserver() {}
  virtual void AddPacket(uint32_t ssrc,
                         uint16_t sequence_number,
                         size_t length,
                         const PacedPacketInfo& pacing_info) = 0;
  virtual void OnTransportFeedback(const rtcp::TransportFeedback& feedback) = 0;
};
  • 接口 SendSideCongestionControllerInterface 继承了 TransportFeedbackObserver,但没有给出后者两个成员函数的实现。
// src/modules/congestion_controller/include/send_side_congestion_controller_interface.h
class SendSideCongestionControllerInterface : public CallStatsObserver,
                                              public Module,
                                              public TransportFeedbackObserver{};
  • SendSideCongestionController 又继承了接口 SendSideCongestionControllerInterface,并实现了 TransportFeedbackObserver 的两个虚函数。发送 RTP 包时调用的AddPacket由此处响应。
// src/modules/congestion_controller/include/send_side_congestion_controller.h
class SendSideCongestionController
    : public SendSideCongestionControllerInterface {};
// src/modules/congestion_controller/send_side_congestion_controller.cc
void SendSideCongestionController::AddPacket(
    uint32_t ssrc,
    uint16_t sequence_number,
    size_t length,
    const PacedPacketInfo& pacing_info) {
  transport_feedback_adapter_.AddPacket(ssrc, sequence_number, length,
                                        pacing_info);
}
  • TransportFeedbackAdapter 负责维护一个 SendTimeHistory 类型的对象,记录每个 RTP 序列号对应的发送时间。当发送端收到 Transport Feedback 包后,可以根据序列号找到相应发送时间,从而计算 GCC 算法所需的OWDV(one-way delay variation)。此外,TransportFeedbackAdapter 会调用 PacketFeedbackObserver::OnPacketAdded 记录发送了的序列号。
// src/modules/congestion_controller/transport_feedback_adapter.cc
void TransportFeedbackAdapter::AddPacket(uint32_t ssrc,
                                         uint16_t sequence_number,
                                         size_t length,
                                         const PacedPacketInfo& pacing_info) {
  send_time_history_.AddAndRemoveOld(
      PacketFeedback(creation_time_ms, sequence_number, length, local_net_id_,
                     remote_net_id_, pacing_info));
  observer->OnPacketAdded(ssrc, sequence_number);
}

四、 记录 RTP 发送延迟 Stats

  • SendPacketObserver 作为父类,其定义如下:
// src/common_types.h
class SendPacketObserver {
 public:
  virtual ~SendPacketObserver() {}
  virtual void OnSendPacket(uint16_t packet_id,
                            int64_t capture_time_ms,
                            uint32_t ssrc) = 0;
};
  • SendDelayStats 继承了 SendPacketObserver,实现了后者的虚函数。发送 RTP 包时调用的 OnSendPacket 由此响应。 用于记录每个 RTP 序列号对应的 ssrc, capture_time, send_time。
// src/video/send_delay_stats.h
class SendDelayStats : public SendPacketObserver {};
// src/video/send_delay_stats.cc
void SendDelayStats::OnSendPacket(uint16_t packet_id,
                                  int64_t capture_time_ms,
                                  uint32_t ssrc) {};

五、 发送 RTP 包

  • Transport 作为父类,其定义如下:
// src/api/call/transport.h
class Transport {
 public:
  virtual bool SendRtp(const uint8_t* packet,
                       size_t length,
                       const PacketOptions& options) = 0;
  virtual bool SendRtcp(const uint8_t* packet, size_t length) = 0;

 protected:
  virtual ~Transport() {}
};
  • AudioSendStream 和 TransportAdapter 都继承了 Transport类,分别负责音频和视频的 RTP 包发送。
// src/audio/audio_send_stream.cc
class AudioSendStream::TimedTransport : public Transport {};

// src/video/transport_adapter.h
class TransportAdapter : public Transport {};

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