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 <crodbro@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27320}
This commit is contained in:
Christoffer Rodbro 2019-03-27 16:24:09 +01:00 committed by Commit Bot
parent b8fffa1ad8
commit 53c75cff2e
2 changed files with 37 additions and 17 deletions

View File

@ -11,9 +11,11 @@
#include "modules/congestion_controller/goog_cc/bitrate_estimator.h"
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <string>
#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>()));
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<float>());
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<uint32_t> 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<uint32_t> BitrateEstimator::PeekBps() const {

View File

@ -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<int> initial_window_ms_;
FieldTrialConstrained<int> noninitial_window_ms_;
FieldTrialParameter<double> uncertainty_scale_;
FieldTrialParameter<DataRate> uncertainty_symmetry_cap_;
FieldTrialParameter<DataRate> estimate_floor_;
int64_t current_window_ms_;
int64_t prev_time_ms_;
float bitrate_estimate_;
float bitrate_estimate_kbps_;
float bitrate_estimate_var_;
};