blob: 41c039710b1f16e3f517cdcc45c4cea2361516b5 [file] [log] [blame]
Sebastian Jansson652dc912018-04-19 17:09:15 +02001/*
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 <string>
12
Steve Anton40d55332019-01-07 10:21:47 -080013#include "absl/memory/memory.h"
Stefan Holmer9416ef82018-07-19 10:34:38 +020014#include "call/rtp_video_sender.h"
Sebastian Jansson652dc912018-04-19 17:09:15 +020015#include "call/test/mock_bitrate_allocator.h"
16#include "call/test/mock_rtp_transport_controller_send.h"
17#include "logging/rtc_event_log/rtc_event_log.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020018#include "modules/utility/include/process_thread.h"
Sebastian Jansson652dc912018-04-19 17:09:15 +020019#include "modules/video_coding/fec_controller_default.h"
20#include "rtc_base/experiments/alr_experiment.h"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "rtc_base/fake_clock.h"
Sebastian Jansson652dc912018-04-19 17:09:15 +020022#include "rtc_base/task_queue_for_test.h"
23#include "test/field_trial.h"
24#include "test/gmock.h"
25#include "test/gtest.h"
26#include "test/mock_transport.h"
27#include "video/test/mock_video_stream_encoder.h"
28#include "video/video_send_stream_impl.h"
29
30namespace webrtc {
31namespace internal {
32namespace {
33using testing::NiceMock;
34using testing::StrictMock;
35using testing::ReturnRef;
36using testing::Return;
37using testing::Invoke;
38using testing::_;
39
40constexpr int64_t kDefaultInitialBitrateBps = 333000;
41const double kDefaultBitratePriority = 0.5;
42
43const float kAlrProbingExperimentPaceMultiplier = 1.0f;
44std::string GetAlrProbingExperimentString() {
45 return std::string(
46 AlrExperimentSettings::kScreenshareProbingBweExperimentName) +
47 "/1.0,2875,80,40,-60,3/";
48}
Stefan Holmer64be7fa2018-10-04 15:21:55 +020049class MockRtpVideoSender : public RtpVideoSenderInterface {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020050 public:
51 MOCK_METHOD1(RegisterProcessThread, void(ProcessThread*));
52 MOCK_METHOD0(DeRegisterProcessThread, void());
53 MOCK_METHOD1(SetActive, void(bool));
54 MOCK_METHOD1(SetActiveModules, void(const std::vector<bool>));
55 MOCK_METHOD0(IsActive, bool());
56 MOCK_METHOD1(OnNetworkAvailability, void(bool));
57 MOCK_CONST_METHOD0(GetRtpStates, std::map<uint32_t, RtpState>());
58 MOCK_CONST_METHOD0(GetRtpPayloadStates,
59 std::map<uint32_t, RtpPayloadState>());
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020060 MOCK_METHOD2(DeliverRtcp, void(const uint8_t*, size_t));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020061 MOCK_METHOD1(OnBitrateAllocationUpdated, void(const VideoBitrateAllocation&));
62 MOCK_METHOD3(OnEncodedImage,
63 EncodedImageCallback::Result(const EncodedImage&,
64 const CodecSpecificInfo*,
65 const RTPFragmentationHeader*));
Stefan Holmer64be7fa2018-10-04 15:21:55 +020066 MOCK_METHOD1(OnTransportOverheadChanged, void(size_t));
67 MOCK_METHOD1(OnOverheadChanged, void(size_t));
68 MOCK_METHOD4(OnBitrateUpdated, void(uint32_t, uint8_t, int64_t, int));
69 MOCK_CONST_METHOD0(GetPayloadBitrateBps, uint32_t());
70 MOCK_CONST_METHOD0(GetProtectionBitrateBps, uint32_t());
71 MOCK_METHOD3(SetEncodingData, void(size_t, size_t, size_t));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020072};
Sebastian Janssonc0e4d452018-10-25 15:08:32 +020073
74BitrateAllocationUpdate CreateAllocation(int bitrate_bps) {
75 BitrateAllocationUpdate update;
Sebastian Jansson13e59032018-11-21 19:13:07 +010076 update.target_bitrate = DataRate::bps(bitrate_bps);
77 update.packet_loss_ratio = 0;
78 update.round_trip_time = TimeDelta::Zero();
Sebastian Janssonc0e4d452018-10-25 15:08:32 +020079 return update;
80}
Sebastian Jansson652dc912018-04-19 17:09:15 +020081} // namespace
82
83class VideoSendStreamImplTest : public ::testing::Test {
84 protected:
85 VideoSendStreamImplTest()
86 : clock_(1000 * 1000 * 1000),
87 config_(&transport_),
88 send_delay_stats_(&clock_),
Sebastian Jansson652dc912018-04-19 17:09:15 +020089 test_queue_("test_queue"),
90 process_thread_(ProcessThread::Create("test_thread")),
91 call_stats_(&clock_, process_thread_.get()),
92 stats_proxy_(&clock_,
93 config_,
94 VideoEncoderConfig::ContentType::kRealtimeVideo) {
95 config_.rtp.ssrcs.push_back(8080);
96 config_.rtp.payload_type = 1;
97
98 EXPECT_CALL(transport_controller_, keepalive_config())
99 .WillRepeatedly(ReturnRef(keepalive_config_));
100 EXPECT_CALL(transport_controller_, packet_router())
101 .WillRepeatedly(Return(&packet_router_));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200102 EXPECT_CALL(transport_controller_,
Amit Hilbuch0fc28432018-12-18 13:01:47 -0800103 CreateRtpVideoSender(_, _, _, _, _, _, _, _, _))
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200104 .WillRepeatedly(Return(&rtp_video_sender_));
105 EXPECT_CALL(rtp_video_sender_, SetActive(_))
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200106 .WillRepeatedly(testing::Invoke(
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200107 [&](bool active) { rtp_video_sender_active_ = active; }));
108 EXPECT_CALL(rtp_video_sender_, IsActive())
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200109 .WillRepeatedly(
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200110 testing::Invoke([&]() { return rtp_video_sender_active_; }));
Sebastian Jansson652dc912018-04-19 17:09:15 +0200111 }
112 ~VideoSendStreamImplTest() {}
113
114 std::unique_ptr<VideoSendStreamImpl> CreateVideoSendStreamImpl(
115 int initial_encoder_max_bitrate,
116 double initial_encoder_bitrate_priority,
117 VideoEncoderConfig::ContentType content_type) {
118 EXPECT_CALL(bitrate_allocator_, GetStartBitrate(_))
119 .WillOnce(Return(123000));
120 std::map<uint32_t, RtpState> suspended_ssrcs;
121 std::map<uint32_t, RtpPayloadState> suspended_payload_states;
Karl Wiberg918f50c2018-07-05 11:40:33 +0200122 return absl::make_unique<VideoSendStreamImpl>(
Sebastian Jansson652dc912018-04-19 17:09:15 +0200123 &stats_proxy_, &test_queue_, &call_stats_, &transport_controller_,
124 &bitrate_allocator_, &send_delay_stats_, &video_stream_encoder_,
125 &event_log_, &config_, initial_encoder_max_bitrate,
126 initial_encoder_bitrate_priority, suspended_ssrcs,
127 suspended_payload_states, content_type,
Niels Möller46879152019-01-07 15:54:47 +0100128 absl::make_unique<FecControllerDefault>(&clock_),
129 /*media_transport=*/nullptr);
Sebastian Jansson652dc912018-04-19 17:09:15 +0200130 }
131
132 protected:
133 NiceMock<MockTransport> transport_;
134 NiceMock<MockRtpTransportControllerSend> transport_controller_;
135 NiceMock<MockBitrateAllocator> bitrate_allocator_;
136 NiceMock<MockVideoStreamEncoder> video_stream_encoder_;
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200137 NiceMock<MockRtpVideoSender> rtp_video_sender_;
Sebastian Jansson652dc912018-04-19 17:09:15 +0200138
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200139 bool rtp_video_sender_active_ = false;
Sebastian Jansson652dc912018-04-19 17:09:15 +0200140 SimulatedClock clock_;
141 RtcEventLogNullImpl event_log_;
142 VideoSendStream::Config config_;
143 SendDelayStats send_delay_stats_;
Sebastian Jansson652dc912018-04-19 17:09:15 +0200144 rtc::test::TaskQueueForTest test_queue_;
145 std::unique_ptr<ProcessThread> process_thread_;
146 CallStats call_stats_;
147 SendStatisticsProxy stats_proxy_;
148 PacketRouter packet_router_;
149 RtpKeepAliveConfig keepalive_config_;
150};
151
152TEST_F(VideoSendStreamImplTest, RegistersAsBitrateObserverOnStart) {
153 test_queue_.SendTask([this] {
154 config_.track_id = "test";
155 const bool kSuspend = false;
156 config_.suspend_below_min_bitrate = kSuspend;
157 auto vss_impl = CreateVideoSendStreamImpl(
158 kDefaultInitialBitrateBps, kDefaultBitratePriority,
159 VideoEncoderConfig::ContentType::kRealtimeVideo);
160 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
161 .WillOnce(Invoke(
162 [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
163 EXPECT_EQ(config.min_bitrate_bps, 0u);
164 EXPECT_EQ(config.max_bitrate_bps, kDefaultInitialBitrateBps);
165 EXPECT_EQ(config.pad_up_bitrate_bps, 0u);
166 EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
167 EXPECT_EQ(config.track_id, "test");
168 EXPECT_EQ(config.bitrate_priority, kDefaultBitratePriority);
Sebastian Jansson652dc912018-04-19 17:09:15 +0200169 }));
170 vss_impl->Start();
171 EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1);
172 vss_impl->Stop();
173 });
174}
175
Erik Språngb57ab382018-09-13 10:52:38 +0200176TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChange) {
177 test_queue_.SendTask([this] {
178 config_.track_id = "test";
179 const bool kSuspend = false;
180 config_.suspend_below_min_bitrate = kSuspend;
181 config_.rtp.extensions.emplace_back(
182 RtpExtension::kTransportSequenceNumberUri, 1);
183 auto vss_impl = CreateVideoSendStreamImpl(
184 kDefaultInitialBitrateBps, kDefaultBitratePriority,
185 VideoEncoderConfig::ContentType::kRealtimeVideo);
186 vss_impl->Start();
187
188 // QVGA + VGA configuration matching defaults in media/engine/simulcast.cc.
189 VideoStream qvga_stream;
190 qvga_stream.width = 320;
191 qvga_stream.height = 180;
192 qvga_stream.max_framerate = 30;
193 qvga_stream.min_bitrate_bps = 30000;
194 qvga_stream.target_bitrate_bps = 150000;
195 qvga_stream.max_bitrate_bps = 200000;
196 qvga_stream.max_qp = 56;
197 qvga_stream.bitrate_priority = 1;
198
199 VideoStream vga_stream;
200 vga_stream.width = 640;
201 vga_stream.height = 360;
202 vga_stream.max_framerate = 30;
203 vga_stream.min_bitrate_bps = 150000;
204 vga_stream.target_bitrate_bps = 500000;
205 vga_stream.max_bitrate_bps = 700000;
206 vga_stream.max_qp = 56;
207 vga_stream.bitrate_priority = 1;
208
209 int min_transmit_bitrate_bps = 30000;
210
211 config_.rtp.ssrcs.emplace_back(1);
212 config_.rtp.ssrcs.emplace_back(2);
213
214 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
215 .WillOnce(Invoke(
216 [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
217 EXPECT_EQ(config.min_bitrate_bps,
218 static_cast<uint32_t>(min_transmit_bitrate_bps));
219 EXPECT_EQ(config.max_bitrate_bps,
220 static_cast<uint32_t>(qvga_stream.max_bitrate_bps +
221 vga_stream.max_bitrate_bps));
222 EXPECT_EQ(config.pad_up_bitrate_bps,
223 static_cast<uint32_t>(qvga_stream.target_bitrate_bps +
224 vga_stream.min_bitrate_bps));
225 EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
Erik Språngb57ab382018-09-13 10:52:38 +0200226 }));
227
228 static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
229 ->OnEncoderConfigurationChanged(
230 std::vector<VideoStream>{qvga_stream, vga_stream},
Rasmus Brandtc402dbe2019-02-04 11:09:46 +0100231 VideoEncoderConfig::ContentType::kRealtimeVideo,
Erik Språngb57ab382018-09-13 10:52:38 +0200232 min_transmit_bitrate_bps);
233 vss_impl->Stop();
234 });
235}
236
237TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChangeWithAlr) {
238 test_queue_.SendTask([this] {
239 config_.track_id = "test";
240 const bool kSuspend = false;
241 config_.suspend_below_min_bitrate = kSuspend;
242 config_.rtp.extensions.emplace_back(
243 RtpExtension::kTransportSequenceNumberUri, 1);
244 config_.periodic_alr_bandwidth_probing = true;
245 auto vss_impl = CreateVideoSendStreamImpl(
246 kDefaultInitialBitrateBps, kDefaultBitratePriority,
247 VideoEncoderConfig::ContentType::kScreen);
248 vss_impl->Start();
249
250 // Simulcast screenshare.
251 VideoStream low_stream;
252 low_stream.width = 1920;
253 low_stream.height = 1080;
254 low_stream.max_framerate = 5;
255 low_stream.min_bitrate_bps = 30000;
256 low_stream.target_bitrate_bps = 200000;
257 low_stream.max_bitrate_bps = 1000000;
258 low_stream.num_temporal_layers = 2;
259 low_stream.max_qp = 56;
260 low_stream.bitrate_priority = 1;
261
262 VideoStream high_stream;
263 high_stream.width = 1920;
264 high_stream.height = 1080;
265 high_stream.max_framerate = 30;
266 high_stream.min_bitrate_bps = 60000;
267 high_stream.target_bitrate_bps = 1250000;
268 high_stream.max_bitrate_bps = 1250000;
269 high_stream.num_temporal_layers = 2;
270 high_stream.max_qp = 56;
271 high_stream.bitrate_priority = 1;
272
273 // With ALR probing, this will be the padding target instead of
274 // low_stream.target_bitrate_bps + high_stream.min_bitrate_bps.
275 int min_transmit_bitrate_bps = 400000;
276
277 config_.rtp.ssrcs.emplace_back(1);
278 config_.rtp.ssrcs.emplace_back(2);
279
280 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
281 .WillOnce(Invoke(
282 [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
283 EXPECT_EQ(config.min_bitrate_bps,
284 static_cast<uint32_t>(low_stream.min_bitrate_bps));
285 EXPECT_EQ(config.max_bitrate_bps,
286 static_cast<uint32_t>(low_stream.max_bitrate_bps +
287 high_stream.max_bitrate_bps));
288 EXPECT_EQ(config.pad_up_bitrate_bps,
289 static_cast<uint32_t>(min_transmit_bitrate_bps));
290 EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
Erik Språngb57ab382018-09-13 10:52:38 +0200291 }));
292
293 static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
294 ->OnEncoderConfigurationChanged(
295 std::vector<VideoStream>{low_stream, high_stream},
Rasmus Brandtc402dbe2019-02-04 11:09:46 +0100296 VideoEncoderConfig::ContentType::kScreen, min_transmit_bitrate_bps);
297 vss_impl->Stop();
298 });
299}
300
301TEST_F(VideoSendStreamImplTest,
302 UpdatesObserverOnConfigurationChangeWithSimulcastVideoHysteresis) {
303 test::ScopedFieldTrials hysteresis_experiment(
304 "WebRTC-VideoRateControl/video_hysteresis:1.25/");
305
306 test_queue_.SendTask([this] {
307 auto vss_impl = CreateVideoSendStreamImpl(
308 kDefaultInitialBitrateBps, kDefaultBitratePriority,
309 VideoEncoderConfig::ContentType::kRealtimeVideo);
310 vss_impl->Start();
311
312 // 2-layer video simulcast.
313 VideoStream low_stream;
314 low_stream.width = 320;
315 low_stream.height = 240;
316 low_stream.max_framerate = 30;
317 low_stream.min_bitrate_bps = 30000;
318 low_stream.target_bitrate_bps = 100000;
319 low_stream.max_bitrate_bps = 200000;
320 low_stream.max_qp = 56;
321 low_stream.bitrate_priority = 1;
322
323 VideoStream high_stream;
324 high_stream.width = 640;
325 high_stream.height = 480;
326 high_stream.max_framerate = 30;
327 high_stream.min_bitrate_bps = 150000;
328 high_stream.target_bitrate_bps = 500000;
329 high_stream.max_bitrate_bps = 750000;
330 high_stream.max_qp = 56;
331 high_stream.bitrate_priority = 1;
332
333 config_.rtp.ssrcs.emplace_back(1);
334 config_.rtp.ssrcs.emplace_back(2);
335
336 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
337 .WillOnce(Invoke([&](BitrateAllocatorObserver*,
338 MediaStreamAllocationConfig config) {
339 EXPECT_EQ(config.min_bitrate_bps,
340 static_cast<uint32_t>(low_stream.min_bitrate_bps));
341 EXPECT_EQ(config.max_bitrate_bps,
342 static_cast<uint32_t>(low_stream.max_bitrate_bps +
343 high_stream.max_bitrate_bps));
344 EXPECT_EQ(config.pad_up_bitrate_bps,
345 static_cast<uint32_t>(low_stream.target_bitrate_bps +
346 1.25 * high_stream.min_bitrate_bps));
347 }));
348
349 static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
350 ->OnEncoderConfigurationChanged(
351 std::vector<VideoStream>{low_stream, high_stream},
352 VideoEncoderConfig::ContentType::kRealtimeVideo,
353 /*min_transmit_bitrate_bps=*/0);
Erik Språngb57ab382018-09-13 10:52:38 +0200354 vss_impl->Stop();
355 });
356}
357
Sebastian Jansson652dc912018-04-19 17:09:15 +0200358TEST_F(VideoSendStreamImplTest, SetsScreensharePacingFactorWithFeedback) {
359 test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString());
360
361 test_queue_.SendTask([this] {
362 config_.rtp.extensions.emplace_back(
363 RtpExtension::kTransportSequenceNumberUri,
364 RtpExtension::kTransportSequenceNumberDefaultId);
365 EXPECT_CALL(transport_controller_,
366 SetPacingFactor(kAlrProbingExperimentPaceMultiplier))
367 .Times(1);
368 auto vss_impl = CreateVideoSendStreamImpl(
369 kDefaultInitialBitrateBps, kDefaultBitratePriority,
370 VideoEncoderConfig::ContentType::kScreen);
371 vss_impl->Start();
372 vss_impl->Stop();
373 });
374}
375
376TEST_F(VideoSendStreamImplTest, DoesNotSetPacingFactorWithoutFeedback) {
377 test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString());
378 test_queue_.SendTask([this] {
379 EXPECT_CALL(transport_controller_, SetPacingFactor(_)).Times(0);
380 auto vss_impl = CreateVideoSendStreamImpl(
381 kDefaultInitialBitrateBps, kDefaultBitratePriority,
382 VideoEncoderConfig::ContentType::kScreen);
383 vss_impl->Start();
384 vss_impl->Stop();
385 });
386}
Erik Språng4e193e42018-09-14 19:01:58 +0200387
388TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationWhenEnabled) {
389 test_queue_.SendTask([this] {
390 EXPECT_CALL(transport_controller_, SetPacingFactor(_)).Times(0);
391 auto vss_impl = CreateVideoSendStreamImpl(
392 kDefaultInitialBitrateBps, kDefaultBitratePriority,
393 VideoEncoderConfig::ContentType::kScreen);
394 vss_impl->Start();
395 VideoBitrateAllocationObserver* const observer =
396 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
397
398 // Populate a test instance of video bitrate allocation.
399 VideoBitrateAllocation alloc;
400 alloc.SetBitrate(0, 0, 10000);
401 alloc.SetBitrate(0, 1, 20000);
402 alloc.SetBitrate(1, 0, 30000);
403 alloc.SetBitrate(1, 1, 40000);
404
405 // Encoder starts out paused, don't forward allocation.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200406 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc)).Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200407 observer->OnBitrateAllocationUpdated(alloc);
408
409 // Unpause encoder, allocation should be passed through.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200410 const uint32_t kBitrateBps = 100000;
411 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
412 .Times(1)
413 .WillOnce(Return(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200414 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
Sebastian Janssonc0e4d452018-10-25 15:08:32 +0200415 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200416 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc)).Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200417 observer->OnBitrateAllocationUpdated(alloc);
418
419 // Pause encoder again, and block allocations.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200420 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
421 .Times(1)
422 .WillOnce(Return(0));
Erik Språng4e193e42018-09-14 19:01:58 +0200423 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
Sebastian Janssonc0e4d452018-10-25 15:08:32 +0200424 ->OnBitrateUpdated(CreateAllocation(0));
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200425 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc)).Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200426 observer->OnBitrateAllocationUpdated(alloc);
427
428 vss_impl->Stop();
429 });
430}
431
432TEST_F(VideoSendStreamImplTest, ThrottlesVideoBitrateAllocationWhenTooSimilar) {
433 test_queue_.SendTask([this] {
434 auto vss_impl = CreateVideoSendStreamImpl(
435 kDefaultInitialBitrateBps, kDefaultBitratePriority,
436 VideoEncoderConfig::ContentType::kScreen);
437 vss_impl->Start();
438 // Unpause encoder, to allows allocations to be passed through.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200439 const uint32_t kBitrateBps = 100000;
440 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
441 .Times(1)
442 .WillOnce(Return(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200443 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
Sebastian Janssonc0e4d452018-10-25 15:08:32 +0200444 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200445 VideoBitrateAllocationObserver* const observer =
446 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
447
448 // Populate a test instance of video bitrate allocation.
449 VideoBitrateAllocation alloc;
450 alloc.SetBitrate(0, 0, 10000);
451 alloc.SetBitrate(0, 1, 20000);
452 alloc.SetBitrate(1, 0, 30000);
453 alloc.SetBitrate(1, 1, 40000);
454
455 // Initial value.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200456 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc)).Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200457 observer->OnBitrateAllocationUpdated(alloc);
458
459 VideoBitrateAllocation updated_alloc = alloc;
460 // Needs 10% increase in bitrate to trigger immediate forward.
461 const uint32_t base_layer_min_update_bitrate_bps =
462 alloc.GetBitrate(0, 0) + alloc.get_sum_bps() / 10;
463
464 // Too small increase, don't forward.
465 updated_alloc.SetBitrate(0, 0, base_layer_min_update_bitrate_bps - 1);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200466 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(_)).Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200467 observer->OnBitrateAllocationUpdated(updated_alloc);
468
469 // Large enough increase, do forward.
470 updated_alloc.SetBitrate(0, 0, base_layer_min_update_bitrate_bps);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200471 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(updated_alloc))
Erik Språng4e193e42018-09-14 19:01:58 +0200472 .Times(1);
473 observer->OnBitrateAllocationUpdated(updated_alloc);
474
475 // This is now a decrease compared to last forward allocation, forward
476 // immediately.
477 updated_alloc.SetBitrate(0, 0, base_layer_min_update_bitrate_bps - 1);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200478 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(updated_alloc))
Erik Språng4e193e42018-09-14 19:01:58 +0200479 .Times(1);
480 observer->OnBitrateAllocationUpdated(updated_alloc);
481
482 vss_impl->Stop();
483 });
484}
485
486TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationOnLayerChange) {
487 test_queue_.SendTask([this] {
488 auto vss_impl = CreateVideoSendStreamImpl(
489 kDefaultInitialBitrateBps, kDefaultBitratePriority,
490 VideoEncoderConfig::ContentType::kScreen);
491 vss_impl->Start();
492 // Unpause encoder, to allows allocations to be passed through.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200493 const uint32_t kBitrateBps = 100000;
494 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
495 .Times(1)
496 .WillOnce(Return(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200497 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
Sebastian Janssonc0e4d452018-10-25 15:08:32 +0200498 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200499 VideoBitrateAllocationObserver* const observer =
500 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
501
502 // Populate a test instance of video bitrate allocation.
503 VideoBitrateAllocation alloc;
504 alloc.SetBitrate(0, 0, 10000);
505 alloc.SetBitrate(0, 1, 20000);
506 alloc.SetBitrate(1, 0, 30000);
507 alloc.SetBitrate(1, 1, 40000);
508
509 // Initial value.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200510 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc)).Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200511 observer->OnBitrateAllocationUpdated(alloc);
512
513 // Move some bitrate from one layer to a new one, but keep sum the same.
514 // Since layout has changed, immediately trigger forward.
515 VideoBitrateAllocation updated_alloc = alloc;
516 updated_alloc.SetBitrate(2, 0, 10000);
517 updated_alloc.SetBitrate(1, 1, alloc.GetBitrate(1, 1) - 10000);
518 EXPECT_EQ(alloc.get_sum_bps(), updated_alloc.get_sum_bps());
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200519 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(updated_alloc))
Erik Språng4e193e42018-09-14 19:01:58 +0200520 .Times(1);
521 observer->OnBitrateAllocationUpdated(updated_alloc);
522
523 vss_impl->Stop();
524 });
525}
526
527TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationAfterTimeout) {
528 test_queue_.SendTask([this] {
529 rtc::ScopedFakeClock fake_clock;
530 fake_clock.SetTimeMicros(clock_.TimeInMicroseconds());
531
532 auto vss_impl = CreateVideoSendStreamImpl(
533 kDefaultInitialBitrateBps, kDefaultBitratePriority,
534 VideoEncoderConfig::ContentType::kScreen);
535 vss_impl->Start();
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200536 const uint32_t kBitrateBps = 100000;
Erik Språng4e193e42018-09-14 19:01:58 +0200537 // Unpause encoder, to allows allocations to be passed through.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200538 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
539 .Times(1)
540 .WillRepeatedly(Return(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200541 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
Sebastian Janssonc0e4d452018-10-25 15:08:32 +0200542 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200543 VideoBitrateAllocationObserver* const observer =
544 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
545
546 // Populate a test instance of video bitrate allocation.
547 VideoBitrateAllocation alloc;
548 alloc.SetBitrate(0, 0, 10000);
549 alloc.SetBitrate(0, 1, 20000);
550 alloc.SetBitrate(1, 0, 30000);
551 alloc.SetBitrate(1, 1, 40000);
552
553 EncodedImage encoded_image;
554 CodecSpecificInfo codec_specific;
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200555 EXPECT_CALL(rtp_video_sender_, OnEncodedImage(_, _, _))
Erik Språng4e193e42018-09-14 19:01:58 +0200556 .WillRepeatedly(Return(
557 EncodedImageCallback::Result(EncodedImageCallback::Result::OK)));
558
559 // Max time we will throttle similar video bitrate allocations.
560 static constexpr int64_t kMaxVbaThrottleTimeMs = 500;
561
562 {
563 // Initial value.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200564 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
565 .Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200566 observer->OnBitrateAllocationUpdated(alloc);
567 }
568
569 {
570 // Sending same allocation again, this one should be throttled.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200571 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
572 .Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200573 observer->OnBitrateAllocationUpdated(alloc);
574 }
575
576 fake_clock.AdvanceTimeMicros(kMaxVbaThrottleTimeMs * 1000);
577
578 {
579 // Sending similar allocation again after timeout, should forward.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200580 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
581 .Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200582 observer->OnBitrateAllocationUpdated(alloc);
583 }
584
585 {
586 // Sending similar allocation again without timeout, throttle.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200587 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
588 .Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200589 observer->OnBitrateAllocationUpdated(alloc);
590 }
591
592 {
593 // Send encoded image, should be a noop.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200594 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
595 .Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200596 static_cast<EncodedImageCallback*>(vss_impl.get())
597 ->OnEncodedImage(encoded_image, &codec_specific, nullptr);
598 }
599
600 {
601 // Advance time and send encoded image, this should wake up and send
602 // cached bitrate allocation.
603 fake_clock.AdvanceTimeMicros(kMaxVbaThrottleTimeMs * 1000);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200604 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
605 .Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200606 static_cast<EncodedImageCallback*>(vss_impl.get())
607 ->OnEncodedImage(encoded_image, &codec_specific, nullptr);
608 }
609
610 {
611 // Advance time and send encoded image, there should be no cached
612 // allocation to send.
613 fake_clock.AdvanceTimeMicros(kMaxVbaThrottleTimeMs * 1000);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200614 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
615 .Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200616 static_cast<EncodedImageCallback*>(vss_impl.get())
617 ->OnEncodedImage(encoded_image, &codec_specific, nullptr);
618 }
619
620 vss_impl->Stop();
621 });
622}
623
Sebastian Jansson652dc912018-04-19 17:09:15 +0200624} // namespace internal
625} // namespace webrtc