一、核心功能
-
CPU负载检测:监控视频帧的捕获、编码、发送全流程耗时,实时计算CPU使用率
-
自适应决策:基于CPU使用率阈值触发视频质量调整(降级/升级)
-
多策略支持:提供新旧两套CPU负载估计算法,支持实验性参数配置
-
指标上报:通过CpuOveruseMetricsObserver接口反馈性能数据
二、核心算法原理
-
负载估算算法:
-
旧算法(SendProcessingUsage1):
// 基于指数滤波的帧处理时间/帧间隔时间比率 usage_percent = 100 * filtered_processing_ms / filtered_frame_diff_ms
-
新算法(SendProcessingUsage2):
// 基于时间常数的指数平滑:load <-- x/d * (1-exp(-d/T)) + exp(-d/T)*load double tau = options_.filter_time_ms * 0.001; double e = diff_time / tau; double c = (e < 0.0001) ? (1-e/2)/tau : -expm1(-e)/diff_time; load_estimate_ = c * encode_time + exp(-e) * load_estimate_;
-
-
过载决策逻辑:
// 过载条件:连续高阈值检测 bool OveruseFrameDetector::IsOverusing(int usage_percent) { return (usage_percent >= options_.high_threshold) && (++checks_above_threshold_ >= options_.high_threshold_consecutive_count); } // 低载条件:低于阈值 + 冷却时间 bool IsUnderusing(int usage_percent, int64_t time_now) { return (usage_percent < options_.low_threshold) && (time_now > last_rampup_time_ms_ + current_rampup_delay_ms_); }
三、关键数据结构
struct CpuOveruseOptions { // 核心配置参数
int high_encode_usage_threshold_percent = 85; // 过载阈值(85%)
int low_encode_usage_threshold_percent = 42; // 低载阈值(高阈值的1/2)
int frame_timeout_interval_ms = 1500; // 帧超时判定时间
int min_frame_samples = 120; // 最小采样帧数
};
struct FrameTiming { // 帧时序追踪(旧算法)
int64_t capture_time_us; // 原始捕获时间
uint32_t timestamp; // 帧时间戳
int64_t capture_us; // 首次进入系统时间
int64_t last_send_us; // 发送完成时间
};
// 状态机标识(测试注入器)
enum class State { kNormal, kOveruse, kUnderuse };
四、核心方法详解
-
帧生命周期管理:
void FrameCaptured(bool is_preprocess, uint32_t timestamp, const VideoFrame& frame, int64_t time_when_first_seen_us) { // 重置条件:分辨率变化(1280x720->640x480)或帧超时(>1500ms) if (FrameSizeChanged(...) || FrameTimeoutDetected(...)) ResetAll(...); // 记录帧进入系统的时间点 usage_->FrameCaptured(..., time_when_first_seen_us, last_capture_time_us_); last_capture_time_us_ = time_when_first_seen_us; } void FrameSent(..., absl::optional<int> encode_duration_us) { // 计算实际编码耗时(支持外部传入或内部计算) duration_us = usage_->FrameSent(..., capture_time_us, encode_duration_us); // 上报编码耗时指标 if (duration_us) EncodedFrameTimeMeasured(*duration_us / 1000); }
-
动态调整机制:
void CheckForOveruse(OveruseFrameDetectorObserverInterface* observer) { // 过载处理:指数退避延迟算法 if (IsOverusing(*usage_percent_)) { current_rampup_delay_ms_ *= kRampUpBackoffFactor; // 延迟翻倍(最大240s) observer->AdaptDown(); // 触发降级决策 } // 低载处理:快速恢复机制 else if (IsUnderusing(*usage_percent_, now_ms)) { in_quick_rampup_ = true; observer->AdaptUp(); // 触发升级决策 } }
五、设计亮点
-
双算法热切换:
// 根据filter_time_ms配置自动选择算法 std::unique_ptr<ProcessingUsage> CreateProcessingUsage(...) { return (options.filter_time_ms > 0) ? std::make_unique<SendProcessingUsage2>(options) : std::make_unique<SendProcessingUsage1>(options); }
-
测试注入器模式:
// 通过字段试验模拟过载场景(WebRTC-ForceSimulatedOveruseIntervalMs) OverdoseInjector::Value() { switch(state_) { case State::kOveruse: return 250; // 强制返回250%使用率 case State::kUnderuse: return 5; // 强制返回5%使用率 default: return usage_->Value(); } }
-
抗抖动设计:
-
帧间隔时间上限约束:
max_sample_diff_ms_ = (1000/fps)*1.35
-
最小采样帧数限制:
min_frame_samples=120
-
连续阈值检测机制:
high_threshold_consecutive_count=2
-
六、典型工作流程

注释精要
// 帧捕获处理(核心逻辑)
void OveruseFrameDetector::FrameCaptured(...) {
// 重置条件检查:分辨率变化或帧超时
if (FrameSizeChanged(frame.width() * frame.height()) ||
FrameTimeoutDetected(time_when_first_seen_us)) {
ResetAll(frame.width() * frame.height()); // 重置统计状态
}
// 区分预处理器/编码器场景
if(is_preprocess) {
frame_timing_.push_back(FrameTiming(frame.timestamp_us(), timestamp, ...));
} else {
frame_timing_.push_back(FrameTiming(frame.timestamp_us(), frame.timestamp(), ...));
}
}
// 过载检测算法(策略核心)
void OveruseFrameDetector::CheckForOveruse(...) {
// 过载处理:指数退避延迟
if (IsOverusing(*usage_percent_)) {
if (now_ms - last_rampup_time_ms_ < kStandardRampUpDelayMs) {
current_rampup_delay_ms_ *= kRampUpBackoffFactor; // 延迟翻倍
if (current_rampup_delay_ms_ > kMaxRampUpDelayMs) // 上限240s
current_rampup_delay_ms_ = kMaxRampUpDelayMs;
}
observer->AdaptDown(); // 触发降级
}
// 低载处理:快速恢复
else if (IsUnderusing(*usage_percent_, now_ms)) {
last_rampup_time_ms_ = now_ms;
in_quick_rampup_ = true; // 启用快速恢复模式
observer->AdaptUp(); // 触发升级
}
}
该设计通过多算法支持、动态阈值调整和状态机管理,实现了高效的CPU负载感知和视频质量自适应控制,在WebRTC中为实时视频通信提供了关键QoS保障能力。