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