webrtc弱网-QualityScaler 源码分析与算法原理
一. 核心功能
QualityScaler 是 WebRTC 中用于动态调整视频编码质量的模块,主要功能包括:
QP 监控:持续监测编码器输出的量化参数(QP)
丢帧率分析:跟踪媒体优化和编码器导致的丢帧情况
自适应决策:根据 QP 和丢帧率触发分辨率/帧率调整
异步任务调度:通过延迟任务实现周期性质量检测
平滑处理:使用指数平滑算法减少 QP 波动影响
二. 核心算法原理
双阈值决策机制:
当 QP > 高阈值时:触发降级(降低分辨率/帧率)
当 QP ≤ 低阈值时:触发升级(提高分辨率/帧率)
丢帧率保护:当总丢帧率 ≥ 60% 时强制降级
指数平滑滤波:
class QpSmoother {rtc::ExpFilter smoother_; // 指数平滑滤波器void Add(float sample) { smoother_.Apply(time_delta, sample); } }
动态采样周期调整:
初始快速检测(快速启动阶段)
根据历史结果动态调整检测间隔
公式:
delay = sampling_period_ms_ * scale_factor_
三. 关键数据结构
// QP 阈值结构体 struct QpThresholds {int low; // 低阈值(升级边界)int high; // 高阈值(降级边界) };// 质量检测结果 enum class CheckQpResult {kInsufficientSamples, // 样本不足kNormalQp, // QP正常kHighQp, // QP过高(需降级)kLowQp // QP过低(需升级) };// 平滑滤波器 class QpSmoother {rtc::ExpFilter smoother_; // 指数平滑实现int64_t last_sample_ms_; // 最后采样时间 };
四. 核心方法详解
质量检测入口:
void StartNextCheckQpTask() {pending_qp_task_ = std::make_unique<CheckQpTask>(this);pending_qp_task_->StartDelayedTask(); // 启动延迟检测任务 }
QP检测逻辑:
CheckQpResult CheckQp() const {// 1. 检查样本数量是否足够(默认至少60帧)if (frames < min_frames_needed_) return kInsufficientSamples;// 2. 检查丢帧率是否超标(≥60%)if (drop_rate >= kFramedropPercentThreshold) return kHighQp;// 3. 检查QP是否超过阈值if (*avg_qp_high > thresholds_.high) return kHighQp;if (*avg_qp_low <= thresholds_.low) return kLowQp;return kNormalQp; }
平滑处理实现:
void QpSmoother::Add(float sample, int64_t time_sent_us) {int64_t now_ms = time_sent_us / 1000;// 应用指数平滑:新值 = α*当前值 + (1-α)*历史值smoother_.Apply(now_ms - last_sample_ms_, sample);last_sample_ms_ = now_ms; }
五. 设计亮点
动态任务调度:
使用
CheckQpTask
实现自循环检测根据历史结果动态调整检测频率
快速启动模式(fast_rampup_)加速初始检测
双通道平滑滤波:
qp_smoother_high_.reset(new QpSmoother(config_.alpha_high)); // 高阈值通道 qp_smoother_low_.reset(new QpSmoother(config_.alpha_low)); // 低阈值通道
使用不同的平滑系数分别处理高低阈值
字段试验支持:
QualityScalerSettings settings(field_trials); // 从字段试验获取参数 sampling_period_ms_ = settings.SamplingPeriodMs().value_or(kMeasureMs);
允许通过字段试验动态配置算法参数
丢帧分类统计:
void ReportDroppedFrameByMediaOpt(); // 媒体优化导致的丢帧 void ReportDroppedFrameByEncoder(); // 编码器导致的丢帧
六. 典型工作流程
注释精要
关键参数:
// 默认检测周期(ms) static const int kMeasureMs = 2000; // 丢帧率阈值(%) static const int kFramedropPercentThreshold = 60;// 最小决策帧数(2秒数据) static const size_t kMinFramesNeededToScale = 2 * 30;
核心类说明:
// QP平滑处理器:使用指数平滑算法消除瞬时波动 class QpSmoother {// α值决定平滑强度:α越大,新值权重越高explicit QpSmoother(float alpha); };// 异步检测任务:实现周期性的质量评估 class CheckQpTask {void StartDelayedTask(); // 启动延迟检测 };
自适应触发逻辑:
void QualityScaler::CheckQp() {// 优先检查丢帧率:超过60%立即降级if (*drop_rate >= 60) return kHighQp; // 双通道平滑QP检测if (high_smoothed_qp > high_thresh) return kHighQp;if (low_smoothed_qp <= low_thresh) return kLowQp; }
该模块通过智能的QP分析和动态的任务调度,实现了视频质量的自适应调整,在带宽波动环境下保持视频流畅性和清晰度的平衡。