Clean up RateControlInput struct, used by bandwidth estimation.
Remove unused member noise_var from RateControlInput struct. Rename incoming_bitrate to estimated_throughput_bps to reflect that the AimdRateControl may be running on either the send side or the receive side. Bug: webrtc:9411 Change-Id: Ie1ae0c29dc9559ef389993144e69fcd41684f1a4 Reviewed-on: https://webrtc-review.googlesource.com/83728 Reviewed-by: Stefan Holmer <stefan@webrtc.org> Reviewed-by: Anastasia Koloskova <koloskova@webrtc.org> Commit-Queue: Björn Terelius <terelius@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23783}
This commit is contained in:
committed by
Commit Bot
parent
5eb6045ce5
commit
43d0b98fe5
@ -58,13 +58,13 @@ AimdRateControl::AimdRateControl()
|
||||
: min_configured_bitrate_bps_(congestion_controller::GetMinBitrateBps()),
|
||||
max_configured_bitrate_bps_(30000000),
|
||||
current_bitrate_bps_(max_configured_bitrate_bps_),
|
||||
latest_incoming_bitrate_bps_(current_bitrate_bps_),
|
||||
latest_estimated_throughput_bps_(current_bitrate_bps_),
|
||||
avg_max_bitrate_kbps_(-1.0f),
|
||||
var_max_bitrate_kbps_(0.4f),
|
||||
rate_control_state_(kRcHold),
|
||||
rate_control_region_(kRcMaxUnknown),
|
||||
time_last_bitrate_change_(-1),
|
||||
time_first_incoming_estimate_(-1),
|
||||
time_first_throughput_estimate_(-1),
|
||||
bitrate_is_initialized_(false),
|
||||
beta_(webrtc::field_trial::IsEnabled(kBweBackOffFactorExperiment)
|
||||
? ReadBackoffFactor()
|
||||
@ -80,7 +80,7 @@ AimdRateControl::~AimdRateControl() {}
|
||||
|
||||
void AimdRateControl::SetStartBitrate(int start_bitrate_bps) {
|
||||
current_bitrate_bps_ = start_bitrate_bps;
|
||||
latest_incoming_bitrate_bps_ = current_bitrate_bps_;
|
||||
latest_estimated_throughput_bps_ = current_bitrate_bps_;
|
||||
bitrate_is_initialized_ = true;
|
||||
}
|
||||
|
||||
@ -104,8 +104,9 @@ int64_t AimdRateControl::GetFeedbackInterval() const {
|
||||
kMaxFeedbackIntervalMs);
|
||||
}
|
||||
|
||||
bool AimdRateControl::TimeToReduceFurther(int64_t time_now,
|
||||
uint32_t incoming_bitrate_bps) const {
|
||||
bool AimdRateControl::TimeToReduceFurther(
|
||||
int64_t time_now,
|
||||
uint32_t estimated_throughput_bps) const {
|
||||
const int64_t bitrate_reduction_interval =
|
||||
std::max<int64_t>(std::min<int64_t>(rtt_, 200), 10);
|
||||
if (time_now - time_last_bitrate_change_ >= bitrate_reduction_interval) {
|
||||
@ -115,7 +116,7 @@ bool AimdRateControl::TimeToReduceFurther(int64_t time_now,
|
||||
// TODO(terelius/holmer): Investigate consequences of increasing
|
||||
// the threshold to 0.95 * LatestEstimate().
|
||||
const uint32_t threshold = static_cast<uint32_t>(0.5 * LatestEstimate());
|
||||
return incoming_bitrate_bps < threshold;
|
||||
return estimated_throughput_bps < threshold;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -138,12 +139,13 @@ uint32_t AimdRateControl::Update(const RateControlInput* input,
|
||||
if (!bitrate_is_initialized_) {
|
||||
const int64_t kInitializationTimeMs = 5000;
|
||||
RTC_DCHECK_LE(kBitrateWindowMs, kInitializationTimeMs);
|
||||
if (time_first_incoming_estimate_ < 0) {
|
||||
if (input->incoming_bitrate)
|
||||
time_first_incoming_estimate_ = now_ms;
|
||||
} else if (now_ms - time_first_incoming_estimate_ > kInitializationTimeMs &&
|
||||
input->incoming_bitrate) {
|
||||
current_bitrate_bps_ = *input->incoming_bitrate;
|
||||
if (time_first_throughput_estimate_ < 0) {
|
||||
if (input->estimated_throughput_bps)
|
||||
time_first_throughput_estimate_ = now_ms;
|
||||
} else if (now_ms - time_first_throughput_estimate_ >
|
||||
kInitializationTimeMs &&
|
||||
input->estimated_throughput_bps) {
|
||||
current_bitrate_bps_ = *input->estimated_throughput_bps;
|
||||
bitrate_is_initialized_ = true;
|
||||
}
|
||||
}
|
||||
@ -189,10 +191,10 @@ int AimdRateControl::GetExpectedBandwidthPeriodMs() const {
|
||||
uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps,
|
||||
const RateControlInput& input,
|
||||
int64_t now_ms) {
|
||||
uint32_t incoming_bitrate_bps =
|
||||
input.incoming_bitrate.value_or(latest_incoming_bitrate_bps_);
|
||||
if (input.incoming_bitrate)
|
||||
latest_incoming_bitrate_bps_ = *input.incoming_bitrate;
|
||||
uint32_t estimated_throughput_bps =
|
||||
input.estimated_throughput_bps.value_or(latest_estimated_throughput_bps_);
|
||||
if (input.estimated_throughput_bps)
|
||||
latest_estimated_throughput_bps_ = *input.estimated_throughput_bps;
|
||||
|
||||
// An over-use should always trigger us to reduce the bitrate, even though
|
||||
// we have not yet established our first estimate. By acting on the over-use,
|
||||
@ -203,9 +205,9 @@ uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps,
|
||||
|
||||
ChangeState(input, now_ms);
|
||||
// Calculated here because it's used in multiple places.
|
||||
const float incoming_bitrate_kbps = incoming_bitrate_bps / 1000.0f;
|
||||
const float estimated_throughput_kbps = estimated_throughput_bps / 1000.0f;
|
||||
// Calculate the max bit rate std dev given the normalized
|
||||
// variance and the current incoming bit rate.
|
||||
// variance and the current throughput bitrate.
|
||||
const float std_max_bit_rate =
|
||||
sqrt(var_max_bitrate_kbps_ * avg_max_bitrate_kbps_);
|
||||
switch (rate_control_state_) {
|
||||
@ -214,7 +216,7 @@ uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps,
|
||||
|
||||
case kRcIncrease:
|
||||
if (avg_max_bitrate_kbps_ >= 0 &&
|
||||
incoming_bitrate_kbps >
|
||||
estimated_throughput_kbps >
|
||||
avg_max_bitrate_kbps_ + 3 * std_max_bit_rate) {
|
||||
ChangeRegion(kRcMaxUnknown);
|
||||
avg_max_bitrate_kbps_ = -1.0;
|
||||
@ -236,7 +238,7 @@ uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps,
|
||||
// Set bit rate to something slightly lower than max
|
||||
// to get rid of any self-induced delay.
|
||||
new_bitrate_bps =
|
||||
static_cast<uint32_t>(beta_ * incoming_bitrate_bps + 0.5);
|
||||
static_cast<uint32_t>(beta_ * estimated_throughput_bps + 0.5);
|
||||
if (new_bitrate_bps > current_bitrate_bps_) {
|
||||
// Avoid increasing the rate when over-using.
|
||||
if (rate_control_region_ != kRcMaxUnknown) {
|
||||
@ -248,7 +250,7 @@ uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps,
|
||||
ChangeRegion(kRcNearMax);
|
||||
|
||||
if (bitrate_is_initialized_ &&
|
||||
incoming_bitrate_bps < current_bitrate_bps_) {
|
||||
estimated_throughput_bps < current_bitrate_bps_) {
|
||||
constexpr float kDegradationFactor = 0.9f;
|
||||
if (smoothing_experiment_ &&
|
||||
new_bitrate_bps <
|
||||
@ -261,13 +263,13 @@ uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps,
|
||||
last_decrease_ = current_bitrate_bps_ - new_bitrate_bps;
|
||||
}
|
||||
}
|
||||
if (incoming_bitrate_kbps <
|
||||
if (estimated_throughput_kbps <
|
||||
avg_max_bitrate_kbps_ - 3 * std_max_bit_rate) {
|
||||
avg_max_bitrate_kbps_ = -1.0f;
|
||||
}
|
||||
|
||||
bitrate_is_initialized_ = true;
|
||||
UpdateMaxBitRateEstimate(incoming_bitrate_kbps);
|
||||
UpdateMaxThroughputEstimate(estimated_throughput_kbps);
|
||||
// Stay on hold until the pipes are cleared.
|
||||
rate_control_state_ = kRcHold;
|
||||
time_last_bitrate_change_ = now_ms;
|
||||
@ -276,16 +278,17 @@ uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps,
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
return ClampBitrate(new_bitrate_bps, incoming_bitrate_bps);
|
||||
return ClampBitrate(new_bitrate_bps, estimated_throughput_bps);
|
||||
}
|
||||
|
||||
uint32_t AimdRateControl::ClampBitrate(uint32_t new_bitrate_bps,
|
||||
uint32_t incoming_bitrate_bps) const {
|
||||
uint32_t AimdRateControl::ClampBitrate(
|
||||
uint32_t new_bitrate_bps,
|
||||
uint32_t estimated_throughput_bps) const {
|
||||
// Don't change the bit rate if the send side is too far off.
|
||||
// We allow a bit more lag at very low rates to not too easily get stuck if
|
||||
// the encoder produces uneven outputs.
|
||||
const uint32_t max_bitrate_bps =
|
||||
static_cast<uint32_t>(1.5f * incoming_bitrate_bps) + 10000;
|
||||
static_cast<uint32_t>(1.5f * estimated_throughput_bps) + 10000;
|
||||
if (new_bitrate_bps > current_bitrate_bps_ &&
|
||||
new_bitrate_bps > max_bitrate_bps) {
|
||||
new_bitrate_bps = std::max(current_bitrate_bps_, max_bitrate_bps);
|
||||
@ -315,21 +318,22 @@ uint32_t AimdRateControl::AdditiveRateIncrease(int64_t now_ms,
|
||||
GetNearMaxIncreaseRateBps() / 1000);
|
||||
}
|
||||
|
||||
void AimdRateControl::UpdateMaxBitRateEstimate(float incoming_bitrate_kbps) {
|
||||
void AimdRateControl::UpdateMaxThroughputEstimate(
|
||||
float estimated_throughput_kbps) {
|
||||
const float alpha = 0.05f;
|
||||
if (avg_max_bitrate_kbps_ == -1.0f) {
|
||||
avg_max_bitrate_kbps_ = incoming_bitrate_kbps;
|
||||
avg_max_bitrate_kbps_ = estimated_throughput_kbps;
|
||||
} else {
|
||||
avg_max_bitrate_kbps_ =
|
||||
(1 - alpha) * avg_max_bitrate_kbps_ + alpha * incoming_bitrate_kbps;
|
||||
(1 - alpha) * avg_max_bitrate_kbps_ + alpha * estimated_throughput_kbps;
|
||||
}
|
||||
// Estimate the max bit rate variance and normalize the variance
|
||||
// with the average max bit rate.
|
||||
const float norm = std::max(avg_max_bitrate_kbps_, 1.0f);
|
||||
var_max_bitrate_kbps_ =
|
||||
(1 - alpha) * var_max_bitrate_kbps_ +
|
||||
alpha * (avg_max_bitrate_kbps_ - incoming_bitrate_kbps) *
|
||||
(avg_max_bitrate_kbps_ - incoming_bitrate_kbps) / norm;
|
||||
alpha * (avg_max_bitrate_kbps_ - estimated_throughput_kbps) *
|
||||
(avg_max_bitrate_kbps_ - estimated_throughput_kbps) / norm;
|
||||
// 0.4 ~= 14 kbit/s at 500 kbit/s
|
||||
if (var_max_bitrate_kbps_ < 0.4f) {
|
||||
var_max_bitrate_kbps_ = 0.4f;
|
||||
|
||||
@ -26,18 +26,19 @@ class AimdRateControl {
|
||||
AimdRateControl();
|
||||
~AimdRateControl();
|
||||
|
||||
// Returns true if there is a valid estimate of the incoming bitrate, false
|
||||
// otherwise.
|
||||
// Returns true if the target bitrate has been initialized. This happens
|
||||
// either if it has been explicitly set via SetStartBitrate/SetEstimate, or if
|
||||
// we have measured a throughput.
|
||||
bool ValidEstimate() const;
|
||||
void SetStartBitrate(int start_bitrate_bps);
|
||||
void SetMinBitrate(int min_bitrate_bps);
|
||||
int64_t GetFeedbackInterval() const;
|
||||
// Returns true if the bitrate estimate hasn't been changed for more than
|
||||
// an RTT, or if the incoming_bitrate is less than half of the current
|
||||
// an RTT, or if the estimated_throughput is less than half of the current
|
||||
// estimate. Should be used to decide if we should reduce the rate further
|
||||
// when over-using.
|
||||
bool TimeToReduceFurther(int64_t time_now,
|
||||
uint32_t incoming_bitrate_bps) const;
|
||||
uint32_t estimated_throughput_bps) const;
|
||||
uint32_t LatestEstimate() const;
|
||||
void SetRtt(int64_t rtt);
|
||||
uint32_t Update(const RateControlInput* input, int64_t now_ms);
|
||||
@ -49,40 +50,40 @@ class AimdRateControl {
|
||||
int GetExpectedBandwidthPeriodMs() const;
|
||||
|
||||
private:
|
||||
// Update the target bitrate according based on, among other things,
|
||||
// the current rate control state, the current target bitrate and the incoming
|
||||
// bitrate. When in the "increase" state the bitrate will be increased either
|
||||
// Update the target bitrate based on, among other things, the current rate
|
||||
// control state, the current target bitrate and the estimated throughput.
|
||||
// When in the "increase" state the bitrate will be increased either
|
||||
// additively or multiplicatively depending on the rate control region. When
|
||||
// in the "decrease" state the bitrate will be decreased to slightly below the
|
||||
// incoming bitrate. When in the "hold" state the bitrate will be kept
|
||||
// current throughput. When in the "hold" state the bitrate will be kept
|
||||
// constant to allow built up queues to drain.
|
||||
uint32_t ChangeBitrate(uint32_t current_bitrate,
|
||||
const RateControlInput& input,
|
||||
int64_t now_ms);
|
||||
// Clamps new_bitrate_bps to within the configured min bitrate and a linear
|
||||
// function of the incoming bitrate, so that the new bitrate can't grow too
|
||||
// function of the throughput, so that the new bitrate can't grow too
|
||||
// large compared to the bitrate actually being received by the other end.
|
||||
uint32_t ClampBitrate(uint32_t new_bitrate_bps,
|
||||
uint32_t incoming_bitrate_bps) const;
|
||||
uint32_t estimated_throughput_bps) const;
|
||||
uint32_t MultiplicativeRateIncrease(int64_t now_ms,
|
||||
int64_t last_ms,
|
||||
uint32_t current_bitrate_bps) const;
|
||||
uint32_t AdditiveRateIncrease(int64_t now_ms, int64_t last_ms) const;
|
||||
void UpdateChangePeriod(int64_t now_ms);
|
||||
void UpdateMaxBitRateEstimate(float incoming_bit_rate_kbps);
|
||||
void UpdateMaxThroughputEstimate(float estimated_throughput_kbps);
|
||||
void ChangeState(const RateControlInput& input, int64_t now_ms);
|
||||
void ChangeRegion(RateControlRegion region);
|
||||
|
||||
uint32_t min_configured_bitrate_bps_;
|
||||
uint32_t max_configured_bitrate_bps_;
|
||||
uint32_t current_bitrate_bps_;
|
||||
uint32_t latest_incoming_bitrate_bps_;
|
||||
uint32_t latest_estimated_throughput_bps_;
|
||||
float avg_max_bitrate_kbps_;
|
||||
float var_max_bitrate_kbps_;
|
||||
RateControlState rate_control_state_;
|
||||
RateControlRegion rate_control_region_;
|
||||
int64_t time_last_bitrate_change_;
|
||||
int64_t time_first_incoming_estimate_;
|
||||
int64_t time_first_throughput_estimate_;
|
||||
bool bitrate_is_initialized_;
|
||||
float beta_;
|
||||
int64_t rtt_;
|
||||
|
||||
@ -43,9 +43,9 @@ AimdRateControlStates CreateAimdRateControlStates() {
|
||||
|
||||
void UpdateRateControl(const AimdRateControlStates& states,
|
||||
const BandwidthUsage& bandwidth_usage,
|
||||
absl::optional<uint32_t> bitrate,
|
||||
absl::optional<uint32_t> throughput_estimate,
|
||||
int64_t now_ms) {
|
||||
RateControlInput input(bandwidth_usage, bitrate, now_ms);
|
||||
RateControlInput input(bandwidth_usage, throughput_estimate);
|
||||
states.aimd_rate_control->Update(&input, now_ms);
|
||||
}
|
||||
|
||||
|
||||
@ -30,11 +30,8 @@ int GetMinBitrateBps() {
|
||||
|
||||
RateControlInput::RateControlInput(
|
||||
BandwidthUsage bw_state,
|
||||
const absl::optional<uint32_t>& incoming_bitrate,
|
||||
double noise_var)
|
||||
: bw_state(bw_state),
|
||||
incoming_bitrate(incoming_bitrate),
|
||||
noise_var(noise_var) {}
|
||||
const absl::optional<uint32_t>& estimated_throughput_bps)
|
||||
: bw_state(bw_state), estimated_throughput_bps(estimated_throughput_bps) {}
|
||||
|
||||
RateControlInput::~RateControlInput() = default;
|
||||
|
||||
|
||||
@ -48,13 +48,11 @@ enum RateControlRegion { kRcNearMax, kRcAboveMax, kRcMaxUnknown };
|
||||
|
||||
struct RateControlInput {
|
||||
RateControlInput(BandwidthUsage bw_state,
|
||||
const absl::optional<uint32_t>& incoming_bitrate,
|
||||
double noise_var);
|
||||
const absl::optional<uint32_t>& estimated_throughput_bps);
|
||||
~RateControlInput();
|
||||
|
||||
BandwidthUsage bw_state;
|
||||
absl::optional<uint32_t> incoming_bitrate;
|
||||
double noise_var;
|
||||
absl::optional<uint32_t> estimated_throughput_bps;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
@ -331,8 +331,7 @@ void RemoteBitrateEstimatorAbsSendTime::IncomingPacketInfo(
|
||||
// We also have to update the estimate immediately if we are overusing
|
||||
// and the target bitrate is too high compared to what we are receiving.
|
||||
const RateControlInput input(detector_.State(),
|
||||
incoming_bitrate_.Rate(arrival_time_ms),
|
||||
estimator_->var_noise());
|
||||
incoming_bitrate_.Rate(arrival_time_ms));
|
||||
target_bitrate_bps = remote_rate_.Update(&input, now_ms);
|
||||
update_estimate = remote_rate_.ValidEstimate();
|
||||
ssrcs = Keys(ssrcs_);
|
||||
|
||||
@ -157,7 +157,6 @@ int64_t RemoteBitrateEstimatorSingleStream::TimeUntilNextProcess() {
|
||||
|
||||
void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t now_ms) {
|
||||
BandwidthUsage bw_state = BandwidthUsage::kBwNormal;
|
||||
double sum_var_noise = 0.0;
|
||||
SsrcOveruseEstimatorMap::iterator it = overuse_detectors_.begin();
|
||||
while (it != overuse_detectors_.end()) {
|
||||
const int64_t time_of_last_received_packet =
|
||||
@ -169,7 +168,6 @@ void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t now_ms) {
|
||||
delete it->second;
|
||||
overuse_detectors_.erase(it++);
|
||||
} else {
|
||||
sum_var_noise += it->second->estimator.var_noise();
|
||||
// Make sure that we trigger an over-use if any of the over-use detectors
|
||||
// is detecting over-use.
|
||||
if (it->second->detector.State() > bw_state) {
|
||||
@ -184,10 +182,7 @@ void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t now_ms) {
|
||||
}
|
||||
AimdRateControl* remote_rate = GetRemoteRate();
|
||||
|
||||
double mean_noise_var =
|
||||
sum_var_noise / static_cast<double>(overuse_detectors_.size());
|
||||
const RateControlInput input(bw_state, incoming_bitrate_.Rate(now_ms),
|
||||
mean_noise_var);
|
||||
const RateControlInput input(bw_state, incoming_bitrate_.Rate(now_ms));
|
||||
uint32_t target_bitrate = remote_rate->Update(&input, now_ms);
|
||||
if (remote_rate->ValidEstimate()) {
|
||||
process_interval_ms_ = remote_rate->GetFeedbackInterval();
|
||||
|
||||
Reference in New Issue
Block a user