基于 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);
}
// 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);
}
// 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 包, 其中的关键步骤:
- 从发送缓存取包,包括普通 RTP 包和 FEC 包
- 给 RTP 包添加头部扩展
- 通知 TransportFeedbackObserver 记录 RTP 包的发送时间
- 通知 SendPacketObserver 记录 RTP 发送延迟的 Stats
- 通知 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 包
// 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 {};