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