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:
parent
b8fffa1ad8
commit
53c75cff2e
@ -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 {
|
||||
|
||||
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user