1 /*
2 * Copyright 2018 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 <memory>
12
13 #include "api/task_queue/task_queue_base.h"
14 #include "api/test/simulated_network.h"
15 #include "api/units/time_delta.h"
16 #include "api/video/builtin_video_bitrate_allocator_factory.h"
17 #include "api/video/video_bitrate_allocation.h"
18 #include "call/fake_network_pipe.h"
19 #include "call/simulated_network.h"
20 #include "modules/rtp_rtcp/source/rtp_rtcp_impl2.h"
21 #include "rtc_base/rate_limiter.h"
22 #include "rtc_base/synchronization/mutex.h"
23 #include "rtc_base/task_queue_for_test.h"
24 #include "system_wrappers/include/sleep.h"
25 #include "test/call_test.h"
26 #include "test/fake_encoder.h"
27 #include "test/field_trial.h"
28 #include "test/gtest.h"
29 #include "test/rtcp_packet_parser.h"
30 #include "test/rtp_rtcp_observer.h"
31 #include "test/video_encoder_proxy_factory.h"
32
33 namespace webrtc {
34 namespace {
35 enum : int { // The first valid value is 1.
36 kAbsSendTimeExtensionId = 1,
37 kTransportSequenceNumberId,
38 };
39 } // namespace
40
41 class BandwidthEndToEndTest : public test::CallTest {
42 public:
43 BandwidthEndToEndTest() = default;
44 };
45
TEST_F(BandwidthEndToEndTest,ReceiveStreamSendsRemb)46 TEST_F(BandwidthEndToEndTest, ReceiveStreamSendsRemb) {
47 class RembObserver : public test::EndToEndTest {
48 public:
49 RembObserver() : EndToEndTest(kDefaultTimeout) {}
50
51 void ModifyVideoConfigs(
52 VideoSendStream::Config* send_config,
53 std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
54 VideoEncoderConfig* encoder_config) override {
55 send_config->rtp.extensions.clear();
56 send_config->rtp.extensions.push_back(
57 RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeExtensionId));
58 (*receive_configs)[0].rtp.transport_cc = false;
59 }
60
61 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
62 test::RtcpPacketParser parser;
63 EXPECT_TRUE(parser.Parse(packet, length));
64
65 if (parser.remb()->num_packets() > 0) {
66 EXPECT_EQ(kReceiverLocalVideoSsrc, parser.remb()->sender_ssrc());
67 EXPECT_LT(0U, parser.remb()->bitrate_bps());
68 EXPECT_EQ(1U, parser.remb()->ssrcs().size());
69 EXPECT_EQ(kVideoSendSsrcs[0], parser.remb()->ssrcs()[0]);
70 observation_complete_.Set();
71 }
72
73 return SEND_PACKET;
74 }
75 void PerformTest() override {
76 EXPECT_TRUE(Wait()) << "Timed out while waiting for a "
77 "receiver RTCP REMB packet to be "
78 "sent.";
79 }
80 } test;
81
82 RunBaseTest(&test);
83 }
84
85 class BandwidthStatsTest : public test::EndToEndTest {
86 public:
BandwidthStatsTest(bool send_side_bwe,TaskQueueBase * task_queue)87 BandwidthStatsTest(bool send_side_bwe, TaskQueueBase* task_queue)
88 : EndToEndTest(test::CallTest::kDefaultTimeout),
89 sender_call_(nullptr),
90 receiver_call_(nullptr),
91 has_seen_pacer_delay_(false),
92 send_side_bwe_(send_side_bwe),
93 task_queue_(task_queue) {}
94
~BandwidthStatsTest()95 ~BandwidthStatsTest() override {
96 // Block until all already posted tasks run to avoid races when such task
97 // accesses `this`.
98 SendTask(task_queue_, [] {});
99 }
100
ModifyVideoConfigs(VideoSendStream::Config * send_config,std::vector<VideoReceiveStreamInterface::Config> * receive_configs,VideoEncoderConfig * encoder_config)101 void ModifyVideoConfigs(
102 VideoSendStream::Config* send_config,
103 std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
104 VideoEncoderConfig* encoder_config) override {
105 send_config->rtp.extensions.clear();
106 if (!send_side_bwe_) {
107 send_config->rtp.extensions.push_back(
108 RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeExtensionId));
109 (*receive_configs)[0].rtp.transport_cc = false;
110 } else {
111 send_config->rtp.extensions.push_back(
112 RtpExtension(RtpExtension::kTransportSequenceNumberUri,
113 kTransportSequenceNumberId));
114 (*receive_configs)[0].rtp.transport_cc = true;
115 }
116
117 // Force a too high encoder bitrate to make sure we get pacer delay.
118 encoder_config->number_of_streams = 1;
119 encoder_config->max_bitrate_bps = kMaxBitrateBps * 2;
120 encoder_config->simulcast_layers[0].min_bitrate_bps = kMaxBitrateBps * 2;
121 encoder_config->simulcast_layers[0].target_bitrate_bps = kMaxBitrateBps * 2;
122 encoder_config->simulcast_layers[0].max_bitrate_bps = kMaxBitrateBps * 2;
123 }
124
ModifySenderBitrateConfig(BitrateConstraints * bitrate_config)125 void ModifySenderBitrateConfig(BitrateConstraints* bitrate_config) override {
126 bitrate_config->max_bitrate_bps = kMaxBitrateBps;
127 }
128
129 // Called on the pacer thread.
OnSendRtp(const uint8_t * packet,size_t length)130 Action OnSendRtp(const uint8_t* packet, size_t length) override {
131 // Stats need to be fetched on the thread where the caller objects were
132 // constructed.
133 task_queue_->PostTask([this]() {
134 if (!sender_call_ || !receiver_call_) {
135 return;
136 }
137
138 Call::Stats sender_stats = sender_call_->GetStats();
139 if (!has_seen_pacer_delay_) {
140 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
141 }
142
143 if (sender_stats.send_bandwidth_bps > 0 && has_seen_pacer_delay_) {
144 Call::Stats receiver_stats = receiver_call_->GetStats();
145 if (send_side_bwe_ || receiver_stats.recv_bandwidth_bps > 0) {
146 observation_complete_.Set();
147 }
148 }
149 });
150
151 return SEND_PACKET;
152 }
153
OnCallsCreated(Call * sender_call,Call * receiver_call)154 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
155 sender_call_ = sender_call;
156 receiver_call_ = receiver_call;
157 }
158
OnStreamsStopped()159 void OnStreamsStopped() override {
160 sender_call_ = nullptr;
161 receiver_call_ = nullptr;
162 }
163
PerformTest()164 void PerformTest() override {
165 EXPECT_TRUE(Wait()) << "Timed out while waiting for "
166 "non-zero bandwidth stats.";
167 }
168
169 private:
170 static const int kMaxBitrateBps = 3000000;
171 Call* sender_call_;
172 Call* receiver_call_;
173 bool has_seen_pacer_delay_;
174 const bool send_side_bwe_;
175 TaskQueueBase* const task_queue_;
176 };
177
TEST_F(BandwidthEndToEndTest,VerifySendSideBweStats)178 TEST_F(BandwidthEndToEndTest, VerifySendSideBweStats) {
179 BandwidthStatsTest test(true, task_queue());
180 RunBaseTest(&test);
181 }
182
TEST_F(BandwidthEndToEndTest,VerifyRecvSideBweStats)183 TEST_F(BandwidthEndToEndTest, VerifyRecvSideBweStats) {
184 BandwidthStatsTest test(false, task_queue());
185 RunBaseTest(&test);
186 }
187
188 // Verifies that it's possible to limit the send BWE by sending a REMB.
189 // This is verified by allowing the send BWE to ramp-up to >1000 kbps,
190 // then have the test generate a REMB of 500 kbps and verify that the send BWE
191 // is reduced to exactly 500 kbps. Then a REMB of 1000 kbps is generated and the
192 // test verifies that the send BWE ramps back up to exactly 1000 kbps.
TEST_F(BandwidthEndToEndTest,RembWithSendSideBwe)193 TEST_F(BandwidthEndToEndTest, RembWithSendSideBwe) {
194 class BweObserver : public test::EndToEndTest {
195 public:
196 explicit BweObserver(TaskQueueBase* task_queue)
197 : EndToEndTest(kDefaultTimeout),
198 sender_call_(nullptr),
199 clock_(Clock::GetRealTimeClock()),
200 sender_ssrc_(0),
201 remb_bitrate_bps_(1000000),
202 receive_transport_(nullptr),
203 state_(kWaitForFirstRampUp),
204 retransmission_rate_limiter_(clock_, 1000),
205 task_queue_(task_queue) {}
206
207 void OnStreamsStopped() override { rtp_rtcp_ = nullptr; }
208
209 std::unique_ptr<test::PacketTransport> CreateReceiveTransport(
210 TaskQueueBase* task_queue) override {
211 auto receive_transport = std::make_unique<test::PacketTransport>(
212 task_queue, nullptr, this, test::PacketTransport::kReceiver,
213 payload_type_map_,
214 std::make_unique<FakeNetworkPipe>(
215 Clock::GetRealTimeClock(), std::make_unique<SimulatedNetwork>(
216 BuiltInNetworkBehaviorConfig())));
217 receive_transport_ = receive_transport.get();
218 return receive_transport;
219 }
220
221 void ModifySenderBitrateConfig(
222 BitrateConstraints* bitrate_config) override {
223 // Set a high start bitrate to reduce the test completion time.
224 bitrate_config->start_bitrate_bps = remb_bitrate_bps_;
225 }
226
227 void ModifyVideoConfigs(
228 VideoSendStream::Config* send_config,
229 std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
230 VideoEncoderConfig* encoder_config) override {
231 ASSERT_EQ(1u, send_config->rtp.ssrcs.size());
232 sender_ssrc_ = send_config->rtp.ssrcs[0];
233
234 encoder_config->max_bitrate_bps = 2000000;
235
236 ASSERT_EQ(1u, receive_configs->size());
237 RtpRtcpInterface::Configuration config;
238 config.receiver_only = true;
239 config.clock = clock_;
240 config.outgoing_transport = receive_transport_;
241 config.retransmission_rate_limiter = &retransmission_rate_limiter_;
242 config.local_media_ssrc = (*receive_configs)[0].rtp.local_ssrc;
243 rtp_rtcp_ = ModuleRtpRtcpImpl2::Create(config);
244 rtp_rtcp_->SetRemoteSSRC((*receive_configs)[0].rtp.remote_ssrc);
245 rtp_rtcp_->SetRTCPStatus(RtcpMode::kReducedSize);
246 }
247
248 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
249 RTC_DCHECK(sender_call);
250 sender_call_ = sender_call;
251 task_queue_->PostTask([this]() { PollStats(); });
252 }
253
254 void PollStats() {
255 Call::Stats stats = sender_call_->GetStats();
256 switch (state_) {
257 case kWaitForFirstRampUp:
258 if (stats.send_bandwidth_bps >= remb_bitrate_bps_) {
259 state_ = kWaitForRemb;
260 remb_bitrate_bps_ /= 2;
261 rtp_rtcp_->SetRemb(
262 remb_bitrate_bps_,
263 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
264 rtp_rtcp_->SendRTCP(kRtcpRr);
265 }
266 break;
267
268 case kWaitForRemb:
269 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
270 state_ = kWaitForSecondRampUp;
271 remb_bitrate_bps_ *= 2;
272 rtp_rtcp_->SetRemb(
273 remb_bitrate_bps_,
274 std::vector<uint32_t>(&sender_ssrc_, &sender_ssrc_ + 1));
275 rtp_rtcp_->SendRTCP(kRtcpRr);
276 }
277 break;
278
279 case kWaitForSecondRampUp:
280 if (stats.send_bandwidth_bps == remb_bitrate_bps_) {
281 observation_complete_.Set();
282 return;
283 }
284 break;
285 }
286
287 task_queue_->PostDelayedTask([this] { PollStats(); },
288 TimeDelta::Seconds(1));
289 }
290
291 void PerformTest() override {
292 EXPECT_TRUE(Wait())
293 << "Timed out while waiting for bitrate to change according to REMB.";
294 }
295
296 private:
297 enum TestState { kWaitForFirstRampUp, kWaitForRemb, kWaitForSecondRampUp };
298
299 Call* sender_call_;
300 Clock* const clock_;
301 uint32_t sender_ssrc_;
302 int remb_bitrate_bps_;
303 std::unique_ptr<ModuleRtpRtcpImpl2> rtp_rtcp_;
304 test::PacketTransport* receive_transport_;
305 TestState state_;
306 RateLimiter retransmission_rate_limiter_;
307 TaskQueueBase* const task_queue_;
308 } test(task_queue());
309
310 RunBaseTest(&test);
311 }
312
TEST_F(BandwidthEndToEndTest,ReportsSetEncoderRates)313 TEST_F(BandwidthEndToEndTest, ReportsSetEncoderRates) {
314 // If these fields trial are on, we get lower bitrates than expected by this
315 // test, due to the packetization overhead and encoder pushback.
316 webrtc::test::ScopedFieldTrials field_trials(
317 std::string(field_trial::GetFieldTrialString()) +
318 "WebRTC-VideoRateControl/bitrate_adjuster:false/");
319 class EncoderRateStatsTest : public test::EndToEndTest,
320 public test::FakeEncoder {
321 public:
322 explicit EncoderRateStatsTest(TaskQueueBase* task_queue)
323 : EndToEndTest(kDefaultTimeout),
324 FakeEncoder(Clock::GetRealTimeClock()),
325 task_queue_(task_queue),
326 send_stream_(nullptr),
327 encoder_factory_(this),
328 bitrate_allocator_factory_(
329 CreateBuiltinVideoBitrateAllocatorFactory()),
330 bitrate_kbps_(0) {}
331
332 void OnVideoStreamsCreated(VideoSendStream* send_stream,
333 const std::vector<VideoReceiveStreamInterface*>&
334 receive_streams) override {
335 send_stream_ = send_stream;
336 }
337
338 void ModifyVideoConfigs(
339 VideoSendStream::Config* send_config,
340 std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
341 VideoEncoderConfig* encoder_config) override {
342 send_config->encoder_settings.encoder_factory = &encoder_factory_;
343 send_config->encoder_settings.bitrate_allocator_factory =
344 bitrate_allocator_factory_.get();
345 RTC_DCHECK_EQ(1, encoder_config->number_of_streams);
346 }
347
348 void SetRates(const RateControlParameters& parameters) override {
349 // Make sure not to trigger on any default zero bitrates.
350 if (parameters.bitrate.get_sum_bps() == 0)
351 return;
352 MutexLock lock(&mutex_);
353 bitrate_kbps_ = parameters.bitrate.get_sum_kbps();
354 observation_complete_.Set();
355 }
356
357 void PerformTest() override {
358 ASSERT_TRUE(Wait())
359 << "Timed out while waiting for encoder SetRates() call.";
360
361 SendTask(task_queue_, [this]() {
362 WaitForEncoderTargetBitrateMatchStats();
363 send_stream_->Stop();
364 WaitForStatsReportZeroTargetBitrate();
365 send_stream_->Start();
366 WaitForEncoderTargetBitrateMatchStats();
367 });
368 }
369
370 void WaitForEncoderTargetBitrateMatchStats() {
371 for (int i = 0; i < kDefaultTimeout.ms(); ++i) {
372 VideoSendStream::Stats stats = send_stream_->GetStats();
373 {
374 MutexLock lock(&mutex_);
375 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
376 static_cast<int>(bitrate_kbps_)) {
377 return;
378 }
379 }
380 SleepMs(1);
381 }
382 FAIL()
383 << "Timed out waiting for stats reporting the currently set bitrate.";
384 }
385
386 void WaitForStatsReportZeroTargetBitrate() {
387 for (int i = 0; i < kDefaultTimeout.ms(); ++i) {
388 if (send_stream_->GetStats().target_media_bitrate_bps == 0) {
389 return;
390 }
391 SleepMs(1);
392 }
393 FAIL() << "Timed out waiting for stats reporting zero bitrate.";
394 }
395
396 private:
397 TaskQueueBase* const task_queue_;
398 Mutex mutex_;
399 VideoSendStream* send_stream_;
400 test::VideoEncoderProxyFactory encoder_factory_;
401 std::unique_ptr<VideoBitrateAllocatorFactory> bitrate_allocator_factory_;
402 uint32_t bitrate_kbps_ RTC_GUARDED_BY(mutex_);
403 } test(task_queue());
404
405 RunBaseTest(&test);
406 }
407 } // namespace webrtc
408