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