webrtc弱网-PccNetworkController类源码分析与算法原理
PccNetworkController是WebRTC中基于PCC算法的拥塞控制核心组件,通过在线凸优化实现智能带宽估计。它采用多模式控制策略(启动、慢启动、在线学习、双重检查),在监控间隔内测试对称速率变化,基于效用函数梯度上升优化发送速率。通过动态评估吞吐量、延迟和丢包率的综合性能,自适应调整传输策略,在保证网络稳定性的同时最大化传输效率,显著提升实时音视频通信的质量和鲁棒性。
一. 核心功能
PCC (Performance-oriented Congestion Control) 是一种基于在线凸优化的拥塞控制算法,主要功能包括:
-
多模式速率控制:启动模式、慢启动模式、在线学习模式和双重检查模式
-
监控间隔管理:通过监控间隔测试不同发送速率对网络性能的影响
-
效用函数优化:基于吞吐量、延迟和丢包率计算效用函数,通过梯度上升最大化性能
-
自适应参数调整:根据网络状况动态调整监控间隔时长和超时参数
二. 核心算法原理
2.1 效用函数数学模型
PCC的核心是基于效用函数的优化:
Utility = w1 * throughput^α - w2 * loss_rate - w3 * delay_gradient
在代码中的具体实现:
// 效用函数参数定义 constexpr double kRttGradientCoefficientBps = 0.005; // 延迟梯度权重 w3 constexpr double kLossCoefficientBps = 10; // 丢包率权重 w2 constexpr double kThroughputCoefficient = 0.001; // 吞吐量权重 w1 constexpr double kThroughputPower = 0.9; // 吞吐量指数 α
2.2 梯度上升更新公式
// 速率更新规则:r_{t+1} = r_t + η * ∇Utility(r_t)
// 在代码中的实现:
void PccNetworkController::UpdateSendingRateAndMode() {if (mode_ == Mode::kSlowStart) {// 慢启动:指数增长bandwidth_estimate_ = bandwidth_estimate_ * kSlowStartModeIncrease;} else {// 在线学习:基于效用函数梯度更新bandwidth_estimate_ = bitrate_controller_.ComputeRateUpdateForOnlineLearningMode(monitor_intervals_, bandwidth_estimate_);}
}
2.3 监控间隔测试策略
// 测试两个对称的速率:r(1+ε) 和 r(1-ε)
monitor_intervals_bitrates_ = {bandwidth_estimate_ * (1 + sign * sampling_step_),bandwidth_estimate_ * (1 - sign * sampling_step_)};
三. 关键数据结构
3.1 PccNetworkController 核心成员
class PccNetworkController {private:Mode mode_; // 当前控制模式DataRate bandwidth_estimate_; // 当前带宽估计值RttTracker rtt_tracker_; // RTT跟踪器PccBitrateController bitrate_controller_; // 比特率控制器std::vector<PccMonitorInterval> monitor_intervals_; // 监控间隔队列std::vector<DataRate> monitor_intervals_bitrates_; // 待测试的比特率std::deque<PacketResult> last_received_packets_; // 最近接收包信息
};
3.2 控制模式枚举
enum class Mode {kStartup, // 启动阶段:快速探测可用带宽kSlowStart, // 慢启动:保守增加速率kOnlineLearning, // 在线学习:基于效用函数优化kDoubleCheck // 双重检查:验证测量结果可靠性
};
四. 核心方法详解
4.1 发送包处理 - OnSentPacket
NetworkControlUpdate PccNetworkController::OnSentPacket(SentPacket msg) {// 1. 初始化阶段检查if (start_time_.IsInfinite()) {start_time_ = msg.send_time;// 创建第一个监控间隔monitor_intervals_.emplace_back(bandwidth_estimate_, msg.send_time,monitor_intervals_duration_);}// 2. 更新平滑发送间隔(指数加权移动平均)smoothed_packets_sending_interval_ = (msg.send_time - last_sent_packet_time_) * kAlphaForPacketInterval +(1 - kAlphaForPacketInterval) * smoothed_packets_sending_interval_;// 3. 超时检测和处理if (IsTimeoutExpired(msg.send_time)) {// 超时时将带宽估计减半bandwidth_estimate_ = std::min<DataRate>(bandwidth_estimate_ * 0.5, receiving_rate);}// 4. 启动阶段持续时间检查if (mode_ == Mode::kStartup && msg.send_time - start_time_ >= kStartupDuration) {// 切换到慢启动模式mode_ = Mode::kSlowStart;monitor_intervals_duration_ = ComputeMonitorIntervalsDuration();}// 5. 创建新的监控间隔if (IsFeedbackCollectionDone() || IsTimeoutExpired(msg.send_time)) {if (mode_ == Mode::kSlowStart) {// 慢启动:测试增长后的速率monitor_intervals_bitrates_ = {kSlowStartModeIncrease * bandwidth_estimate_};} else {// 在线学习:测试对称的速率变化monitor_intervals_bitrates_ = {bandwidth_estimate_ * (1 + sign * sampling_step_),bandwidth_estimate_ * (1 - sign * sampling_step_)};}}return CreateRateUpdate(msg.send_time);
}
4.2 反馈包处理 - OnTransportPacketsFeedback
NetworkControlUpdate PccNetworkController::OnTransportPacketsFeedback(TransportPacketsFeedback msg) {// 1. 保存接收包信息用于后续分析for (const PacketResult& packet_result : msg.ReceivedWithSendInfo()) {last_received_packets_.push_back(packet_result);}// 2. 更新RTT估计rtt_tracker_.OnPacketsFeedback(msg.PacketsWithFeedback(), msg.feedback_time);// 3. 更新监控间隔的统计信息if (!IsFeedbackCollectionDone() && !monitor_intervals_.empty()) {for (size_t i = complete_feedback_monitor_interval_number_;i < monitor_intervals_.size(); ++i) {monitor_intervals_[i].OnPacketsFeedback(msg.PacketsWithFeedback());if (monitor_intervals_[i].IsFeedbackCollectionDone()) {complete_feedback_monitor_interval_number_++;}}}// 4. 检查是否需要双重检查if (IsFeedbackCollectionDone()) {if (mode_ == Mode::kDoubleCheck) {mode_ = Mode::kOnlineLearning;} else if (NeedDoubleCheckMeasurments()) {mode_ = Mode::kDoubleCheck;}// 5. 更新发送速率if (mode_ != Mode::kDoubleCheck)UpdateSendingRateAndMode();}return NetworkControlUpdate();
}
4.3 监控间隔时长计算
TimeDelta PccNetworkController::ComputeMonitorIntervalsDuration() const {TimeDelta monitor_intervals_duration = TimeDelta::Zero();if (monitor_interval_length_strategy_ == MonitorIntervalLengthStrategy::kAdaptive) {// 自适应策略:基于RTT和包发送间隔monitor_intervals_duration = std::max(rtt_tracker_.GetRtt() * monitor_interval_duration_ratio_,smoothed_packets_sending_interval_ * min_packets_number_per_interval_);} else {// 固定策略:基于包数量monitor_intervals_duration = smoothed_packets_sending_interval_ * min_packets_number_per_interval_;}// 确保不小于最小持续时间return std::max(kMinDurationOfMonitorInterval, monitor_intervals_duration);
}
五. 设计亮点
5.1 多模式自适应控制
-
启动模式:快速探测网络容量
-
慢启动:保守增长避免拥塞
-
在线学习:基于效用函数优化
-
双重检查:提高测量可靠性
5.2 对称测试设计
通过测试对称的速率变化 r(1±ε),可以准确估计效用函数的梯度方向。
5.3 自适应监控间隔
根据网络状况动态调整监控间隔时长,平衡测量准确性和响应速度。
5.4 鲁棒性设计
-
超时检测和处理机制
-
双重检查避免错误决策
-
平滑参数更新减少振荡
六. 典型工作流程
6.1 流程图

6.2 时序图

6.3 关键流程说明
启动阶段流程:
-
初始化带宽估计和监控间隔
-
在固定时长内收集网络统计信息
-
基于接收速率初始化带宽估计
-
切换到慢启动模式
在线学习阶段流程:
-
设置两个对称的测试速率
-
在每个监控间隔内以相应速率发送数据
-
收集吞吐量、延迟、丢包率统计
-
计算效用函数并估计梯度
-
沿梯度方向更新发送速率
双重检查流程:
-
检测到速率与丢包率变化方向矛盾
-
进入双重检查模式重新测试
-
验证测量结果的可靠性
-
返回在线学习模式继续优化
这种设计使得PCC能够在不同网络条件下自适应调整,通过在线学习找到最优的发送速率,同时在面对不确定的测量结果时保持鲁棒性。
