Reland of https://chromium-review.googlesource.com/c/external/webrtc/+/616724 under field trial.
Bug: webrtc:8105
Change-Id: I8c68e0f270b3bd5d8da28b8334d4689064f607f6
Reviewed-on: https://webrtc-review.googlesource.com/4920
Commit-Queue: Ivo Creusen <ivoc@webrtc.org>
Reviewed-by: Alex Narest <alexnarest@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20205}
diff --git a/modules/remote_bitrate_estimator/aimd_rate_control.cc b/modules/remote_bitrate_estimator/aimd_rate_control.cc
index 96b0534..37c2529 100644
--- a/modules/remote_bitrate_estimator/aimd_rate_control.cc
+++ b/modules/remote_bitrate_estimator/aimd_rate_control.cc
@@ -68,7 +68,9 @@
? ReadTrendlineFilterWindowSize()
: kDefaultBackoffFactor),
rtt_(kDefaultRttMs),
- in_experiment_(!AdaptiveThresholdExperimentIsDisabled()) {
+ in_experiment_(!AdaptiveThresholdExperimentIsDisabled()),
+ smoothing_experiment_(
+ webrtc::field_trial::IsEnabled("WebRTC-Audio-BandwidthSmoothing")) {
LOG(LS_INFO) << "Using aimd rate control with back off factor " << beta_;
}
@@ -166,13 +168,13 @@
}
int AimdRateControl::GetExpectedBandwidthPeriodMs() const {
- constexpr int kMinPeriodMs = 2000;
+ const int kMinPeriodMs = smoothing_experiment_ ? 500 : 2000;
constexpr int kDefaultPeriodMs = 3000;
constexpr int kMaxPeriodMs = 50000;
int increase_rate = GetNearMaxIncreaseRateBps();
if (!last_decrease_)
- return kDefaultPeriodMs;
+ return smoothing_experiment_ ? kMinPeriodMs : kDefaultPeriodMs;
return std::min(kMaxPeriodMs,
std::max<int>(1000 * static_cast<int64_t>(*last_decrease_) /
@@ -241,8 +243,18 @@
if (bitrate_is_initialized_ &&
incoming_bitrate_bps < current_bitrate_bps_) {
- last_decrease_ =
- rtc::Optional<int>(current_bitrate_bps_ - new_bitrate_bps);
+ constexpr float kDegradationFactor = 0.9f;
+ if (smoothing_experiment_ &&
+ new_bitrate_bps <
+ kDegradationFactor * beta_ * current_bitrate_bps_) {
+ // If bitrate decreases more than a normal back off after overuse, it
+ // indicates a real network degradation. We do not let such a decrease
+ // to determine the bandwidth estimation period.
+ last_decrease_ = rtc::Optional<int>();
+ } else {
+ last_decrease_ =
+ rtc::Optional<int>(current_bitrate_bps_ - new_bitrate_bps);
+ }
}
if (incoming_bitrate_kbps <
avg_max_bitrate_kbps_ - 3 * std_max_bit_rate) {
diff --git a/modules/remote_bitrate_estimator/aimd_rate_control.h b/modules/remote_bitrate_estimator/aimd_rate_control.h
index 769429a..a9ecb67 100644
--- a/modules/remote_bitrate_estimator/aimd_rate_control.h
+++ b/modules/remote_bitrate_estimator/aimd_rate_control.h
@@ -85,6 +85,7 @@
float beta_;
int64_t rtt_;
bool in_experiment_;
+ bool smoothing_experiment_;
rtc::Optional<int> last_decrease_;
};
} // namespace webrtc
diff --git a/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc b/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc
index 690eb68..1e894d9 100644
--- a/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc
+++ b/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc
@@ -11,6 +11,7 @@
#include "modules/remote_bitrate_estimator/aimd_rate_control.h"
#include "system_wrappers/include/clock.h"
+#include "test/field_trial.h"
#include "test/gtest.h"
namespace webrtc {
@@ -18,9 +19,12 @@
constexpr int64_t kClockInitialTime = 123456;
-constexpr int kMinBwePeriodMs = 2000;
+constexpr int kMinBwePeriodMsSmoothingExp = 500;
+constexpr int kMinBwePeriodMsNoSmoothingExp = 2000;
+constexpr int kDefaultPeriodMsNoSmoothingExp = 3000;
constexpr int kMaxBwePeriodMs = 50000;
-constexpr int kDefaultPeriodMs = 3000;
+constexpr char kSmoothingExpFieldTrial[] =
+ "WebRTC-Audio-BandwidthSmoothing/Enabled/";
// After an overuse, we back off to 85% to the received bitrate.
constexpr double kFractionAfterOveruse = 0.85;
@@ -74,6 +78,7 @@
}
TEST(AimdRateControlTest, GetIncreaseRateAndBandwidthPeriod) {
+ // Smoothing experiment disabled
auto states = CreateAimdRateControlStates();
constexpr int kBitrate = 300000;
states.aimd_rate_control->SetEstimate(
@@ -82,7 +87,23 @@
states.simulated_clock->TimeInMilliseconds());
EXPECT_NEAR(14000, states.aimd_rate_control->GetNearMaxIncreaseRateBps(),
1000);
- EXPECT_EQ(3000, states.aimd_rate_control->GetExpectedBandwidthPeriodMs());
+ EXPECT_EQ(kDefaultPeriodMsNoSmoothingExp,
+ states.aimd_rate_control->GetExpectedBandwidthPeriodMs());
+}
+
+TEST(AimdRateControlTest, GetIncreaseRateAndBandwidthPeriodSmoothingExp) {
+ // Smoothing experiment enabled
+ test::ScopedFieldTrials override_field_trials(kSmoothingExpFieldTrial);
+ auto states = CreateAimdRateControlStates();
+ constexpr int kBitrate = 300000;
+ states.aimd_rate_control->SetEstimate(
+ kBitrate, states.simulated_clock->TimeInMilliseconds());
+ UpdateRateControl(states, BandwidthUsage::kBwOverusing, kBitrate,
+ states.simulated_clock->TimeInMilliseconds());
+ EXPECT_NEAR(14000, states.aimd_rate_control->GetNearMaxIncreaseRateBps(),
+ 1000);
+ EXPECT_EQ(kMinBwePeriodMsSmoothingExp,
+ states.aimd_rate_control->GetExpectedBandwidthPeriodMs());
}
TEST(AimdRateControlTest, BweLimitedByAckedBitrate) {
@@ -125,14 +146,29 @@
}
TEST(AimdRateControlTest, DefaultPeriodUntilFirstOveruse) {
+ // Smoothing experiment disabled
auto states = CreateAimdRateControlStates();
states.aimd_rate_control->SetStartBitrate(300000);
- EXPECT_EQ(kDefaultPeriodMs,
+ EXPECT_EQ(kDefaultPeriodMsNoSmoothingExp,
states.aimd_rate_control->GetExpectedBandwidthPeriodMs());
states.simulated_clock->AdvanceTimeMilliseconds(100);
- UpdateRateControl(states, BandwidthUsage::kBwOverusing, 100000,
+ UpdateRateControl(states, BandwidthUsage::kBwOverusing, 280000,
states.simulated_clock->TimeInMilliseconds());
- EXPECT_NE(kDefaultPeriodMs,
+ EXPECT_NE(kDefaultPeriodMsNoSmoothingExp,
+ states.aimd_rate_control->GetExpectedBandwidthPeriodMs());
+}
+
+TEST(AimdRateControlTest, MinPeriodUntilFirstOveruseSmoothingExp) {
+ // Smoothing experiment enabled
+ test::ScopedFieldTrials override_field_trials(kSmoothingExpFieldTrial);
+ auto states = CreateAimdRateControlStates();
+ states.aimd_rate_control->SetStartBitrate(300000);
+ EXPECT_EQ(kMinBwePeriodMsSmoothingExp,
+ states.aimd_rate_control->GetExpectedBandwidthPeriodMs());
+ states.simulated_clock->AdvanceTimeMilliseconds(100);
+ UpdateRateControl(states, BandwidthUsage::kBwOverusing, 280000,
+ states.simulated_clock->TimeInMilliseconds());
+ EXPECT_NE(kMinBwePeriodMsSmoothingExp,
states.aimd_rate_control->GetExpectedBandwidthPeriodMs());
}
@@ -152,6 +188,23 @@
EXPECT_EQ(4000, states.aimd_rate_control->GetExpectedBandwidthPeriodMs());
}
+TEST(AimdRateControlTest, MinPeriodAfterLargeBitrateDecreaseSmoothingExp) {
+ // Smoothing experiment enabled
+ test::ScopedFieldTrials override_field_trials(kSmoothingExpFieldTrial);
+ auto states = CreateAimdRateControlStates();
+ constexpr int kInitialBitrate = 110000;
+ states.aimd_rate_control->SetEstimate(
+ kInitialBitrate, states.simulated_clock->TimeInMilliseconds());
+ states.simulated_clock->AdvanceTimeMilliseconds(100);
+ // Make such a large drop in bitrate that should be treated as network
+ // degradation.
+ constexpr int kAckedBitrate = kInitialBitrate * 3 / 4 / kFractionAfterOveruse;
+ UpdateRateControl(states, BandwidthUsage::kBwOverusing, kAckedBitrate,
+ states.simulated_clock->TimeInMilliseconds());
+ EXPECT_EQ(kMinBwePeriodMsSmoothingExp,
+ states.aimd_rate_control->GetExpectedBandwidthPeriodMs());
+}
+
TEST(AimdRateControlTest, BandwidthPeriodIsNotBelowMin) {
auto states = CreateAimdRateControlStates();
constexpr int kInitialBitrate = 10000;
@@ -161,11 +214,27 @@
// Make a small (1.5 kbps) bitrate drop to 8.5 kbps.
UpdateRateControl(states, BandwidthUsage::kBwOverusing, kInitialBitrate - 1,
states.simulated_clock->TimeInMilliseconds());
- EXPECT_EQ(kMinBwePeriodMs,
+ EXPECT_EQ(kMinBwePeriodMsNoSmoothingExp,
states.aimd_rate_control->GetExpectedBandwidthPeriodMs());
}
-TEST(AimdRateControlTest, BandwidthPeriodIsNotAboveMax) {
+TEST(AimdRateControlTest, BandwidthPeriodIsNotAboveMaxSmoothingExp) {
+ // Smoothing experiment enabled
+ test::ScopedFieldTrials override_field_trials(kSmoothingExpFieldTrial);
+ auto states = CreateAimdRateControlStates();
+ constexpr int kInitialBitrate = 50000000;
+ states.aimd_rate_control->SetEstimate(
+ kInitialBitrate, states.simulated_clock->TimeInMilliseconds());
+ states.simulated_clock->AdvanceTimeMilliseconds(100);
+ // Make a large (10 Mbps) bitrate drop to 10 kbps.
+ constexpr int kAckedBitrate = 40000000 / kFractionAfterOveruse;
+ UpdateRateControl(states, BandwidthUsage::kBwOverusing, kAckedBitrate,
+ states.simulated_clock->TimeInMilliseconds());
+ EXPECT_EQ(kMaxBwePeriodMs,
+ states.aimd_rate_control->GetExpectedBandwidthPeriodMs());
+}
+
+TEST(AimdRateControlTest, BandwidthPeriodIsNotAboveMaxNoSmoothingExp) {
auto states = CreateAimdRateControlStates();
constexpr int kInitialBitrate = 10010000;
states.aimd_rate_control->SetEstimate(