|  | /* | 
|  | *  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 <memory> | 
|  |  | 
|  | #include "api/transport/field_trial_based_config.h" | 
|  | #include "api/units/data_rate.h" | 
|  | #include "system_wrappers/include/clock.h" | 
|  | #include "test/field_trial.h" | 
|  | #include "test/gtest.h" | 
|  |  | 
|  | namespace webrtc { | 
|  | namespace { | 
|  |  | 
|  | constexpr int64_t kClockInitialTime = 123456; | 
|  |  | 
|  | constexpr int kMinBwePeriodMs = 2000; | 
|  | constexpr int kDefaultPeriodMs = 3000; | 
|  | constexpr int kMaxBwePeriodMs = 50000; | 
|  |  | 
|  | // After an overuse, we back off to 85% to the received bitrate. | 
|  | constexpr double kFractionAfterOveruse = 0.85; | 
|  |  | 
|  | struct AimdRateControlStates { | 
|  | std::unique_ptr<AimdRateControl> aimd_rate_control; | 
|  | std::unique_ptr<SimulatedClock> simulated_clock; | 
|  | FieldTrialBasedConfig field_trials; | 
|  | }; | 
|  |  | 
|  | AimdRateControlStates CreateAimdRateControlStates(bool send_side = false) { | 
|  | AimdRateControlStates states; | 
|  | states.aimd_rate_control.reset( | 
|  | new AimdRateControl(&states.field_trials, send_side)); | 
|  | states.simulated_clock.reset(new SimulatedClock(kClockInitialTime)); | 
|  | return states; | 
|  | } | 
|  | absl::optional<DataRate> OptionalRateFromOptionalBps( | 
|  | absl::optional<int> bitrate_bps) { | 
|  | if (bitrate_bps) { | 
|  | return DataRate::BitsPerSec(*bitrate_bps); | 
|  | } else { | 
|  | return absl::nullopt; | 
|  | } | 
|  | } | 
|  | void UpdateRateControl(const AimdRateControlStates& states, | 
|  | const BandwidthUsage& bandwidth_usage, | 
|  | absl::optional<uint32_t> throughput_estimate, | 
|  | int64_t now_ms) { | 
|  | RateControlInput input(bandwidth_usage, | 
|  | OptionalRateFromOptionalBps(throughput_estimate)); | 
|  | states.aimd_rate_control->Update(&input, Timestamp::Millis(now_ms)); | 
|  | } | 
|  | void SetEstimate(const AimdRateControlStates& states, int bitrate_bps) { | 
|  | states.aimd_rate_control->SetEstimate(DataRate::BitsPerSec(bitrate_bps), | 
|  | states.simulated_clock->CurrentTime()); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | TEST(AimdRateControlTest, MinNearMaxIncreaseRateOnLowBandwith) { | 
|  | auto states = CreateAimdRateControlStates(); | 
|  | constexpr int kBitrate = 30000; | 
|  | SetEstimate(states, kBitrate); | 
|  | EXPECT_EQ(4000, | 
|  | states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond()); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, NearMaxIncreaseRateIs5kbpsOn90kbpsAnd200msRtt) { | 
|  | auto states = CreateAimdRateControlStates(); | 
|  | constexpr int kBitrate = 90000; | 
|  | SetEstimate(states, kBitrate); | 
|  | EXPECT_EQ(5000, | 
|  | states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond()); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, NearMaxIncreaseRateIs5kbpsOn60kbpsAnd100msRtt) { | 
|  | auto states = CreateAimdRateControlStates(); | 
|  | constexpr int kBitrate = 60000; | 
|  | SetEstimate(states, kBitrate); | 
|  | states.aimd_rate_control->SetRtt(TimeDelta::Millis(100)); | 
|  | EXPECT_EQ(5000, | 
|  | states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond()); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, GetIncreaseRateAndBandwidthPeriod) { | 
|  | // Smoothing experiment disabled | 
|  | auto states = CreateAimdRateControlStates(); | 
|  | constexpr int kBitrate = 300000; | 
|  | SetEstimate(states, kBitrate); | 
|  | UpdateRateControl(states, BandwidthUsage::kBwOverusing, kBitrate, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | EXPECT_NEAR(14000, | 
|  | states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond(), | 
|  | 1000); | 
|  | EXPECT_EQ(kDefaultPeriodMs, | 
|  | states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, BweLimitedByAckedBitrate) { | 
|  | auto states = CreateAimdRateControlStates(); | 
|  | constexpr int kAckedBitrate = 10000; | 
|  | SetEstimate(states, kAckedBitrate); | 
|  | while (states.simulated_clock->TimeInMilliseconds() - kClockInitialTime < | 
|  | 20000) { | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, kAckedBitrate, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | } | 
|  | ASSERT_TRUE(states.aimd_rate_control->ValidEstimate()); | 
|  | EXPECT_EQ(static_cast<uint32_t>(1.5 * kAckedBitrate + 10000), | 
|  | states.aimd_rate_control->LatestEstimate().bps()); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, BweNotLimitedByDecreasingAckedBitrate) { | 
|  | auto states = CreateAimdRateControlStates(); | 
|  | constexpr int kAckedBitrate = 100000; | 
|  | SetEstimate(states, kAckedBitrate); | 
|  | while (states.simulated_clock->TimeInMilliseconds() - kClockInitialTime < | 
|  | 20000) { | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, kAckedBitrate, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | } | 
|  | ASSERT_TRUE(states.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. | 
|  | uint32_t prev_estimate = states.aimd_rate_control->LatestEstimate().bps(); | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, kAckedBitrate / 2, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | uint32_t new_estimate = states.aimd_rate_control->LatestEstimate().bps(); | 
|  | EXPECT_NEAR(new_estimate, static_cast<uint32_t>(1.5 * kAckedBitrate + 10000), | 
|  | 2000); | 
|  | EXPECT_EQ(new_estimate, prev_estimate); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, DefaultPeriodUntilFirstOveruse) { | 
|  | // Smoothing experiment disabled | 
|  | auto states = CreateAimdRateControlStates(); | 
|  | states.aimd_rate_control->SetStartBitrate(DataRate::KilobitsPerSec(300)); | 
|  | EXPECT_EQ(kDefaultPeriodMs, | 
|  | states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | UpdateRateControl(states, BandwidthUsage::kBwOverusing, 280000, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | EXPECT_NE(kDefaultPeriodMs, | 
|  | states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, ExpectedPeriodAfter20kbpsDropAnd5kbpsIncrease) { | 
|  | auto states = CreateAimdRateControlStates(); | 
|  | constexpr int kInitialBitrate = 110000; | 
|  | SetEstimate(states, kInitialBitrate); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | // Make the bitrate drop by 20 kbps to get to 90 kbps. | 
|  | // The rate increase at 90 kbps should be 5 kbps, so the period should be 4 s. | 
|  | constexpr int kAckedBitrate = | 
|  | (kInitialBitrate - 20000) / kFractionAfterOveruse; | 
|  | UpdateRateControl(states, BandwidthUsage::kBwOverusing, kAckedBitrate, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | EXPECT_EQ(5000, | 
|  | states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond()); | 
|  | EXPECT_EQ(4000, states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, BandwidthPeriodIsNotBelowMin) { | 
|  | auto states = CreateAimdRateControlStates(); | 
|  | constexpr int kInitialBitrate = 10000; | 
|  | SetEstimate(states, kInitialBitrate); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | // 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, | 
|  | states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, BandwidthPeriodIsNotAboveMaxNoSmoothingExp) { | 
|  | auto states = CreateAimdRateControlStates(); | 
|  | constexpr int kInitialBitrate = 10010000; | 
|  | SetEstimate(states, kInitialBitrate); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | // Make a large (10 Mbps) bitrate drop to 10 kbps. | 
|  | constexpr int kAckedBitrate = 10000 / kFractionAfterOveruse; | 
|  | UpdateRateControl(states, BandwidthUsage::kBwOverusing, kAckedBitrate, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | EXPECT_EQ(kMaxBwePeriodMs, | 
|  | states.aimd_rate_control->GetExpectedBandwidthPeriod().ms()); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, SendingRateBoundedWhenThroughputNotEstimated) { | 
|  | auto states = CreateAimdRateControlStates(); | 
|  | constexpr int kInitialBitrateBps = 123000; | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, kInitialBitrateBps, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | // 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 int kInitializationTimeMs = 5000; | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(kInitializationTimeMs + 1); | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, kInitialBitrateBps, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | for (int i = 0; i < 100; ++i) { | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | } | 
|  | EXPECT_LE(states.aimd_rate_control->LatestEstimate().bps(), | 
|  | kInitialBitrateBps * 1.5 + 10000); | 
|  | } | 
|  |  | 
|  | 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. | 
|  | test::ScopedFieldTrials override_field_trials( | 
|  | "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/"); | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | constexpr int kInitialBitrateBps = 123000; | 
|  | SetEstimate(states, kInitialBitrateBps); | 
|  | states.aimd_rate_control->SetInApplicationLimitedRegion(true); | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, kInitialBitrateBps, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | ASSERT_EQ(states.aimd_rate_control->LatestEstimate().bps(), | 
|  | kInitialBitrateBps); | 
|  |  | 
|  | for (int i = 0; i < 100; ++i) { | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | } | 
|  | EXPECT_EQ(states.aimd_rate_control->LatestEstimate().bps(), | 
|  | kInitialBitrateBps); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, SetEstimateIncreaseBweInAlr) { | 
|  | test::ScopedFieldTrials override_field_trials( | 
|  | "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/"); | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | constexpr int kInitialBitrateBps = 123000; | 
|  | SetEstimate(states, kInitialBitrateBps); | 
|  | states.aimd_rate_control->SetInApplicationLimitedRegion(true); | 
|  | ASSERT_EQ(states.aimd_rate_control->LatestEstimate().bps(), | 
|  | kInitialBitrateBps); | 
|  | SetEstimate(states, 2 * kInitialBitrateBps); | 
|  | EXPECT_EQ(states.aimd_rate_control->LatestEstimate().bps(), | 
|  | 2 * kInitialBitrateBps); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, SetEstimateUpperLimitedByNetworkEstimate) { | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | NetworkStateEstimate network_estimate; | 
|  | network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(400); | 
|  | states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); | 
|  | SetEstimate(states, 500'000); | 
|  | EXPECT_EQ(states.aimd_rate_control->LatestEstimate(), | 
|  | network_estimate.link_capacity_upper); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, SetEstimateLowerLimitedByNetworkEstimate) { | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | NetworkStateEstimate network_estimate; | 
|  | network_estimate.link_capacity_lower = DataRate::KilobitsPerSec(400); | 
|  | states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); | 
|  | SetEstimate(states, 100'000); | 
|  | // 0.85 is default backoff factor. (`beta_`) | 
|  | EXPECT_EQ(states.aimd_rate_control->LatestEstimate(), | 
|  | network_estimate.link_capacity_lower * 0.85); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, | 
|  | SetEstimateIgnoredIfLowerThanNetworkEstimateAndCurrent) { | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | SetEstimate(states, 200'000); | 
|  | ASSERT_EQ(states.aimd_rate_control->LatestEstimate().kbps(), 200); | 
|  | NetworkStateEstimate network_estimate; | 
|  | network_estimate.link_capacity_lower = DataRate::KilobitsPerSec(400); | 
|  | states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); | 
|  | // Ignore the next SetEstimate, since the estimate is lower than 85% of | 
|  | // the network estimate. | 
|  | SetEstimate(states, 100'000); | 
|  | EXPECT_EQ(states.aimd_rate_control->LatestEstimate().kbps(), 200); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, SetEstimateIgnoresNetworkEstimatesLowerThanCurrent) { | 
|  | test::ScopedFieldTrials override_field_trials( | 
|  | "WebRTC-Bwe-EstimateBoundedIncrease/" | 
|  | "ratio:0.85,ignore_acked:true,ignore_decr:true/"); | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | states.aimd_rate_control->SetStartBitrate(DataRate::KilobitsPerSec(30)); | 
|  | NetworkStateEstimate network_estimate; | 
|  | network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(400); | 
|  | states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); | 
|  | SetEstimate(states, 500'000); | 
|  | ASSERT_EQ(states.aimd_rate_control->LatestEstimate(), | 
|  | network_estimate.link_capacity_upper * 0.85); | 
|  |  | 
|  | NetworkStateEstimate lower_network_estimate; | 
|  | lower_network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(300); | 
|  | states.aimd_rate_control->SetNetworkStateEstimate(lower_network_estimate); | 
|  | SetEstimate(states, 500'000); | 
|  | EXPECT_EQ(states.aimd_rate_control->LatestEstimate(), | 
|  | network_estimate.link_capacity_upper * 0.85); | 
|  | } | 
|  |  | 
|  | 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. | 
|  | test::ScopedFieldTrials override_field_trials( | 
|  | "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/"); | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | constexpr int kInitialBitrateBps = 123000; | 
|  | SetEstimate(states, kInitialBitrateBps); | 
|  | states.aimd_rate_control->SetInApplicationLimitedRegion(false); | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, kInitialBitrateBps, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | for (int i = 0; i < 100; ++i) { | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | } | 
|  | EXPECT_GT(states.aimd_rate_control->LatestEstimate().bps(), | 
|  | kInitialBitrateBps); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, EstimateNotLimitedByNetworkEstimateIfDisabled) { | 
|  | test::ScopedFieldTrials override_field_trials( | 
|  | "WebRTC-Bwe-EstimateBoundedIncrease/Disabled/"); | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | constexpr int kInitialBitrateBps = 123000; | 
|  | SetEstimate(states, kInitialBitrateBps); | 
|  | states.aimd_rate_control->SetInApplicationLimitedRegion(false); | 
|  | NetworkStateEstimate network_estimate; | 
|  | network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(150); | 
|  | states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); | 
|  |  | 
|  | for (int i = 0; i < 100; ++i) { | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | } | 
|  | EXPECT_GT(states.aimd_rate_control->LatestEstimate(), | 
|  | network_estimate.link_capacity_upper); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, | 
|  | EstimateSlowlyIncreaseToUpperLinkCapacityEstimateIfConfigured) { | 
|  | // Even if alr is detected, the delay based estimator is allowed to increase | 
|  | // up to a percentage of upper link capacity. | 
|  | test::ScopedFieldTrials override_field_trials( | 
|  | "WebRTC-Bwe-EstimateBoundedIncrease/" | 
|  | "ratio:0.85,ignore_acked:true,immediate_incr:false/" | 
|  | "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/"); | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | constexpr int kInitialBitrateBps = 123000; | 
|  | SetEstimate(states, kInitialBitrateBps); | 
|  | states.aimd_rate_control->SetInApplicationLimitedRegion(true); | 
|  |  | 
|  | NetworkStateEstimate network_estimate; | 
|  | network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(200); | 
|  | states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); | 
|  | for (int i = 0; i < 10; ++i) { | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | EXPECT_LT(states.aimd_rate_control->LatestEstimate(), | 
|  | network_estimate.link_capacity_upper * 0.85); | 
|  | } | 
|  | for (int i = 0; i < 50; ++i) { | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | } | 
|  | EXPECT_EQ(states.aimd_rate_control->LatestEstimate(), | 
|  | network_estimate.link_capacity_upper * 0.85); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, | 
|  | EstimateImmediatelyIncreaseToUpperLinkCapacityEstimateIfConfigured) { | 
|  | // Even if alr is detected, the delay based estimator is allowed to increase | 
|  | // up to a percentage of upper link capacity. | 
|  | test::ScopedFieldTrials override_field_trials( | 
|  | "WebRTC-Bwe-EstimateBoundedIncrease/" | 
|  | "ratio:0.85,ignore_acked:true,immediate_incr:true/" | 
|  | "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/"); | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | constexpr int kInitialBitrateBps = 123000; | 
|  | SetEstimate(states, kInitialBitrateBps); | 
|  | states.aimd_rate_control->SetInApplicationLimitedRegion(true); | 
|  |  | 
|  | NetworkStateEstimate network_estimate; | 
|  | network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(200); | 
|  | states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | EXPECT_EQ(states.aimd_rate_control->LatestEstimate(), | 
|  | network_estimate.link_capacity_upper * 0.85); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, EstimateNotLoweredByNetworkEstimate) { | 
|  | // The delay based estimator is allowed to increase up to a percentage of | 
|  | // upper link capacity but does not decrease unless the delay detector | 
|  | // discover an overuse. | 
|  | test::ScopedFieldTrials override_field_trials( | 
|  | "WebRTC-Bwe-EstimateBoundedIncrease/" | 
|  | "ratio:0.85,ignore_acked:true,ignore_decr:true/" | 
|  | "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/"); | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | constexpr int kInitialBitrateBps = 123000; | 
|  | constexpr int kEstimatedThroughputBps = 30'000; | 
|  | SetEstimate(states, kInitialBitrateBps); | 
|  |  | 
|  | NetworkStateEstimate network_estimate; | 
|  | network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(200); | 
|  | states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); | 
|  | for (int i = 0; i < 100; ++i) { | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, | 
|  | kEstimatedThroughputBps, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | } | 
|  | DataRate estimate_after_increase = states.aimd_rate_control->LatestEstimate(); | 
|  | ASSERT_EQ(estimate_after_increase, | 
|  | network_estimate.link_capacity_upper * 0.85); | 
|  |  | 
|  | // A lower network estimate does not decrease the estimate immediately, | 
|  | // but the estimate is not allowed to increase. | 
|  | network_estimate.link_capacity_upper = DataRate::KilobitsPerSec(100); | 
|  | network_estimate.link_capacity_lower = DataRate::KilobitsPerSec(80); | 
|  | states.aimd_rate_control->SetNetworkStateEstimate(network_estimate); | 
|  | for (int i = 0; i < 10; ++i) { | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, | 
|  | kEstimatedThroughputBps, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | EXPECT_EQ(states.aimd_rate_control->LatestEstimate(), | 
|  | estimate_after_increase); | 
|  | } | 
|  |  | 
|  | // If the detector detects and overuse, BWE drops to a value relative the | 
|  | // network estimate. | 
|  | UpdateRateControl(states, BandwidthUsage::kBwOverusing, | 
|  | kEstimatedThroughputBps, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | EXPECT_LT(states.aimd_rate_control->LatestEstimate(), | 
|  | network_estimate.link_capacity_lower); | 
|  | EXPECT_GT(states.aimd_rate_control->LatestEstimate().bps(), | 
|  | kEstimatedThroughputBps); | 
|  | } | 
|  |  | 
|  | TEST(AimdRateControlTest, EstimateDoesNotIncreaseInAlrIfNetworkEstimateNotSet) { | 
|  | // 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. | 
|  | test::ScopedFieldTrials override_field_trials( | 
|  | "WebRTC-Bwe-EstimateBoundedIncrease/ratio:0.85,ignore_acked:true/" | 
|  | "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/"); | 
|  | auto states = CreateAimdRateControlStates(/*send_side=*/true); | 
|  | constexpr int kInitialBitrateBps = 123000; | 
|  | SetEstimate(states, kInitialBitrateBps); | 
|  | states.aimd_rate_control->SetInApplicationLimitedRegion(true); | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, kInitialBitrateBps, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | ASSERT_EQ(states.aimd_rate_control->LatestEstimate().bps(), | 
|  | kInitialBitrateBps); | 
|  |  | 
|  | for (int i = 0; i < 100; ++i) { | 
|  | UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt, | 
|  | states.simulated_clock->TimeInMilliseconds()); | 
|  | states.simulated_clock->AdvanceTimeMilliseconds(100); | 
|  | } | 
|  | EXPECT_EQ(states.aimd_rate_control->LatestEstimate().bps(), | 
|  | kInitialBitrateBps); | 
|  | } | 
|  |  | 
|  | }  // namespace webrtc |