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