WebRTC編碼過載檢測與幀率適應機制分析報告
WebRTC編碼過載檢測與幀率適應機制分析報告
1. 概述
本報告基于WebRTC源碼分析,詳細闡述了編碼過載檢測機制及其觸發的幀率降級算法。分析范圍涵蓋從編碼時間測量到最終幀率調整的完整調用鏈。
2. 編碼使用率計算機制
2.1 基本計算公式
位置: android/cmake/src/video/adaptation/overuse_frame_detector.cc:163-164
float encode_usage_percent =
100.0f * filtered_processing_ms_->filtered() / frame_diff_ms;
2.2 編碼時間測量
編碼時長計算 (overuse_frame_detector.cc:143-144):
encode_duration_us = timing.last_send_us - timing.capture_us;
timing.capture_us: 幀捕獲時間戳timing.last_send_us: 幀發送完成時間戳- 測量范圍: 從幀捕獲到編碼完成發送的總時間
2.3 濾波處理
指數濾波算法 (rtc_base/numerics/exp_filter.cc:24):
y(k) = alpha^exp × y(k-1) + (1 - alpha^exp) × sample
數據處理流程 (overuse_frame_detector.cc:148):
AddSample(1e-3 * (*encode_duration_us), 1e-3 * diff_us);
// 微秒轉毫秒: 1e-3 = 0.001
3. 過載檢測閾值與判斷邏輯
3.1 默認閾值設置
軟件編碼器 (overuse_frame_detector.h:34):
int high_encode_usage_threshold_percent = 85; // 85%
硬件編碼器 (video_stream_encoder_resource_manager.cc:684-685):
options.low_encode_usage_threshold_percent = 150; // 150%
options.high_encode_usage_threshold_percent = 200; // 200%
3.2 過載判斷條件
單次檢查 (overuse_frame_detector.cc:653-657):
if (usage_percent >= options_.high_encode_usage_threshold_percent) {
++checks_above_threshold_;
} else {
checks_above_threshold_ = 0;
}
連續檢查 (overuse_frame_detector.cc:658):
return checks_above_threshold_ >= options_.high_threshold_consecutive_count;
// high_threshold_consecutive_count = 2 (默認值)
最小樣本要求 (overuse_frame_detector.cc:586-587):
if (num_process_times_ <= options_.min_process_count || // min_process_count = 3
!encode_usage_percent_)
return; // 不觸發適應
4. 過載觸發的調用鏈
4.1 檢測到過載后的調用序列
// 1. 過載檢測 (overuse_frame_detector.cc:616)
observer->AdaptDown();
// 2. 資源適應 (encode_usage_resource.cc:93-95)
void EncodeUsageResource::AdaptDown() {
OnResourceUsageStateMeasured(ResourceUsageState::kOveruse);
}
// 3. 資源處理 (resource_adaptation_processor.cc:201)
case ResourceUsageState::kOveruse:
result_and_message = OnResourceOveruse(resource);
// 4. 獲取適應方案 (resource_adaptation_processor.cc:287)
Adaptation adaptation = stream_adapter_->GetAdaptationDown();
// 5. 應用適應 (resource_adaptation_processor.cc:305)
stream_adapter_->ApplyAdaptation(adaptation, reason_resource);
4.2 適應方案選擇
降級偏好判斷 (video_stream_adapter.cc:454-475):
switch (degradation_preference_) {
case DegradationPreference::BALANCED: {
// 先嘗試降幀率,再降分辨率
RestrictionsOrState decrease_frame_rate =
DecreaseFramerate(input_state, current_restrictions);
if (成功) return decrease_frame_rate;
// 否則降分辨率
[[fallthrough]];
}
case DegradationPreference::MAINTAIN_FRAMERATE: {
// 只降分辨率
return DecreaseResolution(input_state, current_restrictions);
}
case DegradationPreference::MAINTAIN_RESOLUTION: {
// 只降幀率
return DecreaseFramerate(input_state, current_restrictions);
}
}
5. 幀率降級算法
5.1 核心降級公式
位置: video_stream_adapter.cc:37-40
int GetLowerFrameRateThan(int fps) {
RTC_DCHECK(fps != std::numeric_limits<int>::max());
return (fps * 2) / 3; // 關鍵公式:降到原來的2/3
}
5.2 幀率降級實現
MAINTAIN_RESOLUTION模式 (video_stream_adapter.cc:507):
if (degradation_preference_ == DegradationPreference::MAINTAIN_RESOLUTION) {
max_frame_rate = GetLowerFrameRateThan(input_state.frames_per_second());
}
BALANCED模式 (video_stream_adapter.cc:511-512):
else if (degradation_preference_ == DegradationPreference::BALANCED) {
max_frame_rate = balanced_settings_.MinFps(input_state.video_codec_type(),
frame_size_pixels);
}
5.3 最小幀率限制
最小值設定 (video_stream_adapter.cc:32):
const int kMinFrameRateFps = 2;
限制應用 (video_stream_adapter.cc:522):
max_frame_rate = std::max(kMinFrameRateFps, max_frame_rate);
6. 實際降級序列計算
6.1 MAINTAIN_RESOLUTION模式幀率序列
基于公式 new_fps = current_fps × 2/3:
| 當前幀率 | 計算過程 | 降級后幀率 | 降幅 |
|---|---|---|---|
| 30fps | 30 × 2/3 = 20 | 20fps | 33.3% |
| 20fps | 20 × 2/3 = 13.33 | 13fps | 35% |
| 13fps | 13 × 2/3 = 8.66 | 8fps | 38.5% |
| 8fps | 8 × 2/3 = 5.33 | 5fps | 37.5% |
| 5fps | 5 × 2/3 = 3.33 | 3fps | 40% |
| 3fps | 3 × 2/3 = 2 | 2fps | 33.3% |
| 2fps | 2 × 2/3 = 1.33 | 2fps | 0% (最小值) |
6.2 BALANCED模式幀率配置
默認配置 (balanced_degradation_settings.cc:25-55):
std::vector<Config> DefaultConfigs() {
return {
{320 * 240, 7, ...}, // 76,800像素 → 7fps最小值
{480 * 360, 10, ...}, // 172,800像素 → 10fps最小值
{640 * 480, 15, ...} // 307,200像素 → 15fps最小值
};
}
7. 編碼使用率實例分析
7.1 30fps正常情況
理論幀間隔:1000ms / 30fps = 33.33ms
實際編碼時間:25ms
編碼使用率 = 100 × 25ms / 33.33ms = 75%
結果:75% < 85% → 正常運行
7.2 30fps過載情況
理論幀間隔:33.33ms
實際編碼時間:30ms
編碼使用率 = 100 × 30ms / 33.33ms = 90%
結果:90% > 85% → 觸發降幀率(連續2次檢測后)
7.3 硬件編碼器容忍度
理論幀間隔:33.33ms
實際編碼時間:60ms(包含流水線延遲)
編碼使用率 = 100 × 60ms / 33.33ms = 180%
結果:180% < 200% → 正常運行(硬件編碼器閾值)
8. 關鍵常量定義
| 常量名 | 數值 | 位置 | 說明 |
|---|---|---|---|
high_encode_usage_threshold_percent |
85% | overuse_frame_detector.h:34 |
軟件編碼器過載閾值 |
high_encode_usage_threshold_percent |
200% | video_stream_encoder_resource_manager.cc:685 |
硬件編碼器過載閾值 |
high_threshold_consecutive_count |
2 | overuse_frame_detector.h:53 |
連續過載檢測次數 |
min_process_count |
3 | overuse_frame_detector.h:50 |
最小處理次數要求 |
min_frame_samples |
120 | overuse_frame_detector.h:46 |
最小幀樣本數 |
kMinFrameRateFps |
2 | video_stream_adapter.cc:32 |
最小幀率限制 |
9. 總結
WebRTC的編碼過載檢測與幀率適應機制基于以下核心原理:
- 時間測量: 精確測量從幀捕獲到發送完成的總時間
- 使用率計算: 編碼時間占幀間隔時間的百分比
- 過載判斷: 連續2次檢測到使用率≥85%(軟件)或≥200%(硬件)
- 幀率降級: 按2/3比例遞減,最低至2fps
- 模式適應: 根據降級偏好選擇降幀率或降分辨率
該機制確保在CPU資源緊張時,通過及時的幀率調整維持視頻編碼的實時性和穩定性。

浙公網安備 33010602011771號