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
11 #include "modules/congestion_controller/goog_cc/delay_based_bwe.h"
12
13 #include <string>
14
15 #include "api/transport/network_types.h"
16 #include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h"
17 #include "modules/congestion_controller/goog_cc/delay_based_bwe_unittest_helper.h"
18 #include "system_wrappers/include/clock.h"
19 #include "test/gtest.h"
20
21 namespace webrtc {
22
23 namespace {
24 constexpr int kNumProbesCluster0 = 5;
25 constexpr int kNumProbesCluster1 = 8;
26 const PacedPacketInfo kPacingInfo0(0, kNumProbesCluster0, 2000);
27 const PacedPacketInfo kPacingInfo1(1, kNumProbesCluster1, 4000);
28 constexpr float kTargetUtilizationFraction = 0.95f;
29 } // namespace
30
TEST_F(DelayBasedBweTest,ProbeDetection)31 TEST_F(DelayBasedBweTest, ProbeDetection) {
32 int64_t now_ms = clock_.TimeInMilliseconds();
33
34 // First burst sent at 8 * 1000 / 10 = 800 kbps.
35 for (int i = 0; i < kNumProbesCluster0; ++i) {
36 clock_.AdvanceTimeMilliseconds(10);
37 now_ms = clock_.TimeInMilliseconds();
38 IncomingFeedback(now_ms, now_ms, 1000, kPacingInfo0);
39 }
40 EXPECT_TRUE(bitrate_observer_.updated());
41
42 // Second burst sent at 8 * 1000 / 5 = 1600 kbps.
43 for (int i = 0; i < kNumProbesCluster1; ++i) {
44 clock_.AdvanceTimeMilliseconds(5);
45 now_ms = clock_.TimeInMilliseconds();
46 IncomingFeedback(now_ms, now_ms, 1000, kPacingInfo1);
47 }
48
49 EXPECT_TRUE(bitrate_observer_.updated());
50 EXPECT_GT(bitrate_observer_.latest_bitrate(), 1500000u);
51 }
52
TEST_F(DelayBasedBweTest,ProbeDetectionNonPacedPackets)53 TEST_F(DelayBasedBweTest, ProbeDetectionNonPacedPackets) {
54 int64_t now_ms = clock_.TimeInMilliseconds();
55 // First burst sent at 8 * 1000 / 10 = 800 kbps, but with every other packet
56 // not being paced which could mess things up.
57 for (int i = 0; i < kNumProbesCluster0; ++i) {
58 clock_.AdvanceTimeMilliseconds(5);
59 now_ms = clock_.TimeInMilliseconds();
60 IncomingFeedback(now_ms, now_ms, 1000, kPacingInfo0);
61 // Non-paced packet, arriving 5 ms after.
62 clock_.AdvanceTimeMilliseconds(5);
63 IncomingFeedback(now_ms, now_ms, 100, PacedPacketInfo());
64 }
65
66 EXPECT_TRUE(bitrate_observer_.updated());
67 EXPECT_GT(bitrate_observer_.latest_bitrate(), 800000u);
68 }
69
TEST_F(DelayBasedBweTest,ProbeDetectionFasterArrival)70 TEST_F(DelayBasedBweTest, ProbeDetectionFasterArrival) {
71 int64_t now_ms = clock_.TimeInMilliseconds();
72 // First burst sent at 8 * 1000 / 10 = 800 kbps.
73 // Arriving at 8 * 1000 / 5 = 1600 kbps.
74 int64_t send_time_ms = 0;
75 for (int i = 0; i < kNumProbesCluster0; ++i) {
76 clock_.AdvanceTimeMilliseconds(1);
77 send_time_ms += 10;
78 now_ms = clock_.TimeInMilliseconds();
79 IncomingFeedback(now_ms, send_time_ms, 1000, kPacingInfo0);
80 }
81
82 EXPECT_FALSE(bitrate_observer_.updated());
83 }
84
TEST_F(DelayBasedBweTest,ProbeDetectionSlowerArrival)85 TEST_F(DelayBasedBweTest, ProbeDetectionSlowerArrival) {
86 int64_t now_ms = clock_.TimeInMilliseconds();
87 // First burst sent at 8 * 1000 / 5 = 1600 kbps.
88 // Arriving at 8 * 1000 / 7 = 1142 kbps.
89 // Since the receive rate is significantly below the send rate, we expect to
90 // use 95% of the estimated capacity.
91 int64_t send_time_ms = 0;
92 for (int i = 0; i < kNumProbesCluster1; ++i) {
93 clock_.AdvanceTimeMilliseconds(7);
94 send_time_ms += 5;
95 now_ms = clock_.TimeInMilliseconds();
96 IncomingFeedback(now_ms, send_time_ms, 1000, kPacingInfo1);
97 }
98
99 EXPECT_TRUE(bitrate_observer_.updated());
100 EXPECT_NEAR(bitrate_observer_.latest_bitrate(),
101 kTargetUtilizationFraction * 1140000u, 10000u);
102 }
103
TEST_F(DelayBasedBweTest,ProbeDetectionSlowerArrivalHighBitrate)104 TEST_F(DelayBasedBweTest, ProbeDetectionSlowerArrivalHighBitrate) {
105 int64_t now_ms = clock_.TimeInMilliseconds();
106 // Burst sent at 8 * 1000 / 1 = 8000 kbps.
107 // Arriving at 8 * 1000 / 2 = 4000 kbps.
108 // Since the receive rate is significantly below the send rate, we expect to
109 // use 95% of the estimated capacity.
110 int64_t send_time_ms = 0;
111 for (int i = 0; i < kNumProbesCluster1; ++i) {
112 clock_.AdvanceTimeMilliseconds(2);
113 send_time_ms += 1;
114 now_ms = clock_.TimeInMilliseconds();
115 IncomingFeedback(now_ms, send_time_ms, 1000, kPacingInfo1);
116 }
117
118 EXPECT_TRUE(bitrate_observer_.updated());
119 EXPECT_NEAR(bitrate_observer_.latest_bitrate(),
120 kTargetUtilizationFraction * 4000000u, 10000u);
121 }
122
TEST_F(DelayBasedBweTest,GetExpectedBwePeriodMs)123 TEST_F(DelayBasedBweTest, GetExpectedBwePeriodMs) {
124 auto default_interval = bitrate_estimator_->GetExpectedBwePeriod();
125 EXPECT_GT(default_interval.ms(), 0);
126 CapacityDropTestHelper(1, true, 333, 0);
127 auto interval = bitrate_estimator_->GetExpectedBwePeriod();
128 EXPECT_GT(interval.ms(), 0);
129 EXPECT_NE(interval.ms(), default_interval.ms());
130 }
131
TEST_F(DelayBasedBweTest,InitialBehavior)132 TEST_F(DelayBasedBweTest, InitialBehavior) {
133 InitialBehaviorTestHelper(730000);
134 }
135
TEST_F(DelayBasedBweTest,RateIncreaseReordering)136 TEST_F(DelayBasedBweTest, RateIncreaseReordering) {
137 RateIncreaseReorderingTestHelper(730000);
138 }
TEST_F(DelayBasedBweTest,RateIncreaseRtpTimestamps)139 TEST_F(DelayBasedBweTest, RateIncreaseRtpTimestamps) {
140 RateIncreaseRtpTimestampsTestHelper(622);
141 }
142
TEST_F(DelayBasedBweTest,CapacityDropOneStream)143 TEST_F(DelayBasedBweTest, CapacityDropOneStream) {
144 CapacityDropTestHelper(1, false, 300, 0);
145 }
146
TEST_F(DelayBasedBweTest,CapacityDropPosOffsetChange)147 TEST_F(DelayBasedBweTest, CapacityDropPosOffsetChange) {
148 CapacityDropTestHelper(1, false, 867, 30000);
149 }
150
TEST_F(DelayBasedBweTest,CapacityDropNegOffsetChange)151 TEST_F(DelayBasedBweTest, CapacityDropNegOffsetChange) {
152 CapacityDropTestHelper(1, false, 933, -30000);
153 }
154
TEST_F(DelayBasedBweTest,CapacityDropOneStreamWrap)155 TEST_F(DelayBasedBweTest, CapacityDropOneStreamWrap) {
156 CapacityDropTestHelper(1, true, 333, 0);
157 }
158
TEST_F(DelayBasedBweTest,TestTimestampGrouping)159 TEST_F(DelayBasedBweTest, TestTimestampGrouping) {
160 TestTimestampGroupingTestHelper();
161 }
162
TEST_F(DelayBasedBweTest,TestShortTimeoutAndWrap)163 TEST_F(DelayBasedBweTest, TestShortTimeoutAndWrap) {
164 // Simulate a client leaving and rejoining the call after 35 seconds. This
165 // will make abs send time wrap, so if streams aren't timed out properly
166 // the next 30 seconds of packets will be out of order.
167 TestWrappingHelper(35);
168 }
169
TEST_F(DelayBasedBweTest,TestLongTimeoutAndWrap)170 TEST_F(DelayBasedBweTest, TestLongTimeoutAndWrap) {
171 // Simulate a client leaving and rejoining the call after some multiple of
172 // 64 seconds later. This will cause a zero difference in abs send times due
173 // to the wrap, but a big difference in arrival time, if streams aren't
174 // properly timed out.
175 TestWrappingHelper(10 * 64);
176 }
177
TEST_F(DelayBasedBweTest,TestInitialOveruse)178 TEST_F(DelayBasedBweTest, TestInitialOveruse) {
179 const DataRate kStartBitrate = DataRate::KilobitsPerSec(300);
180 const DataRate kInitialCapacity = DataRate::KilobitsPerSec(200);
181 const uint32_t kDummySsrc = 0;
182 // High FPS to ensure that we send a lot of packets in a short time.
183 const int kFps = 90;
184
185 stream_generator_->AddStream(new test::RtpStream(kFps, kStartBitrate.bps()));
186 stream_generator_->set_capacity_bps(kInitialCapacity.bps());
187
188 // Needed to initialize the AimdRateControl.
189 bitrate_estimator_->SetStartBitrate(kStartBitrate);
190
191 // Produce 30 frames (in 1/3 second) and give them to the estimator.
192 int64_t bitrate_bps = kStartBitrate.bps();
193 bool seen_overuse = false;
194 for (int i = 0; i < 30; ++i) {
195 bool overuse = GenerateAndProcessFrame(kDummySsrc, bitrate_bps);
196 // The purpose of this test is to ensure that we back down even if we don't
197 // have any acknowledged bitrate estimate yet. Hence, if the test works
198 // as expected, we should not have a measured bitrate yet.
199 EXPECT_FALSE(acknowledged_bitrate_estimator_->bitrate().has_value());
200 if (overuse) {
201 EXPECT_TRUE(bitrate_observer_.updated());
202 EXPECT_NEAR(bitrate_observer_.latest_bitrate(), kStartBitrate.bps() / 2,
203 15000);
204 bitrate_bps = bitrate_observer_.latest_bitrate();
205 seen_overuse = true;
206 break;
207 } else if (bitrate_observer_.updated()) {
208 bitrate_bps = bitrate_observer_.latest_bitrate();
209 bitrate_observer_.Reset();
210 }
211 }
212 EXPECT_TRUE(seen_overuse);
213 EXPECT_NEAR(bitrate_observer_.latest_bitrate(), kStartBitrate.bps() / 2,
214 15000);
215 }
216
TEST_F(DelayBasedBweTest,TestTimestampPrecisionHandling)217 TEST_F(DelayBasedBweTest, TestTimestampPrecisionHandling) {
218 // This test does some basic checks to make sure that timestamps with higher
219 // than millisecond precision are handled properly and do not cause any
220 // problems in the estimator. Specifically, previously reported in
221 // webrtc:14023 and described in more details there, the rounding to the
222 // nearest milliseconds caused discrepancy in the accumulated delay. This lead
223 // to false-positive overuse detection.
224 // Technical details of the test:
225 // Send times(ms): 0.000, 9.725, 20.000, 29.725, 40.000, 49.725, ...
226 // Recv times(ms): 0.500, 10.000, 20.500, 30.000, 40.500, 50.000, ...
227 // Send deltas(ms): 9.750, 10.250, 9.750, 10.250, 9.750, ...
228 // Recv deltas(ms): 9.500, 10.500, 9.500, 10.500, 9.500, ...
229 // There is no delay building up between the send times and the receive times,
230 // therefore this case should never lead to an overuse detection. However, if
231 // the time deltas were accidentally rounded to the nearest milliseconds, then
232 // all the send deltas would be equal to 10ms while some recv deltas would
233 // round up to 11ms which would lead in a false illusion of delay build up.
234 uint32_t last_bitrate = bitrate_observer_.latest_bitrate();
235 for (int i = 0; i < 1000; ++i) {
236 clock_.AdvanceTimeMicroseconds(500);
237 IncomingFeedback(clock_.CurrentTime(),
238 clock_.CurrentTime() - TimeDelta::Micros(500), 1000,
239 PacedPacketInfo());
240 clock_.AdvanceTimeMicroseconds(9500);
241 IncomingFeedback(clock_.CurrentTime(),
242 clock_.CurrentTime() - TimeDelta::Micros(250), 1000,
243 PacedPacketInfo());
244 clock_.AdvanceTimeMicroseconds(10000);
245
246 // The bitrate should never decrease in this test.
247 EXPECT_LE(last_bitrate, bitrate_observer_.latest_bitrate());
248 last_bitrate = bitrate_observer_.latest_bitrate();
249 }
250 }
251
252 class DelayBasedBweTestWithBackoffTimeoutExperiment : public DelayBasedBweTest {
253 public:
DelayBasedBweTestWithBackoffTimeoutExperiment()254 DelayBasedBweTestWithBackoffTimeoutExperiment()
255 : DelayBasedBweTest(
256 "WebRTC-BweAimdRateControlConfig/initial_backoff_interval:200ms/") {
257 }
258 };
259
260 // This test subsumes and improves DelayBasedBweTest.TestInitialOveruse above.
TEST_F(DelayBasedBweTestWithBackoffTimeoutExperiment,TestInitialOveruse)261 TEST_F(DelayBasedBweTestWithBackoffTimeoutExperiment, TestInitialOveruse) {
262 const DataRate kStartBitrate = DataRate::KilobitsPerSec(300);
263 const DataRate kInitialCapacity = DataRate::KilobitsPerSec(200);
264 const uint32_t kDummySsrc = 0;
265 // High FPS to ensure that we send a lot of packets in a short time.
266 const int kFps = 90;
267
268 stream_generator_->AddStream(new test::RtpStream(kFps, kStartBitrate.bps()));
269 stream_generator_->set_capacity_bps(kInitialCapacity.bps());
270
271 // Needed to initialize the AimdRateControl.
272 bitrate_estimator_->SetStartBitrate(kStartBitrate);
273
274 // Produce 30 frames (in 1/3 second) and give them to the estimator.
275 int64_t bitrate_bps = kStartBitrate.bps();
276 bool seen_overuse = false;
277 for (int frames = 0; frames < 30 && !seen_overuse; ++frames) {
278 bool overuse = GenerateAndProcessFrame(kDummySsrc, bitrate_bps);
279 // The purpose of this test is to ensure that we back down even if we don't
280 // have any acknowledged bitrate estimate yet. Hence, if the test works
281 // as expected, we should not have a measured bitrate yet.
282 EXPECT_FALSE(acknowledged_bitrate_estimator_->bitrate().has_value());
283 if (overuse) {
284 EXPECT_TRUE(bitrate_observer_.updated());
285 EXPECT_NEAR(bitrate_observer_.latest_bitrate(), kStartBitrate.bps() / 2,
286 15000);
287 bitrate_bps = bitrate_observer_.latest_bitrate();
288 seen_overuse = true;
289 } else if (bitrate_observer_.updated()) {
290 bitrate_bps = bitrate_observer_.latest_bitrate();
291 bitrate_observer_.Reset();
292 }
293 }
294 EXPECT_TRUE(seen_overuse);
295 // Continue generating an additional 15 frames (equivalent to 167 ms) and
296 // verify that we don't back down further.
297 for (int frames = 0; frames < 15 && seen_overuse; ++frames) {
298 bool overuse = GenerateAndProcessFrame(kDummySsrc, bitrate_bps);
299 EXPECT_FALSE(overuse);
300 if (bitrate_observer_.updated()) {
301 bitrate_bps = bitrate_observer_.latest_bitrate();
302 EXPECT_GE(bitrate_bps, kStartBitrate.bps() / 2 - 15000);
303 EXPECT_LE(bitrate_bps, kInitialCapacity.bps() + 15000);
304 bitrate_observer_.Reset();
305 }
306 }
307 }
308
309 } // namespace webrtc
310