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 "video/video_send_stream_impl.h"
12
13 #include <algorithm>
14 #include <memory>
15 #include <string>
16
17 #include "absl/types/optional.h"
18 #include "api/rtc_event_log/rtc_event_log.h"
19 #include "call/rtp_video_sender.h"
20 #include "call/test/mock_bitrate_allocator.h"
21 #include "call/test/mock_rtp_transport_controller_send.h"
22 #include "modules/rtp_rtcp/source/rtp_sequence_number_map.h"
23 #include "modules/utility/include/process_thread.h"
24 #include "modules/video_coding/fec_controller_default.h"
25 #include "rtc_base/experiments/alr_experiment.h"
26 #include "rtc_base/fake_clock.h"
27 #include "rtc_base/task_queue_for_test.h"
28 #include "test/field_trial.h"
29 #include "test/gmock.h"
30 #include "test/gtest.h"
31 #include "test/mock_transport.h"
32 #include "video/call_stats.h"
33 #include "video/test/mock_video_stream_encoder.h"
34
35 namespace webrtc {
36
operator ==(const BitrateAllocationUpdate & a,const BitrateAllocationUpdate & b)37 bool operator==(const BitrateAllocationUpdate& a,
38 const BitrateAllocationUpdate& b) {
39 return a.target_bitrate == b.target_bitrate &&
40 a.round_trip_time == b.round_trip_time &&
41 a.packet_loss_ratio == b.packet_loss_ratio;
42 }
43
44 namespace internal {
45 namespace {
46 using ::testing::_;
47 using ::testing::AllOf;
48 using ::testing::Field;
49 using ::testing::Invoke;
50 using ::testing::NiceMock;
51 using ::testing::Return;
52
53 constexpr int64_t kDefaultInitialBitrateBps = 333000;
54 const double kDefaultBitratePriority = 0.5;
55
56 const float kAlrProbingExperimentPaceMultiplier = 1.0f;
GetAlrProbingExperimentString()57 std::string GetAlrProbingExperimentString() {
58 return std::string(
59 AlrExperimentSettings::kScreenshareProbingBweExperimentName) +
60 "/1.0,2875,80,40,-60,3/";
61 }
62 class MockRtpVideoSender : public RtpVideoSenderInterface {
63 public:
64 MOCK_METHOD(void, RegisterProcessThread, (ProcessThread*), (override));
65 MOCK_METHOD(void, DeRegisterProcessThread, (), (override));
66 MOCK_METHOD(void, SetActive, (bool), (override));
67 MOCK_METHOD(void, SetActiveModules, (const std::vector<bool>), (override));
68 MOCK_METHOD(bool, IsActive, (), (override));
69 MOCK_METHOD(void, OnNetworkAvailability, (bool), (override));
70 MOCK_METHOD((std::map<uint32_t, RtpState>),
71 GetRtpStates,
72 (),
73 (const, override));
74 MOCK_METHOD((std::map<uint32_t, RtpPayloadState>),
75 GetRtpPayloadStates,
76 (),
77 (const, override));
78 MOCK_METHOD(void, DeliverRtcp, (const uint8_t*, size_t), (override));
79 MOCK_METHOD(void,
80 OnBitrateAllocationUpdated,
81 (const VideoBitrateAllocation&),
82 (override));
83 MOCK_METHOD(EncodedImageCallback::Result,
84 OnEncodedImage,
85 (const EncodedImage&,
86 const CodecSpecificInfo*,
87 const RTPFragmentationHeader*),
88 (override));
89 MOCK_METHOD(void, OnTransportOverheadChanged, (size_t), (override));
90 MOCK_METHOD(void,
91 OnBitrateUpdated,
92 (BitrateAllocationUpdate, int),
93 (override));
94 MOCK_METHOD(uint32_t, GetPayloadBitrateBps, (), (const, override));
95 MOCK_METHOD(uint32_t, GetProtectionBitrateBps, (), (const, override));
96 MOCK_METHOD(void, SetEncodingData, (size_t, size_t, size_t), (override));
97 MOCK_METHOD(std::vector<RtpSequenceNumberMap::Info>,
98 GetSentRtpPacketInfos,
99 (uint32_t ssrc, rtc::ArrayView<const uint16_t> sequence_numbers),
100 (const, override));
101
102 MOCK_METHOD(void, SetFecAllowed, (bool fec_allowed), (override));
103 };
104
CreateAllocation(int bitrate_bps)105 BitrateAllocationUpdate CreateAllocation(int bitrate_bps) {
106 BitrateAllocationUpdate update;
107 update.target_bitrate = DataRate::BitsPerSec(bitrate_bps);
108 update.packet_loss_ratio = 0;
109 update.round_trip_time = TimeDelta::Zero();
110 return update;
111 }
112 } // namespace
113
114 class VideoSendStreamImplTest : public ::testing::Test {
115 protected:
VideoSendStreamImplTest()116 VideoSendStreamImplTest()
117 : clock_(1000 * 1000 * 1000),
118 config_(&transport_),
119 send_delay_stats_(&clock_),
120 test_queue_("test_queue"),
121 process_thread_(ProcessThread::Create("test_thread")),
122 call_stats_(&clock_, process_thread_.get()),
123 stats_proxy_(&clock_,
124 config_,
125 VideoEncoderConfig::ContentType::kRealtimeVideo) {
126 config_.rtp.ssrcs.push_back(8080);
127 config_.rtp.payload_type = 1;
128
129 EXPECT_CALL(transport_controller_, packet_router())
130 .WillRepeatedly(Return(&packet_router_));
131 EXPECT_CALL(transport_controller_, CreateRtpVideoSender)
132 .WillRepeatedly(Return(&rtp_video_sender_));
133 EXPECT_CALL(rtp_video_sender_, SetActive(_))
134 .WillRepeatedly(::testing::Invoke(
135 [&](bool active) { rtp_video_sender_active_ = active; }));
136 EXPECT_CALL(rtp_video_sender_, IsActive())
137 .WillRepeatedly(
138 ::testing::Invoke([&]() { return rtp_video_sender_active_; }));
139 }
~VideoSendStreamImplTest()140 ~VideoSendStreamImplTest() {}
141
CreateVideoSendStreamImpl(int initial_encoder_max_bitrate,double initial_encoder_bitrate_priority,VideoEncoderConfig::ContentType content_type)142 std::unique_ptr<VideoSendStreamImpl> CreateVideoSendStreamImpl(
143 int initial_encoder_max_bitrate,
144 double initial_encoder_bitrate_priority,
145 VideoEncoderConfig::ContentType content_type) {
146 EXPECT_CALL(bitrate_allocator_, GetStartBitrate(_))
147 .WillOnce(Return(123000));
148 std::map<uint32_t, RtpState> suspended_ssrcs;
149 std::map<uint32_t, RtpPayloadState> suspended_payload_states;
150 return std::make_unique<VideoSendStreamImpl>(
151 &clock_, &stats_proxy_, &test_queue_, &call_stats_,
152 &transport_controller_, &bitrate_allocator_, &send_delay_stats_,
153 &video_stream_encoder_, &event_log_, &config_,
154 initial_encoder_max_bitrate, initial_encoder_bitrate_priority,
155 suspended_ssrcs, suspended_payload_states, content_type,
156 std::make_unique<FecControllerDefault>(&clock_));
157 }
158
159 protected:
160 NiceMock<MockTransport> transport_;
161 NiceMock<MockRtpTransportControllerSend> transport_controller_;
162 NiceMock<MockBitrateAllocator> bitrate_allocator_;
163 NiceMock<MockVideoStreamEncoder> video_stream_encoder_;
164 NiceMock<MockRtpVideoSender> rtp_video_sender_;
165
166 bool rtp_video_sender_active_ = false;
167 SimulatedClock clock_;
168 RtcEventLogNull event_log_;
169 VideoSendStream::Config config_;
170 SendDelayStats send_delay_stats_;
171 TaskQueueForTest test_queue_;
172 std::unique_ptr<ProcessThread> process_thread_;
173 // TODO(tommi): Use internal::CallStats
174 CallStats call_stats_;
175 SendStatisticsProxy stats_proxy_;
176 PacketRouter packet_router_;
177 };
178
TEST_F(VideoSendStreamImplTest,RegistersAsBitrateObserverOnStart)179 TEST_F(VideoSendStreamImplTest, RegistersAsBitrateObserverOnStart) {
180 test_queue_.SendTask(
181 [this] {
182 const bool kSuspend = false;
183 config_.suspend_below_min_bitrate = kSuspend;
184 auto vss_impl = CreateVideoSendStreamImpl(
185 kDefaultInitialBitrateBps, kDefaultBitratePriority,
186 VideoEncoderConfig::ContentType::kRealtimeVideo);
187 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
188 .WillOnce(Invoke([&](BitrateAllocatorObserver*,
189 MediaStreamAllocationConfig config) {
190 EXPECT_EQ(config.min_bitrate_bps, 0u);
191 EXPECT_EQ(config.max_bitrate_bps, kDefaultInitialBitrateBps);
192 EXPECT_EQ(config.pad_up_bitrate_bps, 0u);
193 EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
194 EXPECT_EQ(config.bitrate_priority, kDefaultBitratePriority);
195 }));
196 vss_impl->Start();
197 EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get()))
198 .Times(1);
199 vss_impl->Stop();
200 },
201 RTC_FROM_HERE);
202 }
203
TEST_F(VideoSendStreamImplTest,UpdatesObserverOnConfigurationChange)204 TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChange) {
205 test_queue_.SendTask(
206 [this] {
207 const bool kSuspend = false;
208 config_.suspend_below_min_bitrate = kSuspend;
209 config_.rtp.extensions.emplace_back(
210 RtpExtension::kTransportSequenceNumberUri, 1);
211 auto vss_impl = CreateVideoSendStreamImpl(
212 kDefaultInitialBitrateBps, kDefaultBitratePriority,
213 VideoEncoderConfig::ContentType::kRealtimeVideo);
214 vss_impl->Start();
215
216 // QVGA + VGA configuration matching defaults in
217 // media/engine/simulcast.cc.
218 VideoStream qvga_stream;
219 qvga_stream.width = 320;
220 qvga_stream.height = 180;
221 qvga_stream.max_framerate = 30;
222 qvga_stream.min_bitrate_bps = 30000;
223 qvga_stream.target_bitrate_bps = 150000;
224 qvga_stream.max_bitrate_bps = 200000;
225 qvga_stream.max_qp = 56;
226 qvga_stream.bitrate_priority = 1;
227
228 VideoStream vga_stream;
229 vga_stream.width = 640;
230 vga_stream.height = 360;
231 vga_stream.max_framerate = 30;
232 vga_stream.min_bitrate_bps = 150000;
233 vga_stream.target_bitrate_bps = 500000;
234 vga_stream.max_bitrate_bps = 700000;
235 vga_stream.max_qp = 56;
236 vga_stream.bitrate_priority = 1;
237
238 int min_transmit_bitrate_bps = 30000;
239
240 config_.rtp.ssrcs.emplace_back(1);
241 config_.rtp.ssrcs.emplace_back(2);
242
243 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
244 .WillRepeatedly(Invoke([&](BitrateAllocatorObserver*,
245 MediaStreamAllocationConfig config) {
246 EXPECT_EQ(config.min_bitrate_bps,
247 static_cast<uint32_t>(min_transmit_bitrate_bps));
248 EXPECT_EQ(config.max_bitrate_bps,
249 static_cast<uint32_t>(qvga_stream.max_bitrate_bps +
250 vga_stream.max_bitrate_bps));
251 if (config.pad_up_bitrate_bps != 0) {
252 EXPECT_EQ(config.pad_up_bitrate_bps,
253 static_cast<uint32_t>(qvga_stream.target_bitrate_bps +
254 vga_stream.min_bitrate_bps));
255 }
256 EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
257 }));
258
259 static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
260 ->OnEncoderConfigurationChanged(
261 std::vector<VideoStream>{qvga_stream, vga_stream}, false,
262 VideoEncoderConfig::ContentType::kRealtimeVideo,
263 min_transmit_bitrate_bps);
264 vss_impl->Stop();
265 },
266 RTC_FROM_HERE);
267 }
268
TEST_F(VideoSendStreamImplTest,UpdatesObserverOnConfigurationChangeWithAlr)269 TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChangeWithAlr) {
270 test_queue_.SendTask(
271 [this] {
272 const bool kSuspend = false;
273 config_.suspend_below_min_bitrate = kSuspend;
274 config_.rtp.extensions.emplace_back(
275 RtpExtension::kTransportSequenceNumberUri, 1);
276 config_.periodic_alr_bandwidth_probing = true;
277 auto vss_impl = CreateVideoSendStreamImpl(
278 kDefaultInitialBitrateBps, kDefaultBitratePriority,
279 VideoEncoderConfig::ContentType::kScreen);
280 vss_impl->Start();
281
282 // Simulcast screenshare.
283 VideoStream low_stream;
284 low_stream.width = 1920;
285 low_stream.height = 1080;
286 low_stream.max_framerate = 5;
287 low_stream.min_bitrate_bps = 30000;
288 low_stream.target_bitrate_bps = 200000;
289 low_stream.max_bitrate_bps = 1000000;
290 low_stream.num_temporal_layers = 2;
291 low_stream.max_qp = 56;
292 low_stream.bitrate_priority = 1;
293
294 VideoStream high_stream;
295 high_stream.width = 1920;
296 high_stream.height = 1080;
297 high_stream.max_framerate = 30;
298 high_stream.min_bitrate_bps = 60000;
299 high_stream.target_bitrate_bps = 1250000;
300 high_stream.max_bitrate_bps = 1250000;
301 high_stream.num_temporal_layers = 2;
302 high_stream.max_qp = 56;
303 high_stream.bitrate_priority = 1;
304
305 // With ALR probing, this will be the padding target instead of
306 // low_stream.target_bitrate_bps + high_stream.min_bitrate_bps.
307 int min_transmit_bitrate_bps = 400000;
308
309 config_.rtp.ssrcs.emplace_back(1);
310 config_.rtp.ssrcs.emplace_back(2);
311
312 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
313 .WillRepeatedly(Invoke([&](BitrateAllocatorObserver*,
314 MediaStreamAllocationConfig config) {
315 EXPECT_EQ(config.min_bitrate_bps,
316 static_cast<uint32_t>(low_stream.min_bitrate_bps));
317 EXPECT_EQ(config.max_bitrate_bps,
318 static_cast<uint32_t>(low_stream.max_bitrate_bps +
319 high_stream.max_bitrate_bps));
320 if (config.pad_up_bitrate_bps != 0) {
321 EXPECT_EQ(config.pad_up_bitrate_bps,
322 static_cast<uint32_t>(min_transmit_bitrate_bps));
323 }
324 EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
325 }));
326
327 static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
328 ->OnEncoderConfigurationChanged(
329 std::vector<VideoStream>{low_stream, high_stream}, false,
330 VideoEncoderConfig::ContentType::kScreen,
331 min_transmit_bitrate_bps);
332 vss_impl->Stop();
333 },
334 RTC_FROM_HERE);
335 }
336
TEST_F(VideoSendStreamImplTest,UpdatesObserverOnConfigurationChangeWithSimulcastVideoHysteresis)337 TEST_F(VideoSendStreamImplTest,
338 UpdatesObserverOnConfigurationChangeWithSimulcastVideoHysteresis) {
339 test::ScopedFieldTrials hysteresis_experiment(
340 "WebRTC-VideoRateControl/video_hysteresis:1.25/");
341
342 test_queue_.SendTask(
343 [this] {
344 auto vss_impl = CreateVideoSendStreamImpl(
345 kDefaultInitialBitrateBps, kDefaultBitratePriority,
346 VideoEncoderConfig::ContentType::kRealtimeVideo);
347 vss_impl->Start();
348
349 // 2-layer video simulcast.
350 VideoStream low_stream;
351 low_stream.width = 320;
352 low_stream.height = 240;
353 low_stream.max_framerate = 30;
354 low_stream.min_bitrate_bps = 30000;
355 low_stream.target_bitrate_bps = 100000;
356 low_stream.max_bitrate_bps = 200000;
357 low_stream.max_qp = 56;
358 low_stream.bitrate_priority = 1;
359
360 VideoStream high_stream;
361 high_stream.width = 640;
362 high_stream.height = 480;
363 high_stream.max_framerate = 30;
364 high_stream.min_bitrate_bps = 150000;
365 high_stream.target_bitrate_bps = 500000;
366 high_stream.max_bitrate_bps = 750000;
367 high_stream.max_qp = 56;
368 high_stream.bitrate_priority = 1;
369
370 config_.rtp.ssrcs.emplace_back(1);
371 config_.rtp.ssrcs.emplace_back(2);
372
373 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
374 .WillRepeatedly(Invoke([&](BitrateAllocatorObserver*,
375 MediaStreamAllocationConfig config) {
376 EXPECT_EQ(config.min_bitrate_bps,
377 static_cast<uint32_t>(low_stream.min_bitrate_bps));
378 EXPECT_EQ(config.max_bitrate_bps,
379 static_cast<uint32_t>(low_stream.max_bitrate_bps +
380 high_stream.max_bitrate_bps));
381 if (config.pad_up_bitrate_bps != 0) {
382 EXPECT_EQ(
383 config.pad_up_bitrate_bps,
384 static_cast<uint32_t>(low_stream.target_bitrate_bps +
385 1.25 * high_stream.min_bitrate_bps));
386 }
387 }));
388
389 static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
390 ->OnEncoderConfigurationChanged(
391 std::vector<VideoStream>{low_stream, high_stream}, false,
392 VideoEncoderConfig::ContentType::kRealtimeVideo,
393 /*min_transmit_bitrate_bps=*/0);
394 vss_impl->Stop();
395 },
396 RTC_FROM_HERE);
397 }
398
TEST_F(VideoSendStreamImplTest,SetsScreensharePacingFactorWithFeedback)399 TEST_F(VideoSendStreamImplTest, SetsScreensharePacingFactorWithFeedback) {
400 test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString());
401
402 test_queue_.SendTask(
403 [this] {
404 constexpr int kId = 1;
405 config_.rtp.extensions.emplace_back(
406 RtpExtension::kTransportSequenceNumberUri, kId);
407 EXPECT_CALL(transport_controller_,
408 SetPacingFactor(kAlrProbingExperimentPaceMultiplier))
409 .Times(1);
410 auto vss_impl = CreateVideoSendStreamImpl(
411 kDefaultInitialBitrateBps, kDefaultBitratePriority,
412 VideoEncoderConfig::ContentType::kScreen);
413 vss_impl->Start();
414 vss_impl->Stop();
415 },
416 RTC_FROM_HERE);
417 }
418
TEST_F(VideoSendStreamImplTest,DoesNotSetPacingFactorWithoutFeedback)419 TEST_F(VideoSendStreamImplTest, DoesNotSetPacingFactorWithoutFeedback) {
420 test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString());
421 test_queue_.SendTask(
422 [this] {
423 EXPECT_CALL(transport_controller_, SetPacingFactor(_)).Times(0);
424 auto vss_impl = CreateVideoSendStreamImpl(
425 kDefaultInitialBitrateBps, kDefaultBitratePriority,
426 VideoEncoderConfig::ContentType::kScreen);
427 vss_impl->Start();
428 vss_impl->Stop();
429 },
430 RTC_FROM_HERE);
431 }
432
TEST_F(VideoSendStreamImplTest,ForwardsVideoBitrateAllocationWhenEnabled)433 TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationWhenEnabled) {
434 test_queue_.SendTask(
435 [this] {
436 EXPECT_CALL(transport_controller_, SetPacingFactor(_)).Times(0);
437 auto vss_impl = CreateVideoSendStreamImpl(
438 kDefaultInitialBitrateBps, kDefaultBitratePriority,
439 VideoEncoderConfig::ContentType::kScreen);
440 vss_impl->Start();
441 VideoBitrateAllocationObserver* const observer =
442 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
443
444 // Populate a test instance of video bitrate allocation.
445 VideoBitrateAllocation alloc;
446 alloc.SetBitrate(0, 0, 10000);
447 alloc.SetBitrate(0, 1, 20000);
448 alloc.SetBitrate(1, 0, 30000);
449 alloc.SetBitrate(1, 1, 40000);
450
451 // Encoder starts out paused, don't forward allocation.
452 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
453 .Times(0);
454 observer->OnBitrateAllocationUpdated(alloc);
455
456 // Unpause encoder, allocation should be passed through.
457 const uint32_t kBitrateBps = 100000;
458 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
459 .Times(1)
460 .WillOnce(Return(kBitrateBps));
461 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
462 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
463 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
464 .Times(1);
465 observer->OnBitrateAllocationUpdated(alloc);
466
467 // Pause encoder again, and block allocations.
468 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
469 .Times(1)
470 .WillOnce(Return(0));
471 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
472 ->OnBitrateUpdated(CreateAllocation(0));
473 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
474 .Times(0);
475 observer->OnBitrateAllocationUpdated(alloc);
476
477 vss_impl->Stop();
478 },
479 RTC_FROM_HERE);
480 }
481
TEST_F(VideoSendStreamImplTest,ThrottlesVideoBitrateAllocationWhenTooSimilar)482 TEST_F(VideoSendStreamImplTest, ThrottlesVideoBitrateAllocationWhenTooSimilar) {
483 test_queue_.SendTask(
484 [this] {
485 auto vss_impl = CreateVideoSendStreamImpl(
486 kDefaultInitialBitrateBps, kDefaultBitratePriority,
487 VideoEncoderConfig::ContentType::kScreen);
488 vss_impl->Start();
489 // Unpause encoder, to allows allocations to be passed through.
490 const uint32_t kBitrateBps = 100000;
491 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
492 .Times(1)
493 .WillOnce(Return(kBitrateBps));
494 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
495 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
496 VideoBitrateAllocationObserver* const observer =
497 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
498
499 // Populate a test instance of video bitrate allocation.
500 VideoBitrateAllocation alloc;
501 alloc.SetBitrate(0, 0, 10000);
502 alloc.SetBitrate(0, 1, 20000);
503 alloc.SetBitrate(1, 0, 30000);
504 alloc.SetBitrate(1, 1, 40000);
505
506 // Initial value.
507 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
508 .Times(1);
509 observer->OnBitrateAllocationUpdated(alloc);
510
511 VideoBitrateAllocation updated_alloc = alloc;
512 // Needs 10% increase in bitrate to trigger immediate forward.
513 const uint32_t base_layer_min_update_bitrate_bps =
514 alloc.GetBitrate(0, 0) + alloc.get_sum_bps() / 10;
515
516 // Too small increase, don't forward.
517 updated_alloc.SetBitrate(0, 0, base_layer_min_update_bitrate_bps - 1);
518 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(_)).Times(0);
519 observer->OnBitrateAllocationUpdated(updated_alloc);
520
521 // Large enough increase, do forward.
522 updated_alloc.SetBitrate(0, 0, base_layer_min_update_bitrate_bps);
523 EXPECT_CALL(rtp_video_sender_,
524 OnBitrateAllocationUpdated(updated_alloc))
525 .Times(1);
526 observer->OnBitrateAllocationUpdated(updated_alloc);
527
528 // This is now a decrease compared to last forward allocation, forward
529 // immediately.
530 updated_alloc.SetBitrate(0, 0, base_layer_min_update_bitrate_bps - 1);
531 EXPECT_CALL(rtp_video_sender_,
532 OnBitrateAllocationUpdated(updated_alloc))
533 .Times(1);
534 observer->OnBitrateAllocationUpdated(updated_alloc);
535
536 vss_impl->Stop();
537 },
538 RTC_FROM_HERE);
539 }
540
TEST_F(VideoSendStreamImplTest,ForwardsVideoBitrateAllocationOnLayerChange)541 TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationOnLayerChange) {
542 test_queue_.SendTask(
543 [this] {
544 auto vss_impl = CreateVideoSendStreamImpl(
545 kDefaultInitialBitrateBps, kDefaultBitratePriority,
546 VideoEncoderConfig::ContentType::kScreen);
547 vss_impl->Start();
548 // Unpause encoder, to allows allocations to be passed through.
549 const uint32_t kBitrateBps = 100000;
550 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
551 .Times(1)
552 .WillOnce(Return(kBitrateBps));
553 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
554 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
555 VideoBitrateAllocationObserver* const observer =
556 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
557
558 // Populate a test instance of video bitrate allocation.
559 VideoBitrateAllocation alloc;
560 alloc.SetBitrate(0, 0, 10000);
561 alloc.SetBitrate(0, 1, 20000);
562 alloc.SetBitrate(1, 0, 30000);
563 alloc.SetBitrate(1, 1, 40000);
564
565 // Initial value.
566 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
567 .Times(1);
568 observer->OnBitrateAllocationUpdated(alloc);
569
570 // Move some bitrate from one layer to a new one, but keep sum the same.
571 // Since layout has changed, immediately trigger forward.
572 VideoBitrateAllocation updated_alloc = alloc;
573 updated_alloc.SetBitrate(2, 0, 10000);
574 updated_alloc.SetBitrate(1, 1, alloc.GetBitrate(1, 1) - 10000);
575 EXPECT_EQ(alloc.get_sum_bps(), updated_alloc.get_sum_bps());
576 EXPECT_CALL(rtp_video_sender_,
577 OnBitrateAllocationUpdated(updated_alloc))
578 .Times(1);
579 observer->OnBitrateAllocationUpdated(updated_alloc);
580
581 vss_impl->Stop();
582 },
583 RTC_FROM_HERE);
584 }
585
TEST_F(VideoSendStreamImplTest,ForwardsVideoBitrateAllocationAfterTimeout)586 TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationAfterTimeout) {
587 test_queue_.SendTask(
588 [this] {
589 auto vss_impl = CreateVideoSendStreamImpl(
590 kDefaultInitialBitrateBps, kDefaultBitratePriority,
591 VideoEncoderConfig::ContentType::kScreen);
592 vss_impl->Start();
593 const uint32_t kBitrateBps = 100000;
594 // Unpause encoder, to allows allocations to be passed through.
595 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
596 .Times(1)
597 .WillRepeatedly(Return(kBitrateBps));
598 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
599 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
600 VideoBitrateAllocationObserver* const observer =
601 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
602
603 // Populate a test instance of video bitrate allocation.
604 VideoBitrateAllocation alloc;
605 alloc.SetBitrate(0, 0, 10000);
606 alloc.SetBitrate(0, 1, 20000);
607 alloc.SetBitrate(1, 0, 30000);
608 alloc.SetBitrate(1, 1, 40000);
609
610 EncodedImage encoded_image;
611 CodecSpecificInfo codec_specific;
612 EXPECT_CALL(rtp_video_sender_, OnEncodedImage(_, _, _))
613 .WillRepeatedly(Return(EncodedImageCallback::Result(
614 EncodedImageCallback::Result::OK)));
615
616 // Max time we will throttle similar video bitrate allocations.
617 static constexpr int64_t kMaxVbaThrottleTimeMs = 500;
618
619 {
620 // Initial value.
621 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
622 .Times(1);
623 observer->OnBitrateAllocationUpdated(alloc);
624 }
625
626 {
627 // Sending same allocation again, this one should be throttled.
628 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
629 .Times(0);
630 observer->OnBitrateAllocationUpdated(alloc);
631 }
632
633 clock_.AdvanceTimeMicroseconds(kMaxVbaThrottleTimeMs * 1000);
634
635 {
636 // Sending similar allocation again after timeout, should forward.
637 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
638 .Times(1);
639 observer->OnBitrateAllocationUpdated(alloc);
640 }
641
642 {
643 // Sending similar allocation again without timeout, throttle.
644 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
645 .Times(0);
646 observer->OnBitrateAllocationUpdated(alloc);
647 }
648
649 {
650 // Send encoded image, should be a noop.
651 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
652 .Times(0);
653 static_cast<EncodedImageCallback*>(vss_impl.get())
654 ->OnEncodedImage(encoded_image, &codec_specific, nullptr);
655 }
656
657 {
658 // Advance time and send encoded image, this should wake up and send
659 // cached bitrate allocation.
660 clock_.AdvanceTimeMicroseconds(kMaxVbaThrottleTimeMs * 1000);
661 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
662 .Times(1);
663 static_cast<EncodedImageCallback*>(vss_impl.get())
664 ->OnEncodedImage(encoded_image, &codec_specific, nullptr);
665 }
666
667 {
668 // Advance time and send encoded image, there should be no cached
669 // allocation to send.
670 clock_.AdvanceTimeMicroseconds(kMaxVbaThrottleTimeMs * 1000);
671 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
672 .Times(0);
673 static_cast<EncodedImageCallback*>(vss_impl.get())
674 ->OnEncodedImage(encoded_image, &codec_specific, nullptr);
675 }
676
677 vss_impl->Stop();
678 },
679 RTC_FROM_HERE);
680 }
681
TEST_F(VideoSendStreamImplTest,CallsVideoStreamEncoderOnBitrateUpdate)682 TEST_F(VideoSendStreamImplTest, CallsVideoStreamEncoderOnBitrateUpdate) {
683 test_queue_.SendTask(
684 [this] {
685 const bool kSuspend = false;
686 config_.suspend_below_min_bitrate = kSuspend;
687 config_.rtp.extensions.emplace_back(
688 RtpExtension::kTransportSequenceNumberUri, 1);
689 auto vss_impl = CreateVideoSendStreamImpl(
690 kDefaultInitialBitrateBps, kDefaultBitratePriority,
691 VideoEncoderConfig::ContentType::kRealtimeVideo);
692 vss_impl->Start();
693
694 VideoStream qvga_stream;
695 qvga_stream.width = 320;
696 qvga_stream.height = 180;
697 qvga_stream.max_framerate = 30;
698 qvga_stream.min_bitrate_bps = 30000;
699 qvga_stream.target_bitrate_bps = 150000;
700 qvga_stream.max_bitrate_bps = 200000;
701 qvga_stream.max_qp = 56;
702 qvga_stream.bitrate_priority = 1;
703
704 int min_transmit_bitrate_bps = 30000;
705
706 config_.rtp.ssrcs.emplace_back(1);
707
708 static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
709 ->OnEncoderConfigurationChanged(
710 std::vector<VideoStream>{qvga_stream}, false,
711 VideoEncoderConfig::ContentType::kRealtimeVideo,
712 min_transmit_bitrate_bps);
713
714 const DataRate network_constrained_rate =
715 DataRate::BitsPerSec(qvga_stream.target_bitrate_bps);
716 BitrateAllocationUpdate update;
717 update.target_bitrate = network_constrained_rate;
718 update.stable_target_bitrate = network_constrained_rate;
719 update.round_trip_time = TimeDelta::Millis(1);
720 EXPECT_CALL(rtp_video_sender_, OnBitrateUpdated(update, _));
721 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
722 .WillOnce(Return(network_constrained_rate.bps()));
723 EXPECT_CALL(
724 video_stream_encoder_,
725 OnBitrateUpdated(network_constrained_rate, network_constrained_rate,
726 network_constrained_rate, 0, _, 0));
727 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
728 ->OnBitrateUpdated(update);
729
730 // Test allocation where the link allocation is larger than the target,
731 // meaning we have some headroom on the link.
732 const DataRate qvga_max_bitrate =
733 DataRate::BitsPerSec(qvga_stream.max_bitrate_bps);
734 const DataRate headroom = DataRate::BitsPerSec(50000);
735 const DataRate rate_with_headroom = qvga_max_bitrate + headroom;
736 update.target_bitrate = rate_with_headroom;
737 update.stable_target_bitrate = rate_with_headroom;
738 EXPECT_CALL(rtp_video_sender_, OnBitrateUpdated(update, _));
739 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
740 .WillOnce(Return(rate_with_headroom.bps()));
741 EXPECT_CALL(video_stream_encoder_,
742 OnBitrateUpdated(qvga_max_bitrate, qvga_max_bitrate,
743 rate_with_headroom, 0, _, 0));
744 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
745 ->OnBitrateUpdated(update);
746
747 // Add protection bitrate to the mix, this should be subtracted from the
748 // headroom.
749 const uint32_t protection_bitrate_bps = 10000;
750 EXPECT_CALL(rtp_video_sender_, GetProtectionBitrateBps())
751 .WillOnce(Return(protection_bitrate_bps));
752
753 EXPECT_CALL(rtp_video_sender_, OnBitrateUpdated(update, _));
754 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
755 .WillOnce(Return(rate_with_headroom.bps()));
756 const DataRate headroom_minus_protection =
757 rate_with_headroom - DataRate::BitsPerSec(protection_bitrate_bps);
758 EXPECT_CALL(video_stream_encoder_,
759 OnBitrateUpdated(qvga_max_bitrate, qvga_max_bitrate,
760 headroom_minus_protection, 0, _, 0));
761 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
762 ->OnBitrateUpdated(update);
763
764 // Protection bitrate exceeds head room, link allocation should be
765 // capped to target bitrate.
766 EXPECT_CALL(rtp_video_sender_, GetProtectionBitrateBps())
767 .WillOnce(Return(headroom.bps() + 1000));
768 EXPECT_CALL(rtp_video_sender_, OnBitrateUpdated(update, _));
769 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
770 .WillOnce(Return(rate_with_headroom.bps()));
771 EXPECT_CALL(video_stream_encoder_,
772 OnBitrateUpdated(qvga_max_bitrate, qvga_max_bitrate,
773 qvga_max_bitrate, 0, _, 0));
774 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
775 ->OnBitrateUpdated(update);
776
777 // Set rates to zero on stop.
778 EXPECT_CALL(video_stream_encoder_,
779 OnBitrateUpdated(DataRate::Zero(), DataRate::Zero(),
780 DataRate::Zero(), 0, 0, 0));
781 vss_impl->Stop();
782 },
783 RTC_FROM_HERE);
784 }
785
TEST_F(VideoSendStreamImplTest,DisablesPaddingOnPausedEncoder)786 TEST_F(VideoSendStreamImplTest, DisablesPaddingOnPausedEncoder) {
787 int padding_bitrate = 0;
788 std::unique_ptr<VideoSendStreamImpl> vss_impl;
789
790 test_queue_.SendTask(
791 [&] {
792 vss_impl = CreateVideoSendStreamImpl(
793 kDefaultInitialBitrateBps, kDefaultBitratePriority,
794 VideoEncoderConfig::ContentType::kRealtimeVideo);
795
796 // Capture padding bitrate for testing.
797 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
798 .WillRepeatedly(Invoke([&](BitrateAllocatorObserver*,
799 MediaStreamAllocationConfig config) {
800 padding_bitrate = config.pad_up_bitrate_bps;
801 }));
802 // If observer is removed, no padding will be sent.
803 EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get()))
804 .WillRepeatedly(Invoke(
805 [&](BitrateAllocatorObserver*) { padding_bitrate = 0; }));
806
807 EXPECT_CALL(rtp_video_sender_, OnEncodedImage(_, _, _))
808 .WillRepeatedly(Return(EncodedImageCallback::Result(
809 EncodedImageCallback::Result::OK)));
810 const bool kSuspend = false;
811 config_.suspend_below_min_bitrate = kSuspend;
812 config_.rtp.extensions.emplace_back(
813 RtpExtension::kTransportSequenceNumberUri, 1);
814 VideoStream qvga_stream;
815 qvga_stream.width = 320;
816 qvga_stream.height = 180;
817 qvga_stream.max_framerate = 30;
818 qvga_stream.min_bitrate_bps = 30000;
819 qvga_stream.target_bitrate_bps = 150000;
820 qvga_stream.max_bitrate_bps = 200000;
821 qvga_stream.max_qp = 56;
822 qvga_stream.bitrate_priority = 1;
823
824 int min_transmit_bitrate_bps = 30000;
825
826 config_.rtp.ssrcs.emplace_back(1);
827
828 vss_impl->Start();
829
830 // Starts without padding.
831 EXPECT_EQ(0, padding_bitrate);
832
833 // Reconfigure e.g. due to a fake frame.
834 static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
835 ->OnEncoderConfigurationChanged(
836 std::vector<VideoStream>{qvga_stream}, false,
837 VideoEncoderConfig::ContentType::kRealtimeVideo,
838 min_transmit_bitrate_bps);
839 // Still no padding because no actual frames were passed, only
840 // reconfiguration happened.
841 EXPECT_EQ(0, padding_bitrate);
842
843 // Unpause encoder.
844 const uint32_t kBitrateBps = 100000;
845 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
846 .Times(1)
847 .WillOnce(Return(kBitrateBps));
848 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
849 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
850
851 // A frame is encoded.
852 EncodedImage encoded_image;
853 CodecSpecificInfo codec_specific;
854 static_cast<EncodedImageCallback*>(vss_impl.get())
855 ->OnEncodedImage(encoded_image, &codec_specific, nullptr);
856 // Only after actual frame is encoded are we enabling the padding.
857 EXPECT_GT(padding_bitrate, 0);
858 },
859 RTC_FROM_HERE);
860
861 rtc::Event done;
862 test_queue_.PostDelayedTask(
863 [&] {
864 // No padding supposed to be sent for paused observer
865 EXPECT_EQ(0, padding_bitrate);
866 testing::Mock::VerifyAndClearExpectations(&bitrate_allocator_);
867 vss_impl->Stop();
868 vss_impl.reset();
869 done.Set();
870 },
871 5000);
872
873 // Pause the test suite so that the last delayed task executes.
874 ASSERT_TRUE(done.Wait(10000));
875 }
876
TEST_F(VideoSendStreamImplTest,KeepAliveOnDroppedFrame)877 TEST_F(VideoSendStreamImplTest, KeepAliveOnDroppedFrame) {
878 std::unique_ptr<VideoSendStreamImpl> vss_impl;
879 test_queue_.SendTask(
880 [&] {
881 vss_impl = CreateVideoSendStreamImpl(
882 kDefaultInitialBitrateBps, kDefaultBitratePriority,
883 VideoEncoderConfig::ContentType::kRealtimeVideo);
884 vss_impl->Start();
885 const uint32_t kBitrateBps = 100000;
886 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
887 .Times(1)
888 .WillOnce(Return(kBitrateBps));
889 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
890 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
891
892 // Keep the stream from deallocating by dropping a frame.
893 static_cast<EncodedImageCallback*>(vss_impl.get())
894 ->OnDroppedFrame(
895 EncodedImageCallback::DropReason::kDroppedByEncoder);
896 EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get()))
897 .Times(0);
898 },
899 RTC_FROM_HERE);
900
901 rtc::Event done;
902 test_queue_.PostDelayedTask(
903 [&] {
904 testing::Mock::VerifyAndClearExpectations(&bitrate_allocator_);
905 vss_impl->Stop();
906 vss_impl.reset();
907 done.Set();
908 },
909 2000);
910 ASSERT_TRUE(done.Wait(5000));
911 }
912
TEST_F(VideoSendStreamImplTest,ConfiguresBitratesForSvc)913 TEST_F(VideoSendStreamImplTest, ConfiguresBitratesForSvc) {
914 struct TestConfig {
915 bool screenshare = false;
916 bool alr = false;
917 int min_padding_bitrate_bps = 0;
918 };
919
920 std::vector<TestConfig> test_variants;
921 for (bool screenshare : {false, true}) {
922 for (bool alr : {false, true}) {
923 for (int min_padding : {0, 400000}) {
924 test_variants.push_back({screenshare, alr, min_padding});
925 }
926 }
927 }
928
929 for (const TestConfig& test_config : test_variants) {
930 test_queue_.SendTask(
931 [this, test_config] {
932 const bool kSuspend = false;
933 config_.suspend_below_min_bitrate = kSuspend;
934 config_.rtp.extensions.emplace_back(
935 RtpExtension::kTransportSequenceNumberUri, 1);
936 config_.periodic_alr_bandwidth_probing = test_config.alr;
937 auto vss_impl = CreateVideoSendStreamImpl(
938 kDefaultInitialBitrateBps, kDefaultBitratePriority,
939 test_config.screenshare
940 ? VideoEncoderConfig::ContentType::kScreen
941 : VideoEncoderConfig::ContentType::kRealtimeVideo);
942 vss_impl->Start();
943
944 // Svc
945 VideoStream stream;
946 stream.width = 1920;
947 stream.height = 1080;
948 stream.max_framerate = 30;
949 stream.min_bitrate_bps = 60000;
950 stream.target_bitrate_bps = 6000000;
951 stream.max_bitrate_bps = 1250000;
952 stream.num_temporal_layers = 2;
953 stream.max_qp = 56;
954 stream.bitrate_priority = 1;
955
956 config_.rtp.ssrcs.emplace_back(1);
957 config_.rtp.ssrcs.emplace_back(2);
958
959 EXPECT_CALL(
960 bitrate_allocator_,
961 AddObserver(
962 vss_impl.get(),
963 AllOf(Field(&MediaStreamAllocationConfig::min_bitrate_bps,
964 static_cast<uint32_t>(stream.min_bitrate_bps)),
965 Field(&MediaStreamAllocationConfig::max_bitrate_bps,
966 static_cast<uint32_t>(stream.max_bitrate_bps)),
967 // Stream not yet active - no padding.
968 Field(&MediaStreamAllocationConfig::pad_up_bitrate_bps,
969 0u),
970 Field(&MediaStreamAllocationConfig::enforce_min_bitrate,
971 !kSuspend))));
972
973 static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
974 ->OnEncoderConfigurationChanged(
975 std::vector<VideoStream>{stream}, true,
976 test_config.screenshare
977 ? VideoEncoderConfig::ContentType::kScreen
978 : VideoEncoderConfig::ContentType::kRealtimeVideo,
979 test_config.min_padding_bitrate_bps);
980 ::testing::Mock::VerifyAndClearExpectations(&bitrate_allocator_);
981
982 // Simulate an encoded image, this will turn the stream active and
983 // enable padding.
984 EncodedImage encoded_image;
985 CodecSpecificInfo codec_specific;
986 EXPECT_CALL(rtp_video_sender_, OnEncodedImage)
987 .WillRepeatedly(Return(EncodedImageCallback::Result(
988 EncodedImageCallback::Result::OK)));
989
990 // Screensharing implicitly forces ALR.
991 const bool using_alr = test_config.alr || test_config.screenshare;
992 // If ALR is used, pads only to min bitrate as rampup is handled by
993 // probing. Otherwise target_bitrate contains the padding target.
994 int expected_padding =
995 using_alr ? stream.min_bitrate_bps : stream.target_bitrate_bps;
996 // Min padding bitrate may override padding target.
997 expected_padding =
998 std::max(expected_padding, test_config.min_padding_bitrate_bps);
999 EXPECT_CALL(
1000 bitrate_allocator_,
1001 AddObserver(
1002 vss_impl.get(),
1003 AllOf(Field(&MediaStreamAllocationConfig::min_bitrate_bps,
1004 static_cast<uint32_t>(stream.min_bitrate_bps)),
1005 Field(&MediaStreamAllocationConfig::max_bitrate_bps,
1006 static_cast<uint32_t>(stream.max_bitrate_bps)),
1007 // Stream now active - min bitrate use as padding target
1008 // when ALR is active.
1009 Field(&MediaStreamAllocationConfig::pad_up_bitrate_bps,
1010 expected_padding),
1011 Field(&MediaStreamAllocationConfig::enforce_min_bitrate,
1012 !kSuspend))));
1013 static_cast<EncodedImageCallback*>(vss_impl.get())
1014 ->OnEncodedImage(encoded_image, &codec_specific, nullptr);
1015 ::testing::Mock::VerifyAndClearExpectations(&bitrate_allocator_);
1016
1017 vss_impl->Stop();
1018 },
1019 RTC_FROM_HERE);
1020 }
1021 }
1022 } // namespace internal
1023 } // namespace webrtc
1024