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}
This commit is contained in:
Ivo Creusen 2017-10-09 12:28:39 +02:00 committed by Commit Bot
parent 0f46441772
commit 46ca2879e1
3 changed files with 95 additions and 13 deletions

View File

@ -68,7 +68,9 @@ AimdRateControl::AimdRateControl()
? 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::GetNearMaxIncreaseRateBps() const {
}
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 @@ uint32_t AimdRateControl::ChangeBitrate(uint32_t new_bitrate_bps,
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) {

View File

@ -85,6 +85,7 @@ class AimdRateControl {
float beta_;
int64_t rtt_;
bool in_experiment_;
bool smoothing_experiment_;
rtc::Optional<int> last_decrease_;
};
} // namespace webrtc

View File

@ -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 @@ namespace {
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, NearMaxIncreaseRateIs5kbpsOn60kbpsAnd100msRtt) {
}
TEST(AimdRateControlTest, GetIncreaseRateAndBandwidthPeriod) {
// Smoothing experiment disabled
auto states = CreateAimdRateControlStates();
constexpr int kBitrate = 300000;
states.aimd_rate_control->SetEstimate(
@ -82,7 +87,23 @@ TEST(AimdRateControlTest, GetIncreaseRateAndBandwidthPeriod) {
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, BweNotLimitedByDecreasingAckedBitrate) {
}
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 @@ TEST(AimdRateControlTest, ExpectedPeriodAfter20kbpsDropAnd5kbpsIncrease) {
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 @@ TEST(AimdRateControlTest, BandwidthPeriodIsNotBelowMin) {
// 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(