From 53c75cff2ebdbdd05ba5387a7fd59abe2372fb0b Mon Sep 17 00:00:00 2001 From: Christoffer Rodbro Date: Wed, 27 Mar 2019 16:24:09 +0100 Subject: [PATCH] Fix for acknowledged bitrate estimator getting stuck at low bandwidth. Problem seems to be that once the estimate drops, "sample_uncertainty" becomes very large, and it therefore takes a long time to recover. Fix is under config for further downstream verification. Bug: webrtc:10462 Change-Id: I5c2035f06e8a5088db0f0cb6ca511ef900e07645 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/128902 Commit-Queue: Christoffer Rodbro Reviewed-by: Sebastian Jansson Cr-Commit-Position: refs/heads/master@{#27320} --- .../goog_cc/bitrate_estimator.cc | 48 ++++++++++++------- .../goog_cc/bitrate_estimator.h | 6 ++- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/modules/congestion_controller/goog_cc/bitrate_estimator.cc b/modules/congestion_controller/goog_cc/bitrate_estimator.cc index b68498e993..4ac65dd2e4 100644 --- a/modules/congestion_controller/goog_cc/bitrate_estimator.cc +++ b/modules/congestion_controller/goog_cc/bitrate_estimator.cc @@ -11,9 +11,11 @@ #include "modules/congestion_controller/goog_cc/bitrate_estimator.h" #include +#include #include #include +#include "api/units/data_rate.h" #include "modules/remote_bitrate_estimator/test/bwe_test_logging.h" #include "rtc_base/logging.h" @@ -39,13 +41,18 @@ BitrateEstimator::BitrateEstimator(const WebRtcKeyValueConfig* key_value_config) kRateWindowMs, kMinRateWindowMs, kMaxRateWindowMs), + uncertainty_scale_("scale", 10.0), + uncertainty_symmetry_cap_("symmetry_cap", DataRate::Zero()), + estimate_floor_("floor", DataRate::Zero()), current_window_ms_(0), prev_time_ms_(-1), - bitrate_estimate_(-1.0f), + bitrate_estimate_kbps_(-1.0f), bitrate_estimate_var_(50.0f) { // E.g WebRTC-BweThroughputWindowConfig/initial_window_ms:350,window_ms:250/ - ParseFieldTrial({&initial_window_ms_, &noninitial_window_ms_}, - key_value_config->Lookup(kBweThroughputWindowConfig)); + ParseFieldTrial( + {&initial_window_ms_, &noninitial_window_ms_, &uncertainty_scale_, + &uncertainty_symmetry_cap_, &estimate_floor_}, + key_value_config->Lookup(kBweThroughputWindowConfig)); } BitrateEstimator::~BitrateEstimator() = default; @@ -54,33 +61,42 @@ void BitrateEstimator::Update(int64_t now_ms, int bytes) { int rate_window_ms = noninitial_window_ms_.Get(); // We use a larger window at the beginning to get a more stable sample that // we can use to initialize the estimate. - if (bitrate_estimate_ < 0.f) + if (bitrate_estimate_kbps_ < 0.f) rate_window_ms = initial_window_ms_.Get(); - float bitrate_sample = UpdateWindow(now_ms, bytes, rate_window_ms); - if (bitrate_sample < 0.0f) + float bitrate_sample_kbps = UpdateWindow(now_ms, bytes, rate_window_ms); + if (bitrate_sample_kbps < 0.0f) return; - if (bitrate_estimate_ < 0.0f) { + if (bitrate_estimate_kbps_ < 0.0f) { // This is the very first sample we get. Use it to initialize the estimate. - bitrate_estimate_ = bitrate_sample; + bitrate_estimate_kbps_ = bitrate_sample_kbps; return; } // Define the sample uncertainty as a function of how far away it is from the - // current estimate. + // current estimate. With low values of uncertainty_symmetry_cap_ we add more + // uncertainty to increases than to decreases. For higher values we approach + // symmetry. float sample_uncertainty = - 10.0f * std::abs(bitrate_estimate_ - bitrate_sample) / bitrate_estimate_; + uncertainty_scale_ * + std::abs(bitrate_estimate_kbps_ - bitrate_sample_kbps) / + (bitrate_estimate_kbps_ + + std::min(bitrate_sample_kbps, + uncertainty_symmetry_cap_.Get().kbps())); + float sample_var = sample_uncertainty * sample_uncertainty; // Update a bayesian estimate of the rate, weighting it lower if the sample // uncertainty is large. // The bitrate estimate uncertainty is increased with each update to model // that the bitrate changes over time. float pred_bitrate_estimate_var = bitrate_estimate_var_ + 5.f; - bitrate_estimate_ = (sample_var * bitrate_estimate_ + - pred_bitrate_estimate_var * bitrate_sample) / - (sample_var + pred_bitrate_estimate_var); + bitrate_estimate_kbps_ = (sample_var * bitrate_estimate_kbps_ + + pred_bitrate_estimate_var * bitrate_sample_kbps) / + (sample_var + pred_bitrate_estimate_var); + bitrate_estimate_kbps_ = + std::max(bitrate_estimate_kbps_, estimate_floor_.Get().kbps()); bitrate_estimate_var_ = sample_var * pred_bitrate_estimate_var / (sample_var + pred_bitrate_estimate_var); BWE_TEST_LOGGING_PLOT(1, "acknowledged_bitrate", now_ms, - bitrate_estimate_ * 1000); + bitrate_estimate_kbps_ * 1000); } float BitrateEstimator::UpdateWindow(int64_t now_ms, @@ -112,9 +128,9 @@ float BitrateEstimator::UpdateWindow(int64_t now_ms, } absl::optional BitrateEstimator::bitrate_bps() const { - if (bitrate_estimate_ < 0.f) + if (bitrate_estimate_kbps_ < 0.f) return absl::nullopt; - return bitrate_estimate_ * 1000; + return bitrate_estimate_kbps_ * 1000; } absl::optional BitrateEstimator::PeekBps() const { diff --git a/modules/congestion_controller/goog_cc/bitrate_estimator.h b/modules/congestion_controller/goog_cc/bitrate_estimator.h index ceac42ecef..33866a7482 100644 --- a/modules/congestion_controller/goog_cc/bitrate_estimator.h +++ b/modules/congestion_controller/goog_cc/bitrate_estimator.h @@ -15,6 +15,7 @@ #include "absl/types/optional.h" #include "api/transport/webrtc_key_value_config.h" +#include "api/units/data_rate.h" #include "rtc_base/experiments/field_trial_parser.h" namespace webrtc { @@ -40,9 +41,12 @@ class BitrateEstimator { int sum_; FieldTrialConstrained initial_window_ms_; FieldTrialConstrained noninitial_window_ms_; + FieldTrialParameter uncertainty_scale_; + FieldTrialParameter uncertainty_symmetry_cap_; + FieldTrialParameter estimate_floor_; int64_t current_window_ms_; int64_t prev_time_ms_; - float bitrate_estimate_; + float bitrate_estimate_kbps_; float bitrate_estimate_var_; };