美文网首页计算机网络webrtc rtc/rtcp源码分析
WebRTC RTP/RTCP 源码分析(一):RTP 的发送

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

作者: 酸辣粉多加辣椒 | 来源:发表于2019-03-20 17:19 被阅读66次

    基于 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<RtpPacketToSend> 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<int>(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 的发送

        本文链接:https://www.haomeiwen.com/subject/nwetvqtx.html