一、核心功能
IntervalBudget
?類用于基于時間窗口的帶寬預算管理。它根據設定的目標比特率(kbps)和一個固定時間窗口(500ms),計算在該時間窗口內可用的字節數(即“預算”),并支持預算的增加(隨時間累積)和使用(發送數據時消耗)。該類可用于擁塞控制、碼率調整等場景中,確保數據發送速率不超過目標速率。
二、核心算法原理
-
預算計算:
預算基于目標比特率和時間窗口(500ms)計算:
max_bytes_in_budget_ = (kWindowMs * target_rate_kbps_) / 8
即:最大預算 = (500ms × 目標速率kbps) / 8(轉換為字節) -
預算累積(IncreaseBudget):
根據時間差?delta_time_ms
?計算應增加的預算字節數。-
若允許積累未使用預算(
can_build_up_underuse_
為true),則將剩余預算累加,但不超過最大值; -
否則,每個時間窗口的預算獨立,不累積。
-
-
預算消耗(UseBudget):
每發送一定字節數,就從剩余預算中扣除,但不能低于?-max_bytes_in_budget_
(允許一定程度超支)。
三、關鍵數據結構
成員變量 | 類型 | 說明 |
---|---|---|
target_rate_kbps_ | int | 目標比特率,單位kbps |
max_bytes_in_budget_ | int64_t | 時間窗口內的最大預算字節數 |
bytes_remaining_ | int64_t | 當前剩余預算字節數,可為負(表示超支) |
can_build_up_underuse_ | bool | 是否允許未使用的預算累積到下一個周期 |
四、核心方法詳解
1. 構造函數
IntervalBudget(int initial_target_rate_kbps, bool can_build_up_underuse): bytes_remaining_(0), can_build_up_underuse_(can_build_up_underuse) {set_target_rate_kbps(initial_target_rate_kbps); }
2.?set_target_rate_kbps
void IntervalBudget::set_target_rate_kbps(int target_rate_kbps) {target_rate_kbps_ = target_rate_kbps;max_bytes_in_budget_ = (kWindowMs * target_rate_kbps_) / 8;bytes_remaining_ = std::min(std::max(-max_bytes_in_budget_, bytes_remaining_),max_bytes_in_budget_); }
功能:設置目標比特率,并重新計算最大預算,同時限制當前剩余預算在合理范圍內。
3.?IncreaseBudget
void IntervalBudget::IncreaseBudget(int64_t delta_time_ms) {int64_t bytes = target_rate_kbps_ * delta_time_ms / 8;if (bytes_remaining_ < 0 || can_build_up_underuse_) {bytes_remaining_ = std::min(bytes_remaining_ + bytes, max_bytes_in_budget_);} else {bytes_remaining_ = std::min(bytes, max_bytes_in_budget_);} }
功能:根據時間差增加預算。若允許累積或之前超支,則累加;否則重置為本周期預算。
4.?UseBudget
void IntervalBudget::UseBudget(size_t bytes) {bytes_remaining_ = std::max(bytes_remaining_ - static_cast<int>(bytes),-max_bytes_in_budget_); }
功能:使用預算,扣除相應字節數,防止超支過多。
5.?bytes_remaining
size_t IntervalBudget::bytes_remaining() const {return rtc::saturated_cast<size_t>(std::max<int64_t>(0, bytes_remaining_)); }
功能:返回非負的剩余預算(超支時返回0)。
6.?budget_ratio
double IntervalBudget::budget_ratio() const {if (max_bytes_in_budget_ == 0)return 0.0;return static_cast<double>(bytes_remaining_) / max_bytes_in_budget_; }
功能:返回當前預算比率(剩余預算 / 最大預算),用于判斷當前負載情況。
五、設計亮點
-
支持兩種預算模式:
-
可累積模式(
can_build_up_underuse_ = true
):允許未使用的預算累積到下一周期; -
非累積模式:每個周期預算獨立,不累積。
-
-
防溢出與飽和處理:
-
使用?
std::min
?/?std::max
?限制預算范圍; -
bytes_remaining()
?返回非負值,避免負數引起誤解。
-
-
靈活的預算調整:
-
支持動態調整目標碼率,自動重新計算最大預算;
-
支持負預算(超支),但限制在一定范圍內。
-
六、典型工作流程
-
初始化?
IntervalBudget
,設置初始目標碼率和是否允許累積; -
每隔一段時間調用?
IncreaseBudget(delta_time_ms)
?增加預算; -
發送數據時調用?
UseBudget(bytes)
?扣除預算; -
通過?
bytes_remaining()
?或?budget_ratio()
?查詢當前預算狀態; -
可根據網絡狀態動態調用?
set_target_rate_kbps()
?調整目標碼率。
注釋精要
interval_budget.h
// 帶寬預算管理器,基于時間窗口(500ms)和目標碼率進行預算控制 class IntervalBudget {public:explicit IntervalBudget(int initial_target_rate_kbps);IntervalBudget(int initial_target_rate_kbps, bool can_build_up_underuse);void set_target_rate_kbps(int target_rate_kbps); // 設置目標碼率(kbps)void IncreaseBudget(int64_t delta_time_ms); // 增加預算,delta_time_ms 為時間差(毫秒)void UseBudget(size_t bytes); // 使用預算,bytes 為使用的字節數size_t bytes_remaining() const; // 獲取當前剩余預算(非負)double budget_ratio() const; // 獲取預算比率(剩余預算/最大預算)int target_rate_kbps() const; // 獲取當前目標碼率private:int target_rate_kbps_; // 目標碼率(kbps)int64_t max_bytes_in_budget_; // 最大預算字節數(500ms窗口)int64_t bytes_remaining_; // 當前剩余預算字節數(可為負)bool can_build_up_underuse_; // 是否允許未使用的預算累積 };
interval_budget.cc
void IntervalBudget::IncreaseBudget(int64_t delta_time_ms) {int64_t bytes = target_rate_kbps_ * delta_time_ms / 8; // 計算應增加的字節數if (bytes_remaining_ < 0 || can_build_up_underuse_) {// 若當前超支或允許累積,則累加預算(不超過最大值)bytes_remaining_ = std::min(bytes_remaining_ + bytes, max_bytes_in_budget_);} else {// 否則,本周期的預算不超過當前時間窗口內的最大值bytes_remaining_ = std::min(bytes, max_bytes_in_budget_);} }
IntervalBudget類在WebRTC中負責基于時間窗口的帶寬預算管理,用于控制數據發送速率不超過設定的目標比特率。它通過500ms時間窗口將目標碼率轉換為字節預算,隨時間推移累積預算,發送數據時扣除相應字節數。該類支持兩種模式:可累積未使用預算或每周期獨立預算,為擁塞控制和碼率自適應算法提供關鍵的發送速率狀態信息,確保網絡流量平穩且避免擁塞,是pacing模塊和擁塞控制系統的重要組成部分。