1 基本原理
WebRTC的拥塞控制模块使用的是基于TCP的拥塞控制算法。它是根据网络带宽和延迟等信息来自适应地调整传输速率的。
具体来说,该模块采用的是基于RFC 3550中的延迟抖动调整算法的改进版本。该算法实施的基本原理是在传输的过程中定期探测网络的质量和延迟,并根据这些信息来自适应地调整传输速率。
具体步骤如下:
- 定期测量网络的延迟和带宽,以便了解当前的网络情况。
- 根据当前网络的情况来计算最大可用传输速率。
- 根据当前的带宽和延迟情况来动态调整传输速率。
- 如果网络质量出现问题,将立即降低传输速率。
- 检测网络质量的变化并及时调整传输速率。
- 保持一个平衡的传输速率,以最大限度地利用可用带宽。
总之,WebRTC的拥塞控制模块采用了先进的自适应算法,可以在不影响通信质量的情况下尽可能地提高传输速率。这使得WebRTC成为一种非常强大和实用的实时通信技术。以下分析基于【WebRTC source stamp 2022-03-04T04:05:35】版本。新版本相较之前的版本最大的改进是基于接收端的带宽估计,不需要发送端参与带宽的估计计算,从而不需要依赖于发送的的带宽估计。
2 整体架构
拥塞控制模块位于modules中的congestion_controller模块。
include目录:实现了拥塞控制模块对外API。
goog_cc目录: 实现了 Google Congestion Control 的主要功能,提供了丰富的接口和数据类型,帮助开发者轻松实现高效的拥塞控制算法,以提供高质量的实时视频和音频通信服务。Google Congestion Control 是一种开放源代码的拥塞控制算法实现,目的是在不稳定或高延迟的网络环境中,提高视频和音频的传输质量。
pcc目录:实现了 PCC(Probe Congestion Control)拥塞控制算法,是一个基于探针的拥塞控制算法。PCC 算法不需要精准地估算网络带宽,而是通过发送一组探针包来探测网络的状况,进而调整传输速率,从而实现拥塞控制。
rtp目录:实现了 RTP(Real-time Transport Protocol)拥塞控制算法。RTP 是一种用于实时传输音频和视频的协议,可以对数据进行分组和时间戳等处理。RTP 拥塞控制算法实现了在不同网络拥塞情况下的数据传输控制。
3 对外API解读
对外API封装在ReceiveSideCongestionController类中,顾名思义这一个基于接收端的拥塞控制算法。ReceiveSideCongestionController 类的构造函数,用于创建一个接收端拥塞控制器对象,以保证数据传输的稳定性和可靠性。该类对象需要提供时钟、传输反馈信息发送函数、REMB 消息发送函数和网络状态估计器等信息,用于进行拥塞控制和比特率调整等操作。
class ReceiveSideCongestionController : public CallStatsObserver {
public:
// 构造函数
/*
构造函数的参数如下:
clock:一个指向 Clock 类对象的指针,用于获取当前时间戳。
feedback_sender:一个函数对象,用于发送传输反馈信息。
remb_sender:一个函数对象,用于发送 REMB (Receiver Estimated Maximum Bitrate) 消息。
network_state_estimator:一个指向 NetworkStateEstimator 对象的指针,用于估计网络的状态(如带宽,丢包率等)。
*/
ReceiveSideCongestionController(
Clock* clock,
RemoteEstimatorProxy::TransportFeedbackSender feedback_sender,
RembThrottler::RembSender remb_sender,
NetworkStateEstimator* network_state_estimator);
Clock* clock, // 时钟
RemoteEstimatorProxy::TransportFeedbackSender feedback_sender, // 远程估计代理
RembThrottler::RembSender remb_sender, // REMB发送器
NetworkStateEstimator* network_state_estimator); // 网络状态估计器
~ReceiveSideCongestionController() override {}
// 接收到数据包时的回调函数
void OnReceivedPacket(const RtpPacketReceived& packet, MediaType media_type);
// TODO(perkj, bugs.webrtc.org/14859): Remove all usage. This method is
// currently not used by PeerConnections.
virtual void OnReceivedPacket(int64_t arrival_time_ms,
size_t payload_size,
const RTPHeader& header);
// Implements CallStatsObserver.
// 实现CallStatsObserver接口,当RTT更新时调用
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
// This is send bitrate, used to control the rate of feedback messages.
// 这是发送比特率,用于控制反馈消息的速率。
void OnBitrateChanged(int bitrate_bps);
// Ensures the remote party is notified of the receive bitrate no larger than
// `bitrate` using RTCP REMB.
// 确保使用RTCP REMB通知远程方接收比特率不大于`bitrate`。
void SetMaxDesiredReceiveBitrate(DataRate bitrate);
// 设置传输开销
void SetTransportOverhead(DataSize overhead_per_packet);
// Returns latest receive side bandwidth estimation.
// Returns zero if receive side bandwidth estimation is unavailable.
// 返回最新的接收端带宽估计。
// 如果接收端带宽估计不可用,则返回零。
DataRate LatestReceiveSideEstimate() const;
// Removes stream from receive side bandwidth estimation.
// Noop if receive side bwe is not used or stream doesn't participate in it.
// 从接收端带宽估计中删除流。
// 如果不使用接收端bwe或流不参与其中,则不执行任何操作。
void RemoveStream(uint32_t ssrc);
// Runs periodic tasks if it is time to run them, returns time until next
// call to `MaybeProcess` should be non idle.
// 如果到了运行它们的时间,则运行定期任务,返回到下一个
// 调用`MaybeProcess`应该是非空闲的时间。
TimeDelta MaybeProcess();
private:
// 从头部选择估计器
void PickEstimatorFromHeader(const RTPHeader& header)
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// 选择估计器
void PickEstimator() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Clock& clock_; // 时钟
RembThrottler remb_throttler_; // REMB发送器
RemoteEstimatorProxy remote_estimator_proxy_; // 远程估计代理
mutable Mutex mutex_; // 互斥锁
std::unique_ptr<RemoteBitrateEstimator> rbe_ RTC_GUARDED_BY(mutex_); // 远程比特率估计器
bool using_absolute_send_time_ RTC_GUARDED_BY(mutex_); // 是否使用绝对发送时间
uint32_t packets_since_absolute_send_time_ RTC_GUARDED_BY(mutex_); // 自绝对发送时间以来的数据包数
};