• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 #include "modules/remote_bitrate_estimator/aimd_rate_control.h"
11 
12 #include <memory>
13 
14 #include "api/transport/field_trial_based_config.h"
15 #include "system_wrappers/include/clock.h"
16 #include "test/field_trial.h"
17 #include "test/gtest.h"
18 
19 namespace webrtc {
20 namespace {
21 
22 constexpr int64_t kClockInitialTime = 123456;
23 
24 constexpr int kMinBwePeriodMs = 2000;
25 constexpr int kDefaultPeriodMs = 3000;
26 constexpr int kMaxBwePeriodMs = 50000;
27 
28 // After an overuse, we back off to 85% to the received bitrate.
29 constexpr double kFractionAfterOveruse = 0.85;
30 
31 struct AimdRateControlStates {
32   std::unique_ptr<AimdRateControl> aimd_rate_control;
33   std::unique_ptr<SimulatedClock> simulated_clock;
34   FieldTrialBasedConfig field_trials;
35 };
36 
CreateAimdRateControlStates(bool send_side=false)37 AimdRateControlStates CreateAimdRateControlStates(bool send_side = false) {
38   AimdRateControlStates states;
39   states.aimd_rate_control.reset(
40       new AimdRateControl(&states.field_trials, send_side));
41   states.simulated_clock.reset(new SimulatedClock(kClockInitialTime));
42   return states;
43 }
OptionalRateFromOptionalBps(absl::optional<int> bitrate_bps)44 absl::optional<DataRate> OptionalRateFromOptionalBps(
45     absl::optional<int> bitrate_bps) {
46   if (bitrate_bps) {
47     return DataRate::BitsPerSec(*bitrate_bps);
48   } else {
49     return absl::nullopt;
50   }
51 }
UpdateRateControl(const AimdRateControlStates & states,const BandwidthUsage & bandwidth_usage,absl::optional<uint32_t> throughput_estimate,int64_t now_ms)52 void UpdateRateControl(const AimdRateControlStates& states,
53                        const BandwidthUsage& bandwidth_usage,
54                        absl::optional<uint32_t> throughput_estimate,
55                        int64_t now_ms) {
56   RateControlInput input(bandwidth_usage,
57                          OptionalRateFromOptionalBps(throughput_estimate));
58   states.aimd_rate_control->Update(&input, Timestamp::Millis(now_ms));
59 }
SetEstimate(const AimdRateControlStates & states,int bitrate_bps)60 void SetEstimate(const AimdRateControlStates& states, int bitrate_bps) {
61   states.aimd_rate_control->SetEstimate(DataRate::BitsPerSec(bitrate_bps),
62                                         states.simulated_clock->CurrentTime());
63 }
64 
65 }  // namespace
66 
TEST(AimdRateControlTest,MinNearMaxIncreaseRateOnLowBandwith)67 TEST(AimdRateControlTest, MinNearMaxIncreaseRateOnLowBandwith) {
68   auto states = CreateAimdRateControlStates();
69   constexpr int kBitrate = 30000;
70   SetEstimate(states, kBitrate);
71   EXPECT_EQ(4000,
72             states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond());
73 }
74 
TEST(AimdRateControlTest,NearMaxIncreaseRateIs5kbpsOn90kbpsAnd200msRtt)75 TEST(AimdRateControlTest, NearMaxIncreaseRateIs5kbpsOn90kbpsAnd200msRtt) {
76   auto states = CreateAimdRateControlStates();
77   constexpr int kBitrate = 90000;
78   SetEstimate(states, kBitrate);
79   EXPECT_EQ(5000,
80             states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond());
81 }
82 
TEST(AimdRateControlTest,NearMaxIncreaseRateIs5kbpsOn60kbpsAnd100msRtt)83 TEST(AimdRateControlTest, NearMaxIncreaseRateIs5kbpsOn60kbpsAnd100msRtt) {
84   auto states = CreateAimdRateControlStates();
85   constexpr int kBitrate = 60000;
86   SetEstimate(states, kBitrate);
87   states.aimd_rate_control->SetRtt(TimeDelta::Millis(100));
88   EXPECT_EQ(5000,
89             states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond());
90 }
91 
TEST(AimdRateControlTest,GetIncreaseRateAndBandwidthPeriod)92 TEST(AimdRateControlTest, GetIncreaseRateAndBandwidthPeriod) {
93   // Smoothing experiment disabled
94   auto states = CreateAimdRateControlStates();
95   constexpr int kBitrate = 300000;
96   SetEstimate(states, kBitrate);
97   UpdateRateControl(states, BandwidthUsage::kBwOverusing, kBitrate,
98                     states.simulated_clock->TimeInMilliseconds());
99   EXPECT_NEAR(14000,
100               states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond(),
101               1000);
102   EXPECT_EQ(kDefaultPeriodMs,
103             states.aimd_rate_control->GetExpectedBandwidthPeriod().ms());
104 }
105 
TEST(AimdRateControlTest,BweLimitedByAckedBitrate)106 TEST(AimdRateControlTest, BweLimitedByAckedBitrate) {
107   auto states = CreateAimdRateControlStates();
108   constexpr int kAckedBitrate = 10000;
109   SetEstimate(states, kAckedBitrate);
110   while (states.simulated_clock->TimeInMilliseconds() - kClockInitialTime <
111          20000) {
112     UpdateRateControl(states, BandwidthUsage::kBwNormal, kAckedBitrate,
113                       states.simulated_clock->TimeInMilliseconds());
114     states.simulated_clock->AdvanceTimeMilliseconds(100);
115   }
116   ASSERT_TRUE(states.aimd_rate_control->ValidEstimate());
117   EXPECT_EQ(static_cast<uint32_t>(1.5 * kAckedBitrate + 10000),
118             states.aimd_rate_control->LatestEstimate().bps());
119 }
120 
TEST(AimdRateControlTest,BweNotLimitedByDecreasingAckedBitrate)121 TEST(AimdRateControlTest, BweNotLimitedByDecreasingAckedBitrate) {
122   auto states = CreateAimdRateControlStates();
123   constexpr int kAckedBitrate = 100000;
124   SetEstimate(states, kAckedBitrate);
125   while (states.simulated_clock->TimeInMilliseconds() - kClockInitialTime <
126          20000) {
127     UpdateRateControl(states, BandwidthUsage::kBwNormal, kAckedBitrate,
128                       states.simulated_clock->TimeInMilliseconds());
129     states.simulated_clock->AdvanceTimeMilliseconds(100);
130   }
131   ASSERT_TRUE(states.aimd_rate_control->ValidEstimate());
132   // If the acked bitrate decreases the BWE shouldn't be reduced to 1.5x
133   // what's being acked, but also shouldn't get to increase more.
134   uint32_t prev_estimate = states.aimd_rate_control->LatestEstimate().bps();
135   UpdateRateControl(states, BandwidthUsage::kBwNormal, kAckedBitrate / 2,
136                     states.simulated_clock->TimeInMilliseconds());
137   uint32_t new_estimate = states.aimd_rate_control->LatestEstimate().bps();
138   EXPECT_NEAR(new_estimate, static_cast<uint32_t>(1.5 * kAckedBitrate + 10000),
139               2000);
140   EXPECT_EQ(new_estimate, prev_estimate);
141 }
142 
TEST(AimdRateControlTest,DefaultPeriodUntilFirstOveruse)143 TEST(AimdRateControlTest, DefaultPeriodUntilFirstOveruse) {
144   // Smoothing experiment disabled
145   auto states = CreateAimdRateControlStates();
146   states.aimd_rate_control->SetStartBitrate(DataRate::KilobitsPerSec(300));
147   EXPECT_EQ(kDefaultPeriodMs,
148             states.aimd_rate_control->GetExpectedBandwidthPeriod().ms());
149   states.simulated_clock->AdvanceTimeMilliseconds(100);
150   UpdateRateControl(states, BandwidthUsage::kBwOverusing, 280000,
151                     states.simulated_clock->TimeInMilliseconds());
152   EXPECT_NE(kDefaultPeriodMs,
153             states.aimd_rate_control->GetExpectedBandwidthPeriod().ms());
154 }
155 
TEST(AimdRateControlTest,ExpectedPeriodAfter20kbpsDropAnd5kbpsIncrease)156 TEST(AimdRateControlTest, ExpectedPeriodAfter20kbpsDropAnd5kbpsIncrease) {
157   auto states = CreateAimdRateControlStates();
158   constexpr int kInitialBitrate = 110000;
159   SetEstimate(states, kInitialBitrate);
160   states.simulated_clock->AdvanceTimeMilliseconds(100);
161   // Make the bitrate drop by 20 kbps to get to 90 kbps.
162   // The rate increase at 90 kbps should be 5 kbps, so the period should be 4 s.
163   constexpr int kAckedBitrate =
164       (kInitialBitrate - 20000) / kFractionAfterOveruse;
165   UpdateRateControl(states, BandwidthUsage::kBwOverusing, kAckedBitrate,
166                     states.simulated_clock->TimeInMilliseconds());
167   EXPECT_EQ(5000,
168             states.aimd_rate_control->GetNearMaxIncreaseRateBpsPerSecond());
169   EXPECT_EQ(4000, states.aimd_rate_control->GetExpectedBandwidthPeriod().ms());
170 }
171 
TEST(AimdRateControlTest,BandwidthPeriodIsNotBelowMin)172 TEST(AimdRateControlTest, BandwidthPeriodIsNotBelowMin) {
173   auto states = CreateAimdRateControlStates();
174   constexpr int kInitialBitrate = 10000;
175   SetEstimate(states, kInitialBitrate);
176   states.simulated_clock->AdvanceTimeMilliseconds(100);
177   // Make a small (1.5 kbps) bitrate drop to 8.5 kbps.
178   UpdateRateControl(states, BandwidthUsage::kBwOverusing, kInitialBitrate - 1,
179                     states.simulated_clock->TimeInMilliseconds());
180   EXPECT_EQ(kMinBwePeriodMs,
181             states.aimd_rate_control->GetExpectedBandwidthPeriod().ms());
182 }
183 
TEST(AimdRateControlTest,BandwidthPeriodIsNotAboveMaxNoSmoothingExp)184 TEST(AimdRateControlTest, BandwidthPeriodIsNotAboveMaxNoSmoothingExp) {
185   auto states = CreateAimdRateControlStates();
186   constexpr int kInitialBitrate = 10010000;
187   SetEstimate(states, kInitialBitrate);
188   states.simulated_clock->AdvanceTimeMilliseconds(100);
189   // Make a large (10 Mbps) bitrate drop to 10 kbps.
190   constexpr int kAckedBitrate = 10000 / kFractionAfterOveruse;
191   UpdateRateControl(states, BandwidthUsage::kBwOverusing, kAckedBitrate,
192                     states.simulated_clock->TimeInMilliseconds());
193   EXPECT_EQ(kMaxBwePeriodMs,
194             states.aimd_rate_control->GetExpectedBandwidthPeriod().ms());
195 }
196 
TEST(AimdRateControlTest,SendingRateBoundedWhenThroughputNotEstimated)197 TEST(AimdRateControlTest, SendingRateBoundedWhenThroughputNotEstimated) {
198   auto states = CreateAimdRateControlStates();
199   constexpr int kInitialBitrateBps = 123000;
200   UpdateRateControl(states, BandwidthUsage::kBwNormal, kInitialBitrateBps,
201                     states.simulated_clock->TimeInMilliseconds());
202   // AimdRateControl sets the initial bit rate to what it receives after
203   // five seconds has passed.
204   // TODO(bugs.webrtc.org/9379): The comment in the AimdRateControl does not
205   // match the constant.
206   constexpr int kInitializationTimeMs = 5000;
207   states.simulated_clock->AdvanceTimeMilliseconds(kInitializationTimeMs + 1);
208   UpdateRateControl(states, BandwidthUsage::kBwNormal, kInitialBitrateBps,
209                     states.simulated_clock->TimeInMilliseconds());
210   for (int i = 0; i < 100; ++i) {
211     UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt,
212                       states.simulated_clock->TimeInMilliseconds());
213     states.simulated_clock->AdvanceTimeMilliseconds(100);
214   }
215   EXPECT_LE(states.aimd_rate_control->LatestEstimate().bps(),
216             kInitialBitrateBps * 1.5 + 10000);
217 }
218 
TEST(AimdRateControlTest,EstimateDoesNotIncreaseInAlr)219 TEST(AimdRateControlTest, EstimateDoesNotIncreaseInAlr) {
220   // When alr is detected, the delay based estimator is not allowed to increase
221   // bwe since there will be no feedback from the network if the new estimate
222   // is correct.
223   test::ScopedFieldTrials override_field_trials(
224       "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/");
225   auto states = CreateAimdRateControlStates(/*send_side=*/true);
226   constexpr int kInitialBitrateBps = 123000;
227   SetEstimate(states, kInitialBitrateBps);
228   states.aimd_rate_control->SetInApplicationLimitedRegion(true);
229   UpdateRateControl(states, BandwidthUsage::kBwNormal, kInitialBitrateBps,
230                     states.simulated_clock->TimeInMilliseconds());
231   ASSERT_EQ(states.aimd_rate_control->LatestEstimate().bps(),
232             kInitialBitrateBps);
233 
234   for (int i = 0; i < 100; ++i) {
235     UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt,
236                       states.simulated_clock->TimeInMilliseconds());
237     states.simulated_clock->AdvanceTimeMilliseconds(100);
238   }
239   EXPECT_EQ(states.aimd_rate_control->LatestEstimate().bps(),
240             kInitialBitrateBps);
241 }
242 
TEST(AimdRateControlTest,SetEstimateIncreaseBweInAlr)243 TEST(AimdRateControlTest, SetEstimateIncreaseBweInAlr) {
244   test::ScopedFieldTrials override_field_trials(
245       "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/");
246   auto states = CreateAimdRateControlStates(/*send_side=*/true);
247   constexpr int kInitialBitrateBps = 123000;
248   SetEstimate(states, kInitialBitrateBps);
249   states.aimd_rate_control->SetInApplicationLimitedRegion(true);
250   ASSERT_EQ(states.aimd_rate_control->LatestEstimate().bps(),
251             kInitialBitrateBps);
252   SetEstimate(states, 2 * kInitialBitrateBps);
253   EXPECT_EQ(states.aimd_rate_control->LatestEstimate().bps(),
254             2 * kInitialBitrateBps);
255 }
256 
TEST(AimdRateControlTest,EstimateIncreaseWhileNotInAlr)257 TEST(AimdRateControlTest, EstimateIncreaseWhileNotInAlr) {
258   // Allow the estimate to increase as long as alr is not detected to ensure
259   // tha BWE can not get stuck at a certain bitrate.
260   test::ScopedFieldTrials override_field_trials(
261       "WebRTC-DontIncreaseDelayBasedBweInAlr/Enabled/");
262   auto states = CreateAimdRateControlStates(/*send_side=*/true);
263   constexpr int kInitialBitrateBps = 123000;
264   SetEstimate(states, kInitialBitrateBps);
265   states.aimd_rate_control->SetInApplicationLimitedRegion(false);
266   UpdateRateControl(states, BandwidthUsage::kBwNormal, kInitialBitrateBps,
267                     states.simulated_clock->TimeInMilliseconds());
268   for (int i = 0; i < 100; ++i) {
269     UpdateRateControl(states, BandwidthUsage::kBwNormal, absl::nullopt,
270                       states.simulated_clock->TimeInMilliseconds());
271     states.simulated_clock->AdvanceTimeMilliseconds(100);
272   }
273   EXPECT_GT(states.aimd_rate_control->LatestEstimate().bps(),
274             kInitialBitrateBps);
275 }
276 
277 }  // namespace webrtc
278