diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /third_party/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc')
-rw-r--r-- | third_party/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc b/third_party/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc new file mode 100644 index 0000000000..f26afe995c --- /dev/null +++ b/third_party/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control_unittest.cc @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "modules/remote_bitrate_estimator/aimd_rate_control.h" + +#include "api/units/data_rate.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "test/explicit_key_value_config.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +using ::webrtc::test::ExplicitKeyValueConfig; + +constexpr Timestamp kInitialTime = Timestamp::Millis(123'456); + +constexpr TimeDelta kMinBwePeriod = TimeDelta::Seconds(2); +constexpr TimeDelta kDefaultPeriod = TimeDelta::Seconds(3); +constexpr TimeDelta kMaxBwePeriod = TimeDelta::Seconds(50); + +// After an overuse, we back off to 85% to the received bitrate. +constexpr double kFractionAfterOveruse = 0.85; + +} // namespace + +TEST(AimdRateControlTest, MinNearMaxIncreaseRateOnLowBandwith) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig("")); + aimd_rate_control.SetEstimate(DataRate::BitsPerSec(30'000), kInitialTime); + EXPECT_EQ(aimd_rate_control.GetNearMaxIncreaseRateBpsPerSecond(), 4'000); +} + +TEST(AimdRateControlTest, NearMaxIncreaseRateIs5kbpsOn90kbpsAnd200msRtt) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig("")); + aimd_rate_control.SetEstimate(DataRate::BitsPerSec(90'000), kInitialTime); + EXPECT_EQ(aimd_rate_control.GetNearMaxIncreaseRateBpsPerSecond(), 5'000); +} + +TEST(AimdRateControlTest, NearMaxIncreaseRateIs5kbpsOn60kbpsAnd100msRtt) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig("")); + aimd_rate_control.SetEstimate(DataRate::BitsPerSec(60'000), kInitialTime); + aimd_rate_control.SetRtt(TimeDelta::Millis(100)); + EXPECT_EQ(aimd_rate_control.GetNearMaxIncreaseRateBpsPerSecond(), 5'000); +} + +TEST(AimdRateControlTest, GetIncreaseRateAndBandwidthPeriod) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig("")); + constexpr DataRate kBitrate = DataRate::BitsPerSec(300'000); + aimd_rate_control.SetEstimate(kBitrate, kInitialTime); + aimd_rate_control.Update({BandwidthUsage::kBwOverusing, kBitrate}, + kInitialTime); + EXPECT_NEAR(aimd_rate_control.GetNearMaxIncreaseRateBpsPerSecond(), 14'000, + 1'000); + EXPECT_EQ(aimd_rate_control.GetExpectedBandwidthPeriod(), kDefaultPeriod); +} + +TEST(AimdRateControlTest, BweLimitedByAckedBitrate) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig("")); + constexpr DataRate kAckedBitrate = DataRate::BitsPerSec(10'000); + Timestamp now = kInitialTime; + aimd_rate_control.SetEstimate(kAckedBitrate, now); + while (now - kInitialTime < TimeDelta::Seconds(20)) { + aimd_rate_control.Update({BandwidthUsage::kBwNormal, kAckedBitrate}, now); + now += TimeDelta::Millis(100); + } + ASSERT_TRUE(aimd_rate_control.ValidEstimate()); + EXPECT_EQ(aimd_rate_control.LatestEstimate(), + 1.5 * kAckedBitrate + DataRate::BitsPerSec(10'000)); +} + +TEST(AimdRateControlTest, BweNotLimitedByDecreasingAckedBitrate) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig("")); + constexpr DataRate kAckedBitrate = DataRate::BitsPerSec(10'000); + Timestamp now = kInitialTime; + aimd_rate_control.SetEstimate(kAckedBitrate, now); + while (now - kInitialTime < TimeDelta::Seconds(20)) { + aimd_rate_control.Update({BandwidthUsage::kBwNormal, kAckedBitrate}, now); + now += TimeDelta::Millis(100); + } + ASSERT_TRUE(aimd_rate_control.ValidEstimate()); + // If the acked bitrate decreases the BWE shouldn't be reduced to 1.5x + // what's being acked, but also shouldn't get to increase more. + DataRate prev_estimate = aimd_rate_control.LatestEstimate(); + aimd_rate_control.Update({BandwidthUsage::kBwNormal, kAckedBitrate / 2}, now); + DataRate new_estimate = aimd_rate_control.LatestEstimate(); + EXPECT_EQ(new_estimate, prev_estimate); + EXPECT_NEAR(new_estimate.bps(), + (1.5 * kAckedBitrate + DataRate::BitsPerSec(10'000)).bps(), + 2'000); +} + +TEST(AimdRateControlTest, DefaultPeriodUntilFirstOveruse) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig("")); + aimd_rate_control.SetStartBitrate(DataRate::KilobitsPerSec(300)); + EXPECT_EQ(aimd_rate_control.GetExpectedBandwidthPeriod(), kDefaultPeriod); + aimd_rate_control.Update( + {BandwidthUsage::kBwOverusing, DataRate::KilobitsPerSec(280)}, + kInitialTime); + EXPECT_NE(aimd_rate_control.GetExpectedBandwidthPeriod(), kDefaultPeriod); +} + +TEST(AimdRateControlTest, ExpectedPeriodAfterTypicalDrop) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig("")); + // The rate increase at 216 kbps should be 12 kbps. If we drop from + // 216 + 4*12 = 264 kbps, it should take 4 seconds to recover. Since we + // back off to 0.85*acked_rate-5kbps, the acked bitrate needs to be 260 + // kbps to end up at 216 kbps. + constexpr DataRate kInitialBitrate = DataRate::BitsPerSec(264'000); + constexpr DataRate kUpdatedBitrate = DataRate::BitsPerSec(216'000); + const DataRate kAckedBitrate = + (kUpdatedBitrate + DataRate::BitsPerSec(5'000)) / kFractionAfterOveruse; + Timestamp now = kInitialTime; + aimd_rate_control.SetEstimate(kInitialBitrate, now); + now += TimeDelta::Millis(100); + aimd_rate_control.Update({BandwidthUsage::kBwOverusing, kAckedBitrate}, now); + EXPECT_EQ(aimd_rate_control.LatestEstimate(), kUpdatedBitrate); + EXPECT_EQ(aimd_rate_control.GetNearMaxIncreaseRateBpsPerSecond(), 12'000); + EXPECT_EQ(aimd_rate_control.GetExpectedBandwidthPeriod(), + TimeDelta::Seconds(4)); +} + +TEST(AimdRateControlTest, BandwidthPeriodIsNotBelowMin) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig("")); + constexpr DataRate kInitialBitrate = DataRate::BitsPerSec(10'000); + Timestamp now = kInitialTime; + aimd_rate_control.SetEstimate(kInitialBitrate, now); + now += TimeDelta::Millis(100); + // Make a small (1.5 kbps) bitrate drop to 8.5 kbps. + aimd_rate_control.Update( + {BandwidthUsage::kBwOverusing, kInitialBitrate - DataRate::BitsPerSec(1)}, + now); + EXPECT_EQ(aimd_rate_control.GetExpectedBandwidthPeriod(), kMinBwePeriod); +} + +TEST(AimdRateControlTest, BandwidthPeriodIsNotAboveMaxNoSmoothingExp) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig("")); + constexpr DataRate kInitialBitrate = DataRate::BitsPerSec(10'010'000); + Timestamp now = kInitialTime; + aimd_rate_control.SetEstimate(kInitialBitrate, now); + now += TimeDelta::Millis(100); + // Make a large (10 Mbps) bitrate drop to 10 kbps. + const DataRate kAckedBitrate = + DataRate::BitsPerSec(10'000) / kFractionAfterOveruse; + aimd_rate_control.Update({BandwidthUsage::kBwOverusing, kAckedBitrate}, now); + EXPECT_EQ(aimd_rate_control.GetExpectedBandwidthPeriod(), kMaxBwePeriod); +} + +TEST(AimdRateControlTest, SendingRateBoundedWhenThroughputNotEstimated) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig("")); + constexpr DataRate kInitialBitrate = DataRate::BitsPerSec(123'000); + Timestamp now = kInitialTime; + aimd_rate_control.Update({BandwidthUsage::kBwNormal, kInitialBitrate}, now); + // AimdRateControl sets the initial bit rate to what it receives after + // five seconds has passed. + // TODO(bugs.webrtc.org/9379): The comment in the AimdRateControl does not + // match the constant. + constexpr TimeDelta kInitializationTime = TimeDelta::Seconds(5); + now += (kInitializationTime + TimeDelta::Millis(1)); + aimd_rate_control.Update({BandwidthUsage::kBwNormal, kInitialBitrate}, now); + for (int i = 0; i < 100; ++i) { + aimd_rate_control.Update({BandwidthUsage::kBwNormal, absl::nullopt}, now); + now += TimeDelta::Millis(100); + } + EXPECT_LE(aimd_rate_control.LatestEstimate(), + kInitialBitrate * 1.5 + DataRate::BitsPerSec(10'000)); +} + +TEST(AimdRateControlTest, EstimateDoesNotIncreaseInAlr) { + // When alr is detected, the delay based estimator is not allowed to increase + // bwe since there will be no feedback from the network if the new estimate + // is correct. + ExplicitKeyValueConfig field_trials( + "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/"); + AimdRateControl aimd_rate_control(field_trials, /*send_side=*/true); + Timestamp now = kInitialTime; + constexpr DataRate kInitialBitrate = DataRate::BitsPerSec(123'000); + aimd_rate_control.SetEstimate(kInitialBitrate, now); + aimd_rate_control.SetInApplicationLimitedRegion(true); + aimd_rate_control.Update({BandwidthUsage::kBwNormal, kInitialBitrate}, now); + ASSERT_EQ(aimd_rate_control.LatestEstimate(), kInitialBitrate); + + for (int i = 0; i < 100; ++i) { + aimd_rate_control.Update({BandwidthUsage::kBwNormal, absl::nullopt}, now); + now += TimeDelta::Millis(100); + } + EXPECT_EQ(aimd_rate_control.LatestEstimate(), kInitialBitrate); +} + +TEST(AimdRateControlTest, SetEstimateIncreaseBweInAlr) { + ExplicitKeyValueConfig field_trials( + "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/"); + AimdRateControl aimd_rate_control(field_trials, /*send_side=*/true); + constexpr DataRate kInitialBitrate = DataRate::BitsPerSec(123'000); + aimd_rate_control.SetEstimate(kInitialBitrate, kInitialTime); + aimd_rate_control.SetInApplicationLimitedRegion(true); + ASSERT_EQ(aimd_rate_control.LatestEstimate(), kInitialBitrate); + aimd_rate_control.SetEstimate(2 * kInitialBitrate, kInitialTime); + EXPECT_EQ(aimd_rate_control.LatestEstimate(), 2 * kInitialBitrate); +} + +TEST(AimdRateControlTest, SetEstimateUpperLimitedByNetworkEstimate) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig(""), + /*send_side=*/true); + NetworkStateEstimate network_estimate; + network_estimate.link_capacity_upper = DataRate::BitsPerSec(400'000); + aimd_rate_control.SetNetworkStateEstimate(network_estimate); + aimd_rate_control.SetEstimate(DataRate::BitsPerSec(500'000), kInitialTime); + EXPECT_EQ(aimd_rate_control.LatestEstimate(), + network_estimate.link_capacity_upper); +} + +TEST(AimdRateControlTest, + SetEstimateUpperLimitedByCurrentBitrateIfNetworkEstimateIsLow) { + AimdRateControl aimd_rate_control( + ExplicitKeyValueConfig( + "WebRTC-Bwe-EstimateBoundedIncrease/c_upper:true/"), + /*send_side=*/true); + aimd_rate_control.SetEstimate(DataRate::BitsPerSec(500'000), kInitialTime); + ASSERT_EQ(aimd_rate_control.LatestEstimate(), DataRate::BitsPerSec(500'000)); + + NetworkStateEstimate network_estimate; + network_estimate.link_capacity_upper = DataRate::BitsPerSec(300'000); + aimd_rate_control.SetNetworkStateEstimate(network_estimate); + aimd_rate_control.SetEstimate(DataRate::BitsPerSec(700'000), kInitialTime); + EXPECT_EQ(aimd_rate_control.LatestEstimate(), DataRate::BitsPerSec(500'000)); +} + +TEST(AimdRateControlTest, + SetEstimateDefaultNotUpperLimitedByCurrentBitrateIfNetworkEstimateIsLow) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig(""), + /*send_side=*/true); + aimd_rate_control.SetEstimate(DataRate::BitsPerSec(500'000), kInitialTime); + ASSERT_EQ(aimd_rate_control.LatestEstimate(), DataRate::BitsPerSec(500'000)); + + NetworkStateEstimate network_estimate; + network_estimate.link_capacity_upper = DataRate::BitsPerSec(300'000); + aimd_rate_control.SetNetworkStateEstimate(network_estimate); + aimd_rate_control.SetEstimate(DataRate::BitsPerSec(700'000), kInitialTime); + EXPECT_EQ(aimd_rate_control.LatestEstimate(), DataRate::BitsPerSec(300'000)); +} + +TEST(AimdRateControlTest, SetEstimateLowerLimitedByNetworkEstimate) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig(""), + /*send_side=*/true); + NetworkStateEstimate network_estimate; + network_estimate.link_capacity_lower = DataRate::BitsPerSec(400'000); + aimd_rate_control.SetNetworkStateEstimate(network_estimate); + aimd_rate_control.SetEstimate(DataRate::BitsPerSec(100'000), kInitialTime); + // 0.85 is default backoff factor. (`beta_`) + EXPECT_EQ(aimd_rate_control.LatestEstimate(), + network_estimate.link_capacity_lower * 0.85); +} + +TEST(AimdRateControlTest, + SetEstimateIgnoredIfLowerThanNetworkEstimateAndCurrent) { + AimdRateControl aimd_rate_control(ExplicitKeyValueConfig(""), + /*send_side=*/true); + aimd_rate_control.SetEstimate(DataRate::KilobitsPerSec(200), kInitialTime); + ASSERT_EQ(aimd_rate_control.LatestEstimate().kbps(), 200); + NetworkStateEstimate network_estimate; + network_estimate.link_capacity_lower = DataRate::KilobitsPerSec(400); + aimd_rate_control.SetNetworkStateEstimate(network_estimate); + // Ignore the next SetEstimate, since the estimate is lower than 85% of + // the network estimate. + aimd_rate_control.SetEstimate(DataRate::KilobitsPerSec(100), kInitialTime); + EXPECT_EQ(aimd_rate_control.LatestEstimate().kbps(), 200); +} + +TEST(AimdRateControlTest, EstimateIncreaseWhileNotInAlr) { + // Allow the estimate to increase as long as alr is not detected to ensure + // tha BWE can not get stuck at a certain bitrate. + ExplicitKeyValueConfig field_trials( + "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/"); + AimdRateControl aimd_rate_control(field_trials, /*send_side=*/true); + Timestamp now = kInitialTime; + constexpr DataRate kInitialBitrate = DataRate::BitsPerSec(123'000); + aimd_rate_control.SetEstimate(kInitialBitrate, now); + aimd_rate_control.SetInApplicationLimitedRegion(false); + aimd_rate_control.Update({BandwidthUsage::kBwNormal, kInitialBitrate}, now); + for (int i = 0; i < 100; ++i) { + aimd_rate_control.Update({BandwidthUsage::kBwNormal, absl::nullopt}, now); + now += TimeDelta::Millis(100); + } + EXPECT_GT(aimd_rate_control.LatestEstimate(), kInitialBitrate); +} + +TEST(AimdRateControlTest, EstimateNotLimitedByNetworkEstimateIfDisabled) { + ExplicitKeyValueConfig field_trials( + "WebRTC-Bwe-EstimateBoundedIncrease/Disabled/"); + AimdRateControl aimd_rate_control(field_trials, /*send_side=*/true); + Timestamp now = kInitialTime; + constexpr DataRate kInitialBitrate = DataRate::BitsPerSec(123'000); + aimd_rate_control.SetEstimate(kInitialBitrate, now); + aimd_rate_control.SetInApplicationLimitedRegion(false); + NetworkStateEstimate network_estimate; + network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(150); + aimd_rate_control.SetNetworkStateEstimate(network_estimate); + + for (int i = 0; i < 100; ++i) { + aimd_rate_control.Update({BandwidthUsage::kBwNormal, absl::nullopt}, now); + now += TimeDelta::Millis(100); + } + EXPECT_GT(aimd_rate_control.LatestEstimate(), + network_estimate.link_capacity_upper); +} + +} // namespace webrtc |