ProbeController是WebRTC中负责智能带宽探测的核心组件,其主要作用是通过主动发送探测数据包来评估网络容量和可用带宽。它在连接建立初期进行指数级探测快速估算初始带宽,在传输过程中根据网络状态变化(如带宽分配调整、ALR状态、带宽估计下降等)触发动态探测。通过周期性和条件性探测机制,ProbeController能够实时适应网络变化,在带宽大幅跌落时快速发起恢复探测,确保WebRTC能够优化传输性能,维持音视频通话的质量和稳定性。
一、核心功能
ProbeController
是 WebRTC 中用于控制带宽探测的核心组件,主要功能包括:
-
初始探测:在连接建立初期发起指数级增长的探测,以快速估算可用带宽。
-
动态探测:根据网络状态变化(如最大分配带宽变化、ALR 状态、带宽估计下降等)触发探测。
-
周期性与条件性探测:支持在 ALR(Application Limited Region)状态下周期性地发起探测,或根据网络状态估计发起探测。
-
带宽跌落恢复:在带宽大幅下降时发起探测以快速恢复。
二、核心算法原理
1. 指数探测(Exponential Probing)
在初始阶段,使用指数增长的方式发送探测包:
-
第一个探测:
p1 * start_bitrate
-
第二个探测:
p2 * start_bitrate
(如果配置了second_exponential_probe_scale
)
2. 进一步探测(Further Probing)
若当前带宽估计超过上一次探测结果的 further_probe_threshold
,则发起新一轮探测:
further_exponential_probe_scale * current_estimate
3. ALR 探测(ALR Probing)
在 ALR 状态下周期性地发起探测,探测比特率为:
alr_probe_scale * estimated_bitrate
4. 网络状态估计探测(Network State Estimate Probing)
若当前带宽估计低于网络状态估计的某个比例,则发起探测:
network_state_probe_scale * network_estimate
5. 带宽跌落恢复探测(Drop Recovery Probing)
若带宽下降超过一定比例(如 33%),则在恢复时发起探测:
kProbeFractionAfterDrop * bitrate_before_drop
三、关键数据结构
1. ProbeControllerConfig
包含所有可配置的探测参数,通过字段试验(Field Trials)动态调整。
2. ProbeClusterConfig
表示一个探测集群的配置,包括:
-
target_data_rate
:目标探测比特率 -
target_duration
:探测持续时间 -
target_probe_count
:探测包数量 -
id
:唯一标识
3. State
表示探测控制器的状态:
-
kInit
:初始状态,等待首次探测 -
kWaitingForProbingResult
:等待探测结果 -
kProbingComplete
:探测完成
4. BandwidthLimitedCause
表示带宽受限的原因,影响是否发起探测。
四、核心方法详解
1. SetBitrates()
设置最小、起始和最大比特率,触发初始指数探测。
2. OnMaxTotalAllocatedBitrate()
处理最大分配比特率变化,触发分配探测(若允许)。
3. SetEstimatedBitrate()
更新当前带宽估计,决定是否发起进一步探测。
4. RequestProbe()
在带宽大幅下降后请求探测以恢复。
5. Process()
处理周期性探测(ALR 或网络状态估计触发)。
6. InitiateProbing()
实际发起探测,生成 ProbeClusterConfig
列表。
五、设计亮点
-
灵活可配置:所有探测参数可通过字段试验动态调整,适应不同网络环境。
-
多条件触发:支持初始探测、动态分配变化、ALR 状态、网络状态估计、带宽跌落等多种触发条件。
-
状态机管理:使用状态机清晰管理探测生命周期。
-
事件日志:通过
RtcEventLog
记录探测事件,便于调试和分析。 -
带宽受限处理:根据带宽受限原因智能决定是否发起探测。
六、典型工作流程
-
初始化:调用
SetBitrates()
设置初始比特率,触发指数探测。 -
等待结果:进入
kWaitingForProbingResult
状态,等待探测结果。 -
结果处理:根据探测结果决定是否继续探测或完成。
-
动态响应:在运行过程中响应带宽变化、ALR 状态、分配变化等事件,触发新的探测。
-
周期探测:在 ALR 或网络状态估计条件下周期性地发起探测。
-
跌落恢复:在带宽大幅下降后发起恢复探测。
注释精要
// 设置比特率,触发初始探测 std::vector<ProbeClusterConfig> ProbeController::SetBitrates( DataRate min_bitrate, DataRate start_bitrate, DataRate max_bitrate, Timestamp at_time) { if (start_bitrate > DataRate::Zero()) { start_bitrate_ = start_bitrate; estimated_bitrate_ = start_bitrate; } else if (start_bitrate_.IsZero()) { start_bitrate_ = min_bitrate; } DataRate old_max_bitrate = max_bitrate_; max_bitrate_ = max_bitrate.IsFinite() ? max_bitrate : kDefaultMaxProbingBitrate; switch (state_) { case State::kInit: if (network_available_) return InitiateExponentialProbing(at_time); // 初始指数探测 break; case State::kWaitingForProbingResult: break; case State::kProbingComplete: // 若新最大比特率高于旧值和当前估计,触发探测 if (!estimated_bitrate_.IsZero() && old_max_bitrate < max_bitrate_ && estimated_bitrate_ < max_bitrate_) { return InitiateProbing(at_time, {max_bitrate_}, false); } break; } return std::vector<ProbeClusterConfig>(); }
// 发起实际探测 std::vector<ProbeClusterConfig> ProbeController::InitiateProbing( Timestamp now, std::vector<DataRate> bitrates_to_probe, bool probe_further) { // 若当前估计超过最大比特率的一定比例,跳过探测 if (config_.skip_if_estimate_larger_than_fraction_of_max > 0) { // ... 判断逻辑 } // 计算最大探测比特率,考虑分配比特率 DataRate max_probe_bitrate = max_bitrate_; if (max_total_allocated_bitrate_ > DataRate::Zero()) { max_probe_bitrate = std::min(max_probe_bitrate, max_total_allocated_bitrate_ * 2); } // 根据带宽受限原因调整探测上限 DataRate estimate_capped_bitrate = DataRate::PlusInfinity(); switch (bandwidth_limited_cause_) { case BandwidthLimitedCause::kLossLimitedBweIncreasing: estimate_capped_bitrate = std::min(max_probe_bitrate, estimated_bitrate_ * config_.loss_limited_probe_scale); break; // ... 其他情况 } // 生成探测配置 std::vector<ProbeClusterConfig> pending_probes; for (DataRate bitrate : bitrates_to_probe) { // ... 配置每个探测集群 ProbeClusterConfig config; config.at_time = now; config.target_data_rate = bitrate; config.target_duration = config_.min_probe_duration; config.target_probe_count = config_.min_probe_packets_sent; config.id = next_probe_cluster_id_++; MaybeLogProbeClusterCreated(event_log_, config); // 记录事件 pending_probes.push_back(config); } // 更新状态和下一次探测的最小比特率阈值 time_last_probing_initiated_ = now; if (probe_further) { state_ = State::kWaitingForProbingResult; min_bitrate_to_probe_further_ = ...; } else { state_ = State::kProbingComplete; min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); } return pending_probes; }
总结
ProbeController
是 WebRTC 中负责智能带宽探测的核心模块,通过多种触发条件和灵活的参数配置,实现在不同网络环境下高效、自适应的带宽探测与恢复。其设计充分考虑了实时通信中的网络动态变化,是保障音视频传输质量的重要组成部分。