webrtc代码走读(十)-QOS-Sender Side BWE原理
1、背景介绍
为什么 Sender Side BWE 是 WebRTC 的核心
BWE(Bandwidth Estimation,带宽估计)是 WebRTC 视频引擎中决定通讯质量的关键模块。其核心作用是:在保证网络不拥塞的前提下,动态计算发送端可承载的最大视频码率,直接避免因码率超出网络承载能力导致的画面卡顿、花屏等问题。
1.1 BWE 算法的演进历程
BWE 算法的发展本质是“从被动响应到主动预测”的升级,具体分为三个阶段:
| 阶段 | 核心逻辑 | 优缺点 | 代表算法 |
|---|---|---|---|
| 早期版本 | 基于丢包的被动评估:逐步增加发送量,直到检测到丢包才降低码率 | 优点:实现简单;缺点:丢包已代表网络拥塞,属于“事后补救”,延迟高 | 基础丢包反馈算法 |
| 中期版本 | 基于延迟的主动预测:通过接收端时延变化预判拥塞,提前调整码率 | 优点:比丢包更灵敏,可避免拥塞发生;缺点:依赖接收端计算,反馈链路长 | KalmanFilter(接收端计算) |
| 最新版本 | 发送端本地化计算:将延迟分析逻辑迁移到发送端,减少反馈开销 | 优点:响应速度更快,减少网络往返延迟;缺点:对发送端算力有轻微要求 | Trendline(发送端计算) |
1.2 GCC vs Sender Side BWE
WebRTC 历史上存在两种主流拥塞控制算法,开发中需明确区分,避免代码混淆:
| 对比维度 | GCC(Google Congest Control) | Sender Side BWE |
|---|---|---|
| 码控计算模块位置 | 接收端 | 发送端 |
| RTP 头部扩展字段 | AbsSendTime(绝对发送时间) | TransportSequenceNumber(传输序列号) |
| 接收端关键对象 | RemoteBitrateEstimatorAbsSendTime | RemoteEstimatorProxy |
| 网络延时滤波器 | Kalman Filter | Trendline Filter |
| 接收端反馈 RTCP 报文 | REMB(Receiver Estimated Maximum Bitrate) | TransportCC(Transport Congestion Control) |
| 适用 WebRTC 版本 | M55 之前 | M55 之后(当前主流版本) |
2 Sender Side BWE 的三大核心逻辑
Sender Side BWE 通过“多维度评估+动态融合”确定最终码率,核心逻辑分为三部分:REMB 兼容逻辑、基于丢包的拥塞控制、基于延迟的拥塞控制,最终取三者最小值作为发送码率(min(base, remb, bwe))。
2.1 REMB Bitrate:向下兼容逻辑
REMB(Receiver Estimated Maximum Bitrate)是 GCC 算法中接收端反馈的“建议最大码率”。在 Sender Side BWE 中,REMB 仅作为向下兼容老版本的备用逻辑,不参与主流计算。
- 作用:当接收端为 M55 之前的老版本时,发送端仍能通过 REMB 报文获取码率建议,避免版本不兼容导致的通讯失败。
- 优先级:最低,仅当基于延迟和丢包的计算结果无效时才使用。
2.2 基于丢包的拥塞控制:通过丢包率直接调整码率
核心思想
丢包率直接反映网络拥塞程度:
- 丢包率极低(<2%):网络空闲,可提升码率;
- 丢包率高(>10%):网络拥塞,需降低码率;
- 丢包率中等(2%~10%):网络处于临界状态,维持当前码率。
关键公式与阈值
WebRTC 中通过以下逻辑计算丢包调整后的码率:
if 丢包率 fL(tk) < 0.02(2%):码率 = 当前码率 × 1.08 + 1000bps(8%增长+保底1kbps,避免低码率时停滞)
elif 丢包率 fL(tk) > 0.1(10%):码率 = 当前码率 × (512 - 丢包率×256) / 512(约等于码率 × (1 - 0.5×丢包率))
else:码率保持不变
- 阈值说明:
low_loss_threshold_ = 0.02f(2%)、high_loss_threshold_ = 0.1f(10%),为 WebRTC 内置默认值,开发中可通过BitrateController接口修改。
2.3 基于延迟的拥塞控制:预测拥塞的核心逻辑
基于延迟的拥塞控制是 Sender Side BWE 的核心,通过分析“包组到达时间的延迟趋势”预判网络状态,分为四个关键步骤:包组延迟评估(InterArrival)→ 滤波器趋势判断(TrendlineEstimator)→ 过载检测(OveruseDetector)→ 码率调节(AimdRateControl)。
2.3.1 步骤1:包组延迟评估(InterArrival)—— 为什么要按“组”计算延迟?
- 问题本质:视频帧可能被拆分为多个 RTP 包(如 1 帧 1080P 视频可能拆分为 10 个 RTP 包),若单个包计算延迟,会因“同一帧内包的发送间隔极短”导致延迟计算失真。
- 解决方案:按“帧”分组(即“包组”),计算两组包的延迟差,核心参数如下:
| 参数 | 定义 | 计算公式 | 示例 |
|---|---|---|---|
| delta_timestamp | 两组包的发送时间差 | T2(第二组最后一个包的发送时间) - T1(第一组最后一个包的发送时间) | 若两组包分属不同帧,发送间隔为 40ms(25fps 帧率),则 delta_timestamp = 40ms |
| delta_arrival | 两组包的到达时间差 | t2(第二组最后一个包的到达时间) - t1(第一组最后一个包的到达时间) | 若网络延迟稳定,delta_arrival ≈ delta_timestamp;若网络拥塞,delta_arrival > delta_timestamp |
| delta_size | 两组包的大小差 | 第二组包的总字节数 - 第一组包的总字节数 | 若第一组 10KB,第二组 12KB,则 delta_size = 2KB |
步骤2:Trendline 滤波趋势判断—— 如何量化延迟趋势?
Trendline 滤波器的核心是:通过“累积延迟”和“平滑延迟”计算延迟增长斜率,斜率越大,说明网络拥塞越严重。
关键计算步骤(附公式与注释)
-
单个包组的延迟增长值:
delay_i = delta_arrival - delta_timestamp- 含义:若
delay_i > 0,说明当前组的到达延迟比上一组高,网络开始堆积数据;若delay_i < 0,说明网络延迟降低。
- 含义:若
-
累积延迟:
acc_delay_i = acc_delay_{i-1} + delay_i- 含义:叠加历史延迟增长值,反映延迟的长期趋势。
-
平滑延迟(避免瞬时波动影响):
smo_delay_i = alpha × smo_delay_{i-1} + (1 - alpha) × acc_delay_i- 参数:
alpha = 0.9(WebRTC 内置,平衡平滑度与响应速度); - 作用:过滤瞬时延迟抖动,避免因单个包的网络波动误判拥塞。
- 参数:
-
趋势斜率计算:
- 分子(numerator):
sum( (trans_k - trans_avg) × (smo_delay_k - smo_delay_avg) )trans_k:第 k 组包的传输持续时间(从组内第一个包到达至最后一个包到达的时间);trans_avg:所有组trans_k的平均值;smo_delay_avg:所有组smo_delay_k的平均值。
- 分母(denominator):
sum( (trans_k - trans_avg)^2 ) - 最终趋势值:
trendline_i = numerator / denominator- 含义:
trendline_i > 0表示延迟呈上升趋势(网络拥塞);trendline_i < 0表示延迟呈下降趋势(网络空闲)。
- 含义:
- 分子(numerator):
步骤3:过载检测(OveruseDetector)—— 如何判断网络状态?
通过 Trendline 计算的 trendline_i,结合动态阈值 gamma_1,判断网络处于“过载(overuse)”“正常(normal)”还是“未充分利用(underuse)”,核心是一个有限状态机。
状态机迁移逻辑(伪代码)
// 输入:当前包组的趋势值 trendline_i,周期内包组个数 N
m_i = trendline_i × N // 周期内总趋势值,放大趋势差异if m_i > gamma_1(动态阈值,由网络抖动自适应调整):// 延迟增长过快,网络过载current_state = overuse// 过载时,需记录过载持续时间,避免瞬时波动误判overuse_time += delta_Tif overuse_time > overuse_threshold:// 过载持续超过阈值,触发码率下降trigger_rate_decrease()
elif m_i < -gamma_1:// 延迟下降,网络未充分利用current_state = underusetrigger_rate_increase() // 触发码率上升
else:// 延迟稳定,网络正常current_state = normalmaintain_current_rate() // 维持当前码率
步骤4:AIMD 码率调节(AimdRateControl)—— 如何调整码率?
AIMD(Additive Increase Multiplicative Decrease,和式增加,积式减少)是 TCP 拥塞控制的经典思想,WebRTC 对其进行了适配,核心逻辑根据网络状态动态调整码率。
关键调节规则(附公式)
| 网络状态 | 调节策略 | 公式/说明 | 示例 |
|---|---|---|---|
| 未充分利用(underuse) | 分阶段增长: 1. 会话初期(慢启动):倍数增长 2. 稳定期:线性增长 | 1. 慢启动:new_bitrate = current_bitrate × 1.08(8%倍数增长)2. 稳定期: new_bitrate = current_bitrate + (RTT 周期内可传输码率) | 若当前码率 1Mbps,慢启动后变为 1.08Mbps;稳定期若 RTT 为 100ms,可增加 1Mbps × 0.1 = 100kbps |
| 过载(overuse) | 乘法下降:基于过去 500ms 内的最大确认码率 | new_bitrate = max_acked_bitrate_500ms × 0.85(降低 15%) | 若过去 500ms 最大确认码率为 1Mbps,下降后为 850kbps |
| 正常(normal) | 维持当前码率 | new_bitrate = current_bitrate | - |
3、WebRTC 源码实现解析
以下基于 WebRTC M100+ 版本源码,梳理 Sender Side BWE 的核心函数调用链。
src/modules/congestion_controller/send_side_congestion_controller.ccsrc/modules/bitrate_controller/send_side_bandwidth_estimation.ccsrc/modules/congestion_controller/delay_based_bwe/delay_based_bwe.cc
3.1 核心函数调用链总览
Sender Side BWE 的触发入口是“接收端 RTCP 反馈报文的处理”,整体调用链如下:
// 1. 接收 RTCP 报文(TransportCC 或 RR)
BaseChannel::ProcessPacket → WebRtcVideoChannel::OnRtcpReceived → Call::DeliverRtcp → VideoSendStreamImpl::DeliverRtcp
// 2. 解析 RTCP 报文,触发拥塞控制回调
→ ModuleRtpRtcpImpl::IncomingRtcpPacket → RTCPReceiver::IncomingPacket → RTCPReceiver::TriggerCallbacksFromRtcpPacket
// 3. 分支1:基于延迟的拥塞控制(核心)
→ SendSideCongestionController::OnTransportFeedback → DelayBasedBwe::IncomingPacketFeedbackVector → BitrateControllerImpl::OnDelayBasedBweResult
// 3. 分支2:基于丢包的拥塞控制
→ BitrateControllerImpl::RtcpBandwidthObserverImpl::OnReceivedRtcpReceiverReport → BitrateControllerImpl::OnReceivedRtcpReceiverReport
// 4. 融合所有评估结果,确定最终码率
→ SendSideBandwidthEstimation::UpdateEstimate → SendSideBandwidthEstimation::CapBitrateToThresholds
// 5. 将码率更新到发送端各模块( pacing、FEC、编码器)
→ SendSideCongestionController::MaybeTriggerOnNetworkChanged
3.2 关键函数源码
基于延迟的拥塞控制:DelayBasedBwe::IncomingPacketFeedbackVector
/*** @brief 接收端反馈的包组到达信息,更新延迟统计并计算 BWE 值* @param packet_feedbacks:接收端反馈的包组列表(包含每个包的发送时间、到达时间、序列号)* @param now_ms:当前时间(毫秒)* @return void* @note 该函数是基于延迟拥塞控制的入口,负责将反馈信息传递给 InterArrival 和 TrendlineEstimator*/
void DelayBasedBwe::IncomingPacketFeedbackVector(const std::vector<PacketFeedback>& packet_feedbacks,int64_t now_ms) {// 遍历每个包的反馈信息,按包组分组(同一帧的包为一组)for (const auto& feedback : packet_feedbacks) {// 1. 检查包是否属于新的包组(通过序列号判断,同一帧的包序列号连续)if (!inter_arrival_->IsPacketInOrder(feedback.sequence_number)) {// 包乱序,跳过(乱序会导致延迟计算失真)continue;}// 2. 计算当前包组的延迟参数(delta_timestamp、delta_arrival、delta_size)std::optional<InterArrival::Result> result = inter_arrival_->ComputeDeltas(feedback.send_time_ms, // 包的发送时间feedback.arrival_time_ms, // 包的到达时间feedback.payload_size, // 包的 payload 大小feedback.sequence_number, // 包的序列号now_ms);// 3. 若成功计算出包组延迟参数,更新 Trendline 滤波器if (result) {// 调用 TrendlineEstimator 计算延迟趋势trendline_estimator_->Update(result->delta_send_time_ms, // delta_timestampresult->delta_arrival_time_ms, // delta_arrivalresult->delta_payload_size, // delta_sizenow_ms);// 4. 调用 OveruseDetector 判断网络是否过载OveruseDetector::State overuse_state = overuse_detector_->Detect(trendline_estimator_->trendline_slope(), // 延迟趋势斜率result->delta_arrival_time_ms,now_ms);// 5. 根据过载状态,通过 AIMD 调节码率aimd_rate_control_->Update(overuse_state, // 网络过载状态trendline_estimator_->time_since_last_update_ms(),now_ms);}}// 6. 将计算出的 BWE 值(基于延迟)传递给 BitrateControllerint64_t target_bitrate_bps = aimd_rate_control_->GetTargetBitrate();OnDelayBasedBweResult(target_bitrate_bps, now_ms);
}
基于丢包的拥塞控制:SendSideBandwidthEstimation::UpdateEstimate
/*** @brief 基于丢包率更新码率估计,是丢包拥塞控制的核心逻辑* @param now_ms:当前时间(毫秒)* @return void* @note 该函数结合丢包率、历史码率、反馈超时等因素,计算丢包调整后的码率*/
void SendSideBandwidthEstimation::UpdateEstimate(int64_t now_ms) {uint32_t new_bitrate = current_bitrate_bps_; // 初始化为当前码率// 1. 会话启动初期(前 2 秒)且无丢包:优先使用基于延迟的 BWE 值(快速启动)if (last_fraction_loss_ == 0 && IsInStartPhase(now_ms)) {// 取“基于延迟的 BWE”和“当前码率”的最大值(快速提升码率)new_bitrate = std::max(bwe_incoming_, new_bitrate);new_bitrate = std::max(delay_based_bitrate_bps_, new_bitrate);if (new_bitrate != current_bitrate_bps_) {min_bitrate_history_.clear(); // 清空历史最小码率(启动期无需参考历史)min_bitrate_history_.push_back(std::make_pair(now_ms, current_bitrate_bps_));CapBitrateToThresholds(now_ms, new_bitrate); // 限制码率在 [min, max] 范围内return;}}// 2. 更新历史最小码率(用于后续码率增长计算)UpdateMinHistory(now_ms);// 3. 无任何反馈(如接收端离线):维持当前码率if (last_packet_report_ms_ == -1) {CapBitrateToThresholds(now_ms, current_bitrate_bps_);return;}// 4. 检查反馈是否超时(反馈间隔是否过长)int64_t time_since_packet_report_ms = now_ms - last_packet_report_ms_;int64_t time_since_feedback_ms = now_ms - last_feedback_ms_;// 5. 反馈未超时:基于丢包率调整码率if (time_since_packet_report_ms < 1.2 * kFeedbackIntervalMs) {// 转换丢包率(RTCP RR 报文中的丢包率是 0~255 的整数,需转为 0~1 的浮点数)float loss = last_fraction_loss_ / 256.0f;// 仅当码率高于阈值时,才基于丢包率调整(过滤非拥塞导致的丢包,如网络抖动)if (current_bitrate_bps_ < bitrate_threshold_bps_ || loss <= low_loss_threshold_) {// 情况1:丢包率 < 2% 或码率过低:码率增长 8% + 1kbps(避免低码率停滞)new_bitrate = static_cast<uint32_t>(min_bitrate_history_.front().second * 1.08 + 0.5); // 8% 增长,四舍五入new_bitrate += 1000; // 额外加 1kbps,低码率场景(如 10kbps)效果明显} else if (current_bitrate_bps_ > bitrate_threshold_bps_) {if (loss <= high_loss_threshold_) {// 情况2:丢包率 2%~10%:维持当前码率new_bitrate = current_bitrate_bps_;} else {// 情况3:丢包率 >10%:降低码率(每 kBweDecreaseIntervalMs + RTT 周期仅降一次)if (!has_decreased_since_last_fraction_loss_ &&(now_ms - time_last_decrease_ms_) >= (kBweDecreaseIntervalMs + last_round_trip_time_ms_)) {time_last_decrease_ms_ = now_ms; // 记录上次降低时间,避免频繁降码率// 码率降低公式:newRate = 当前码率 × (512 - 丢包率×256) / 512 ≈ 当前码率 × (1 - 0.5×丢包率)new_bitrate = static_cast<uint32_t>((current_bitrate_bps_ * static_cast<double>(512 - last_fraction_loss_)) / 512.0);has_decreased_since_last_fraction_loss_ = true; // 标记已降低,避免重复操作}}}} // 6. 反馈超时(接收端长时间未反馈):降低码率(应对网络断连风险)else if (time_since_feedback_ms > kFeedbackTimeoutIntervals * kFeedbackIntervalMs &&(last_timeout_ms_ == -1 || now_ms - last_timeout_ms_ > kTimeoutIntervalMs)) {if (in_timeout_experiment_) {LOG(LS_WARNING) << "Feedback timed out (" << time_since_feedback_ms << " ms), reducing bitrate.";new_bitrate *= 0.8; // 超时后码率降低 20%// 重置丢包统计(避免超时后重复处理旧丢包)lost_packets_since_last_loss_update_Q8_ = 0;expected_packets_since_last_loss_update_ = 0;last_timeout_ms_ = now_ms; // 记录上次超时时间}}// 7. 限制码率在 [min_bitrate_configured_, max_bitrate_configured_] 范围内CapBitrateToThresholds(now_ms, new_bitrate);
}
*融合所有评估结果:SendSideBandwidthEstimation::CapBitrateToThresholds
/*** @brief 融合“基于延迟的 BWE”“基于丢包的 BWE”“REMB”,并限制码率在配置范围内* @param now_ms:当前时间(毫秒)* @param bitrate_bps:待调整的码率(输入值)* @return void* @note 该函数是 Sender Side BWE 的“最终决策层”,输出最终发送码率*/
void SendSideBandwidthEstimation::CapBitrateToThresholds(int64_t now_ms,uint32_t bitrate_bps) {// 1. 若 REMB 有效(兼容老版本),码率不能超过 REMB 值if (bwe_incoming_ > 0 && bitrate_bps > bwe_incoming_) {bitrate_bps = bwe_incoming_;}// 2. 若基于延迟的 BWE 有效,码率不能超过延迟 BWE 值(核心限制)if (delay_based_bitrate_bps_ > 0 && bitrate_bps > delay_based_bitrate_bps_) {bitrate_bps = delay_based_bitrate_bps_;}// 3. 码率不能超过配置的最大码率(开发者可通过 API 设置,如 setMaxBitrate)if (bitrate_bps > max_bitrate_configured_) {bitrate_bps = max_bitrate_configured_;}// 4. 码率不能低于配置的最小码率(避免画面质量过低)if (bitrate_bps < min_bitrate_configured_) {// 每隔 kLowBitrateLogPeriodMs 打印一次警告日志(避免日志刷屏)if (last_low_bitrate_log_ms_ == -1 ||now_ms - last_low_bitrate_log_ms_ > kLowBitrateLogPeriodMs) {LOG(LS_WARNING) << "Estimated available bandwidth " << bitrate_bps / 1000<< " kbps is below configured min bitrate "<< min_bitrate_configured_ / 1000 << " kbps.";last_low_bitrate_log_ms_ = now_ms;}bitrate_bps = min_bitrate_configured_;}// 5. 若码率变化或丢包率变化,记录 RTC 事件日志(用于调试)if (bitrate_bps != current_bitrate_bps_ ||last_fraction_loss_ != last_logged_fraction_loss_ ||now_ms - last_rtc_event_log_ms_ > kRtcEventLogPeriodMs) {event_log_->LogLossBasedBweUpdate(bitrate_bps, last_fraction_loss_,expected_packets_since_last_loss_update_);last_logged_fraction_loss_ = last_fraction_loss_;last_rtc_event_log_ms_ = now_ms;}// 6. 更新当前码率(最终结果)current_bitrate_bps_ = bitrate_bps;
}
码率更新到发送端模块:SendSideCongestionController::MaybeTriggerOnNetworkChanged
/*** @brief 将最终码率更新到发送端各核心模块( pacing、FEC、编码器)* @return void* @note 该函数是 Sender Side BWE 的“执行层”,确保码率调整生效*/
void SendSideCongestionController::MaybeTriggerOnNetworkChanged() {uint32_t bitrate_bps; // 最终码率(bps)uint8_t fraction_loss; // 丢包率(0~255)int64_t rtt; // 网络往返延迟(ms)// 1. 从 BitrateController 获取最新的网络参数(码率、丢包率、RTT)bool estimate_changed = bitrate_controller_->GetNetworkParameters(&bitrate_bps, &fraction_loss, &rtt);// 2. 若码率变化,更新 Pacer(发送 pacing 模块,控制发送速率避免突发)if (estimate_changed) {pacer_->SetEstimatedBitrate(bitrate_bps); // 调整 pacing 速率probe_controller_->SetEstimatedBitrate(bitrate_bps); // 调整带宽探测速率retransmission_rate_limiter_->SetMaxRate(bitrate_bps); // 调整重传速率上限}// 3. 处理网络断连或发送队列满的情况:码率设为 0(暂停发送)bitrate_bps = IsNetworkDown() || IsSendQueueFull() ? 0 : bitrate_bps;// 4. 若网络参数(码率、丢包率、RTT)变化,通知观察者(如编码器、FEC 模块)if (HasNetworkParametersToReportChanged(bitrate_bps, fraction_loss, rtt)) {int64_t probing_interval_ms;{rtc::CritScope cs(&bwe_lock_); // 加锁,线程安全// 获取 BWE 周期(用于后续带宽探测)probing_interval_ms = delay_based_bwe_->GetExpectedBwePeriodMs();}{rtc::CritScope cs(&observer_lock_); // 加锁,线程安全if (observer_) {// 通知观察者:网络参数变化,需调整编码码率、FEC 冗余度等observer_->OnNetworkChanged(bitrate_bps, fraction_loss, rtt,probing_interval_ms);// 示例:观察者可能是 VideoEncoder,此时会调用 SetRates(bitrate_bps) 调整编码码率}}}
}
4、开发应用实践:如何基于 Sender Side BWE 优化 WebRTC 应用
4.1 关键配置参数调整(提升通讯质量)
在实际开发中,可通过 WebRTC 的 API 调整以下参数,优化 Sender Side BWE 效果:
| 参数 | 作用 | 推荐配置 | API 示例(C++) |
|---|---|---|---|
| 最小码率(min_bitrate) | 避免码率过低导致画面模糊 | 视频通话:300kbps(480P);直播:1Mbps(720P) | webrtc::VideoSendStream::Config config; config.min_bitrate_bps = 300000; |
| 最大码率(max_bitrate) | 避免码率过高导致拥塞 | 基于网络环境:WiFi 设为 8Mbps(1080P);4G 设为 4Mbps | config.max_bitrate_bps = 8000000; |
| BWE 启动期(start_phase_duration) | 会话初期快速提升码率的时间 | 默认 2000ms(2秒),可根据需求调整为 3000ms | send_side_bwe_.SetStartPhaseDurationMs(3000); |
| 丢包率阈值(low_loss_threshold/high_loss_threshold) | 调整丢包触发码率变化的敏感度 | 弱网环境可降低 high_loss_threshold 至 0.08(8%) | send_side_bwe_.SetLossThresholds(0.02f, 0.08f); |
4.2 常见问题与解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 会话初期画面卡顿 | BWE 启动期码率提升过慢 | 1. 延长启动期(SetStartPhaseDurationMs(3000));2. 增大启动期码率增长倍数(需修改 AIMD 源码) |
| 弱网环境下码率频繁波动 | 延迟抖动导致 OveruseDetector 误判 | 1. 增大 Trendline 滤波器的 alpha 值(如 0.95);2. 提高过载检测的阈值 gamma_1 |
| 码率始终低于配置的最小码率 | 网络拥塞严重,BWE 计算结果过低 | 1. 检查是否配置了正确的最小码率;2. 优化视频编码参数(如降低分辨率、提高压缩率) |
4.3 调试工具与日志分析
开发中可通过以下工具分析 Sender Side BWE 的运行状态:
- RTC 事件日志:通过
event_log_->LogLossBasedBweUpdate记录码率、丢包率变化,可使用 WebRTC 提供的rtc_event_log_analyzer工具可视化分析; - Wireshark 抓包:过滤 TransportCC(RTCP 类型 205)或 REMB(RTCP 类型 206)报文,查看接收端反馈的延迟和丢包信息;
- WebRTC 内置 metrics:通过
webrtc::Metrics模块获取bwe_delay_based_bitrate、bwe_loss_based_bitrate等指标,实时监控 BWE 计算结果。
