blob: 32d0df1c2e61b7dc5efcdae83f63a41881071371 [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
Stefan Holmer9416ef82018-07-19 10:34:38 +020013#include "call/rtp_video_sender.h"
Sebastian Jansson652dc912018-04-19 17:09:15 +020014#include "call/test/mock_bitrate_allocator.h"
15#include "call/test/mock_rtp_transport_controller_send.h"
16#include "logging/rtc_event_log/rtc_event_log.h"
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020017#include "modules/utility/include/process_thread.h"
Sebastian Jansson652dc912018-04-19 17:09:15 +020018#include "modules/video_coding/fec_controller_default.h"
19#include "rtc_base/experiments/alr_experiment.h"
Erik Språng4e193e42018-09-14 19:01:58 +020020#include "rtc_base/fakeclock.h"
Sebastian Jansson652dc912018-04-19 17:09:15 +020021#include "rtc_base/task_queue_for_test.h"
22#include "test/field_trial.h"
23#include "test/gmock.h"
24#include "test/gtest.h"
25#include "test/mock_transport.h"
26#include "video/test/mock_video_stream_encoder.h"
27#include "video/video_send_stream_impl.h"
28
29namespace webrtc {
30namespace internal {
31namespace {
32using testing::NiceMock;
33using testing::StrictMock;
34using testing::ReturnRef;
35using testing::Return;
36using testing::Invoke;
37using testing::_;
38
39constexpr int64_t kDefaultInitialBitrateBps = 333000;
40const double kDefaultBitratePriority = 0.5;
41
42const float kAlrProbingExperimentPaceMultiplier = 1.0f;
43std::string GetAlrProbingExperimentString() {
44 return std::string(
45 AlrExperimentSettings::kScreenshareProbingBweExperimentName) +
46 "/1.0,2875,80,40,-60,3/";
47}
Stefan Holmer64be7fa2018-10-04 15:21:55 +020048class MockRtpVideoSender : public RtpVideoSenderInterface {
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020049 public:
50 MOCK_METHOD1(RegisterProcessThread, void(ProcessThread*));
51 MOCK_METHOD0(DeRegisterProcessThread, void());
52 MOCK_METHOD1(SetActive, void(bool));
53 MOCK_METHOD1(SetActiveModules, void(const std::vector<bool>));
54 MOCK_METHOD0(IsActive, bool());
55 MOCK_METHOD1(OnNetworkAvailability, void(bool));
56 MOCK_CONST_METHOD0(GetRtpStates, std::map<uint32_t, RtpState>());
57 MOCK_CONST_METHOD0(GetRtpPayloadStates,
58 std::map<uint32_t, RtpPayloadState>());
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020059 MOCK_METHOD2(DeliverRtcp, void(const uint8_t*, size_t));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020060 MOCK_METHOD1(OnBitrateAllocationUpdated, void(const VideoBitrateAllocation&));
61 MOCK_METHOD3(OnEncodedImage,
62 EncodedImageCallback::Result(const EncodedImage&,
63 const CodecSpecificInfo*,
64 const RTPFragmentationHeader*));
Stefan Holmer64be7fa2018-10-04 15:21:55 +020065 MOCK_METHOD1(OnTransportOverheadChanged, void(size_t));
66 MOCK_METHOD1(OnOverheadChanged, void(size_t));
67 MOCK_METHOD4(OnBitrateUpdated, void(uint32_t, uint8_t, int64_t, int));
68 MOCK_CONST_METHOD0(GetPayloadBitrateBps, uint32_t());
69 MOCK_CONST_METHOD0(GetProtectionBitrateBps, uint32_t());
70 MOCK_METHOD3(SetEncodingData, void(size_t, size_t, size_t));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +020071};
Sebastian Janssonc0e4d452018-10-25 15:08:32 +020072
73BitrateAllocationUpdate CreateAllocation(int bitrate_bps) {
74 BitrateAllocationUpdate update;
Sebastian Jansson13e59032018-11-21 19:13:07 +010075 update.target_bitrate = DataRate::bps(bitrate_bps);
76 update.packet_loss_ratio = 0;
77 update.round_trip_time = TimeDelta::Zero();
Sebastian Janssonc0e4d452018-10-25 15:08:32 +020078 return update;
79}
Sebastian Jansson652dc912018-04-19 17:09:15 +020080} // namespace
81
82class VideoSendStreamImplTest : public ::testing::Test {
83 protected:
84 VideoSendStreamImplTest()
85 : clock_(1000 * 1000 * 1000),
86 config_(&transport_),
87 send_delay_stats_(&clock_),
Sebastian Jansson652dc912018-04-19 17:09:15 +020088 test_queue_("test_queue"),
89 process_thread_(ProcessThread::Create("test_thread")),
90 call_stats_(&clock_, process_thread_.get()),
91 stats_proxy_(&clock_,
92 config_,
93 VideoEncoderConfig::ContentType::kRealtimeVideo) {
94 config_.rtp.ssrcs.push_back(8080);
95 config_.rtp.payload_type = 1;
96
97 EXPECT_CALL(transport_controller_, keepalive_config())
98 .WillRepeatedly(ReturnRef(keepalive_config_));
99 EXPECT_CALL(transport_controller_, packet_router())
100 .WillRepeatedly(Return(&packet_router_));
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200101 EXPECT_CALL(transport_controller_,
Benjamin Wright192eeec2018-10-17 17:27:25 -0700102 CreateRtpVideoSender(_, _, _, _, _, _, _, _, _, _))
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200103 .WillRepeatedly(Return(&rtp_video_sender_));
104 EXPECT_CALL(rtp_video_sender_, SetActive(_))
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200105 .WillRepeatedly(testing::Invoke(
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200106 [&](bool active) { rtp_video_sender_active_ = active; }));
107 EXPECT_CALL(rtp_video_sender_, IsActive())
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200108 .WillRepeatedly(
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200109 testing::Invoke([&]() { return rtp_video_sender_active_; }));
Sebastian Jansson652dc912018-04-19 17:09:15 +0200110 }
111 ~VideoSendStreamImplTest() {}
112
113 std::unique_ptr<VideoSendStreamImpl> CreateVideoSendStreamImpl(
114 int initial_encoder_max_bitrate,
115 double initial_encoder_bitrate_priority,
116 VideoEncoderConfig::ContentType content_type) {
117 EXPECT_CALL(bitrate_allocator_, GetStartBitrate(_))
118 .WillOnce(Return(123000));
119 std::map<uint32_t, RtpState> suspended_ssrcs;
120 std::map<uint32_t, RtpPayloadState> suspended_payload_states;
Karl Wiberg918f50c2018-07-05 11:40:33 +0200121 return absl::make_unique<VideoSendStreamImpl>(
Sebastian Jansson652dc912018-04-19 17:09:15 +0200122 &stats_proxy_, &test_queue_, &call_stats_, &transport_controller_,
123 &bitrate_allocator_, &send_delay_stats_, &video_stream_encoder_,
124 &event_log_, &config_, initial_encoder_max_bitrate,
125 initial_encoder_bitrate_priority, suspended_ssrcs,
126 suspended_payload_states, content_type,
Stefan Holmerdbdb3a02018-07-17 16:03:46 +0200127 absl::make_unique<FecControllerDefault>(&clock_));
Sebastian Jansson652dc912018-04-19 17:09:15 +0200128 }
129
130 protected:
131 NiceMock<MockTransport> transport_;
132 NiceMock<MockRtpTransportControllerSend> transport_controller_;
133 NiceMock<MockBitrateAllocator> bitrate_allocator_;
134 NiceMock<MockVideoStreamEncoder> video_stream_encoder_;
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200135 NiceMock<MockRtpVideoSender> rtp_video_sender_;
Sebastian Jansson652dc912018-04-19 17:09:15 +0200136
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200137 bool rtp_video_sender_active_ = false;
Sebastian Jansson652dc912018-04-19 17:09:15 +0200138 SimulatedClock clock_;
139 RtcEventLogNullImpl event_log_;
140 VideoSendStream::Config config_;
141 SendDelayStats send_delay_stats_;
Sebastian Jansson652dc912018-04-19 17:09:15 +0200142 rtc::test::TaskQueueForTest test_queue_;
143 std::unique_ptr<ProcessThread> process_thread_;
144 CallStats call_stats_;
145 SendStatisticsProxy stats_proxy_;
146 PacketRouter packet_router_;
147 RtpKeepAliveConfig keepalive_config_;
148};
149
150TEST_F(VideoSendStreamImplTest, RegistersAsBitrateObserverOnStart) {
151 test_queue_.SendTask([this] {
152 config_.track_id = "test";
153 const bool kSuspend = false;
154 config_.suspend_below_min_bitrate = kSuspend;
155 auto vss_impl = CreateVideoSendStreamImpl(
156 kDefaultInitialBitrateBps, kDefaultBitratePriority,
157 VideoEncoderConfig::ContentType::kRealtimeVideo);
158 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
159 .WillOnce(Invoke(
160 [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
161 EXPECT_EQ(config.min_bitrate_bps, 0u);
162 EXPECT_EQ(config.max_bitrate_bps, kDefaultInitialBitrateBps);
163 EXPECT_EQ(config.pad_up_bitrate_bps, 0u);
164 EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
165 EXPECT_EQ(config.track_id, "test");
166 EXPECT_EQ(config.bitrate_priority, kDefaultBitratePriority);
167 EXPECT_EQ(config.has_packet_feedback, false);
168 }));
169 vss_impl->Start();
170 EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1);
171 vss_impl->Stop();
172 });
173}
174
Erik Språngb57ab382018-09-13 10:52:38 +0200175TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChange) {
176 test_queue_.SendTask([this] {
177 config_.track_id = "test";
178 const bool kSuspend = false;
179 config_.suspend_below_min_bitrate = kSuspend;
180 config_.rtp.extensions.emplace_back(
181 RtpExtension::kTransportSequenceNumberUri, 1);
182 auto vss_impl = CreateVideoSendStreamImpl(
183 kDefaultInitialBitrateBps, kDefaultBitratePriority,
184 VideoEncoderConfig::ContentType::kRealtimeVideo);
185 vss_impl->Start();
186
187 // QVGA + VGA configuration matching defaults in media/engine/simulcast.cc.
188 VideoStream qvga_stream;
189 qvga_stream.width = 320;
190 qvga_stream.height = 180;
191 qvga_stream.max_framerate = 30;
192 qvga_stream.min_bitrate_bps = 30000;
193 qvga_stream.target_bitrate_bps = 150000;
194 qvga_stream.max_bitrate_bps = 200000;
195 qvga_stream.max_qp = 56;
196 qvga_stream.bitrate_priority = 1;
197
198 VideoStream vga_stream;
199 vga_stream.width = 640;
200 vga_stream.height = 360;
201 vga_stream.max_framerate = 30;
202 vga_stream.min_bitrate_bps = 150000;
203 vga_stream.target_bitrate_bps = 500000;
204 vga_stream.max_bitrate_bps = 700000;
205 vga_stream.max_qp = 56;
206 vga_stream.bitrate_priority = 1;
207
208 int min_transmit_bitrate_bps = 30000;
209
210 config_.rtp.ssrcs.emplace_back(1);
211 config_.rtp.ssrcs.emplace_back(2);
212
213 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
214 .WillOnce(Invoke(
215 [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
216 EXPECT_EQ(config.min_bitrate_bps,
217 static_cast<uint32_t>(min_transmit_bitrate_bps));
218 EXPECT_EQ(config.max_bitrate_bps,
219 static_cast<uint32_t>(qvga_stream.max_bitrate_bps +
220 vga_stream.max_bitrate_bps));
221 EXPECT_EQ(config.pad_up_bitrate_bps,
222 static_cast<uint32_t>(qvga_stream.target_bitrate_bps +
223 vga_stream.min_bitrate_bps));
224 EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
225 EXPECT_EQ(config.has_packet_feedback, true);
226 }));
227
228 static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
229 ->OnEncoderConfigurationChanged(
230 std::vector<VideoStream>{qvga_stream, vga_stream},
231 min_transmit_bitrate_bps);
232 vss_impl->Stop();
233 });
234}
235
236TEST_F(VideoSendStreamImplTest, UpdatesObserverOnConfigurationChangeWithAlr) {
237 test_queue_.SendTask([this] {
238 config_.track_id = "test";
239 const bool kSuspend = false;
240 config_.suspend_below_min_bitrate = kSuspend;
241 config_.rtp.extensions.emplace_back(
242 RtpExtension::kTransportSequenceNumberUri, 1);
243 config_.periodic_alr_bandwidth_probing = true;
244 auto vss_impl = CreateVideoSendStreamImpl(
245 kDefaultInitialBitrateBps, kDefaultBitratePriority,
246 VideoEncoderConfig::ContentType::kScreen);
247 vss_impl->Start();
248
249 // Simulcast screenshare.
250 VideoStream low_stream;
251 low_stream.width = 1920;
252 low_stream.height = 1080;
253 low_stream.max_framerate = 5;
254 low_stream.min_bitrate_bps = 30000;
255 low_stream.target_bitrate_bps = 200000;
256 low_stream.max_bitrate_bps = 1000000;
257 low_stream.num_temporal_layers = 2;
258 low_stream.max_qp = 56;
259 low_stream.bitrate_priority = 1;
260
261 VideoStream high_stream;
262 high_stream.width = 1920;
263 high_stream.height = 1080;
264 high_stream.max_framerate = 30;
265 high_stream.min_bitrate_bps = 60000;
266 high_stream.target_bitrate_bps = 1250000;
267 high_stream.max_bitrate_bps = 1250000;
268 high_stream.num_temporal_layers = 2;
269 high_stream.max_qp = 56;
270 high_stream.bitrate_priority = 1;
271
272 // With ALR probing, this will be the padding target instead of
273 // low_stream.target_bitrate_bps + high_stream.min_bitrate_bps.
274 int min_transmit_bitrate_bps = 400000;
275
276 config_.rtp.ssrcs.emplace_back(1);
277 config_.rtp.ssrcs.emplace_back(2);
278
279 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
280 .WillOnce(Invoke(
281 [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
282 EXPECT_EQ(config.min_bitrate_bps,
283 static_cast<uint32_t>(low_stream.min_bitrate_bps));
284 EXPECT_EQ(config.max_bitrate_bps,
285 static_cast<uint32_t>(low_stream.max_bitrate_bps +
286 high_stream.max_bitrate_bps));
287 EXPECT_EQ(config.pad_up_bitrate_bps,
288 static_cast<uint32_t>(min_transmit_bitrate_bps));
289 EXPECT_EQ(config.enforce_min_bitrate, !kSuspend);
290 EXPECT_EQ(config.has_packet_feedback, true);
291 }));
292
293 static_cast<VideoStreamEncoderInterface::EncoderSink*>(vss_impl.get())
294 ->OnEncoderConfigurationChanged(
295 std::vector<VideoStream>{low_stream, high_stream},
296 min_transmit_bitrate_bps);
297 vss_impl->Stop();
298 });
299}
300
Sebastian Jansson652dc912018-04-19 17:09:15 +0200301TEST_F(VideoSendStreamImplTest, ReportFeedbackAvailability) {
302 test_queue_.SendTask([this] {
303 config_.rtp.extensions.emplace_back(
304 RtpExtension::kTransportSequenceNumberUri,
305 RtpExtension::kTransportSequenceNumberDefaultId);
306
307 auto vss_impl = CreateVideoSendStreamImpl(
308 kDefaultInitialBitrateBps, kDefaultBitratePriority,
309 VideoEncoderConfig::ContentType::kRealtimeVideo);
310 EXPECT_CALL(bitrate_allocator_, AddObserver(vss_impl.get(), _))
311 .WillOnce(Invoke(
312 [&](BitrateAllocatorObserver*, MediaStreamAllocationConfig config) {
313 EXPECT_EQ(config.has_packet_feedback, true);
314 }));
315 vss_impl->Start();
316 EXPECT_CALL(bitrate_allocator_, RemoveObserver(vss_impl.get())).Times(1);
317 vss_impl->Stop();
318 });
319}
320
321TEST_F(VideoSendStreamImplTest, SetsScreensharePacingFactorWithFeedback) {
322 test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString());
323
324 test_queue_.SendTask([this] {
325 config_.rtp.extensions.emplace_back(
326 RtpExtension::kTransportSequenceNumberUri,
327 RtpExtension::kTransportSequenceNumberDefaultId);
328 EXPECT_CALL(transport_controller_,
329 SetPacingFactor(kAlrProbingExperimentPaceMultiplier))
330 .Times(1);
331 auto vss_impl = CreateVideoSendStreamImpl(
332 kDefaultInitialBitrateBps, kDefaultBitratePriority,
333 VideoEncoderConfig::ContentType::kScreen);
334 vss_impl->Start();
335 vss_impl->Stop();
336 });
337}
338
339TEST_F(VideoSendStreamImplTest, DoesNotSetPacingFactorWithoutFeedback) {
340 test::ScopedFieldTrials alr_experiment(GetAlrProbingExperimentString());
341 test_queue_.SendTask([this] {
342 EXPECT_CALL(transport_controller_, SetPacingFactor(_)).Times(0);
343 auto vss_impl = CreateVideoSendStreamImpl(
344 kDefaultInitialBitrateBps, kDefaultBitratePriority,
345 VideoEncoderConfig::ContentType::kScreen);
346 vss_impl->Start();
347 vss_impl->Stop();
348 });
349}
Erik Språng4e193e42018-09-14 19:01:58 +0200350
351TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationWhenEnabled) {
352 test_queue_.SendTask([this] {
353 EXPECT_CALL(transport_controller_, SetPacingFactor(_)).Times(0);
354 auto vss_impl = CreateVideoSendStreamImpl(
355 kDefaultInitialBitrateBps, kDefaultBitratePriority,
356 VideoEncoderConfig::ContentType::kScreen);
357 vss_impl->Start();
358 VideoBitrateAllocationObserver* const observer =
359 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
360
361 // Populate a test instance of video bitrate allocation.
362 VideoBitrateAllocation alloc;
363 alloc.SetBitrate(0, 0, 10000);
364 alloc.SetBitrate(0, 1, 20000);
365 alloc.SetBitrate(1, 0, 30000);
366 alloc.SetBitrate(1, 1, 40000);
367
368 // Encoder starts out paused, don't forward allocation.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200369 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc)).Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200370 observer->OnBitrateAllocationUpdated(alloc);
371
372 // Unpause encoder, allocation should be passed through.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200373 const uint32_t kBitrateBps = 100000;
374 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
375 .Times(1)
376 .WillOnce(Return(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200377 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
Sebastian Janssonc0e4d452018-10-25 15:08:32 +0200378 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200379 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc)).Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200380 observer->OnBitrateAllocationUpdated(alloc);
381
382 // Pause encoder again, and block allocations.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200383 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
384 .Times(1)
385 .WillOnce(Return(0));
Erik Språng4e193e42018-09-14 19:01:58 +0200386 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
Sebastian Janssonc0e4d452018-10-25 15:08:32 +0200387 ->OnBitrateUpdated(CreateAllocation(0));
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200388 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc)).Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200389 observer->OnBitrateAllocationUpdated(alloc);
390
391 vss_impl->Stop();
392 });
393}
394
395TEST_F(VideoSendStreamImplTest, ThrottlesVideoBitrateAllocationWhenTooSimilar) {
396 test_queue_.SendTask([this] {
397 auto vss_impl = CreateVideoSendStreamImpl(
398 kDefaultInitialBitrateBps, kDefaultBitratePriority,
399 VideoEncoderConfig::ContentType::kScreen);
400 vss_impl->Start();
401 // Unpause encoder, to allows allocations to be passed through.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200402 const uint32_t kBitrateBps = 100000;
403 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
404 .Times(1)
405 .WillOnce(Return(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200406 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
Sebastian Janssonc0e4d452018-10-25 15:08:32 +0200407 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200408 VideoBitrateAllocationObserver* const observer =
409 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
410
411 // Populate a test instance of video bitrate allocation.
412 VideoBitrateAllocation alloc;
413 alloc.SetBitrate(0, 0, 10000);
414 alloc.SetBitrate(0, 1, 20000);
415 alloc.SetBitrate(1, 0, 30000);
416 alloc.SetBitrate(1, 1, 40000);
417
418 // Initial value.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200419 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc)).Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200420 observer->OnBitrateAllocationUpdated(alloc);
421
422 VideoBitrateAllocation updated_alloc = alloc;
423 // Needs 10% increase in bitrate to trigger immediate forward.
424 const uint32_t base_layer_min_update_bitrate_bps =
425 alloc.GetBitrate(0, 0) + alloc.get_sum_bps() / 10;
426
427 // Too small increase, don't forward.
428 updated_alloc.SetBitrate(0, 0, base_layer_min_update_bitrate_bps - 1);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200429 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(_)).Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200430 observer->OnBitrateAllocationUpdated(updated_alloc);
431
432 // Large enough increase, do forward.
433 updated_alloc.SetBitrate(0, 0, base_layer_min_update_bitrate_bps);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200434 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(updated_alloc))
Erik Språng4e193e42018-09-14 19:01:58 +0200435 .Times(1);
436 observer->OnBitrateAllocationUpdated(updated_alloc);
437
438 // This is now a decrease compared to last forward allocation, forward
439 // immediately.
440 updated_alloc.SetBitrate(0, 0, base_layer_min_update_bitrate_bps - 1);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200441 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(updated_alloc))
Erik Språng4e193e42018-09-14 19:01:58 +0200442 .Times(1);
443 observer->OnBitrateAllocationUpdated(updated_alloc);
444
445 vss_impl->Stop();
446 });
447}
448
449TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationOnLayerChange) {
450 test_queue_.SendTask([this] {
451 auto vss_impl = CreateVideoSendStreamImpl(
452 kDefaultInitialBitrateBps, kDefaultBitratePriority,
453 VideoEncoderConfig::ContentType::kScreen);
454 vss_impl->Start();
455 // Unpause encoder, to allows allocations to be passed through.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200456 const uint32_t kBitrateBps = 100000;
457 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
458 .Times(1)
459 .WillOnce(Return(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200460 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
Sebastian Janssonc0e4d452018-10-25 15:08:32 +0200461 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200462 VideoBitrateAllocationObserver* const observer =
463 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
464
465 // Populate a test instance of video bitrate allocation.
466 VideoBitrateAllocation alloc;
467 alloc.SetBitrate(0, 0, 10000);
468 alloc.SetBitrate(0, 1, 20000);
469 alloc.SetBitrate(1, 0, 30000);
470 alloc.SetBitrate(1, 1, 40000);
471
472 // Initial value.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200473 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc)).Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200474 observer->OnBitrateAllocationUpdated(alloc);
475
476 // Move some bitrate from one layer to a new one, but keep sum the same.
477 // Since layout has changed, immediately trigger forward.
478 VideoBitrateAllocation updated_alloc = alloc;
479 updated_alloc.SetBitrate(2, 0, 10000);
480 updated_alloc.SetBitrate(1, 1, alloc.GetBitrate(1, 1) - 10000);
481 EXPECT_EQ(alloc.get_sum_bps(), updated_alloc.get_sum_bps());
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200482 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(updated_alloc))
Erik Språng4e193e42018-09-14 19:01:58 +0200483 .Times(1);
484 observer->OnBitrateAllocationUpdated(updated_alloc);
485
486 vss_impl->Stop();
487 });
488}
489
490TEST_F(VideoSendStreamImplTest, ForwardsVideoBitrateAllocationAfterTimeout) {
491 test_queue_.SendTask([this] {
492 rtc::ScopedFakeClock fake_clock;
493 fake_clock.SetTimeMicros(clock_.TimeInMicroseconds());
494
495 auto vss_impl = CreateVideoSendStreamImpl(
496 kDefaultInitialBitrateBps, kDefaultBitratePriority,
497 VideoEncoderConfig::ContentType::kScreen);
498 vss_impl->Start();
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200499 const uint32_t kBitrateBps = 100000;
Erik Språng4e193e42018-09-14 19:01:58 +0200500 // Unpause encoder, to allows allocations to be passed through.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200501 EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
502 .Times(1)
503 .WillRepeatedly(Return(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200504 static_cast<BitrateAllocatorObserver*>(vss_impl.get())
Sebastian Janssonc0e4d452018-10-25 15:08:32 +0200505 ->OnBitrateUpdated(CreateAllocation(kBitrateBps));
Erik Språng4e193e42018-09-14 19:01:58 +0200506 VideoBitrateAllocationObserver* const observer =
507 static_cast<VideoBitrateAllocationObserver*>(vss_impl.get());
508
509 // Populate a test instance of video bitrate allocation.
510 VideoBitrateAllocation alloc;
511 alloc.SetBitrate(0, 0, 10000);
512 alloc.SetBitrate(0, 1, 20000);
513 alloc.SetBitrate(1, 0, 30000);
514 alloc.SetBitrate(1, 1, 40000);
515
516 EncodedImage encoded_image;
517 CodecSpecificInfo codec_specific;
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200518 EXPECT_CALL(rtp_video_sender_, OnEncodedImage(_, _, _))
Erik Språng4e193e42018-09-14 19:01:58 +0200519 .WillRepeatedly(Return(
520 EncodedImageCallback::Result(EncodedImageCallback::Result::OK)));
521
522 // Max time we will throttle similar video bitrate allocations.
523 static constexpr int64_t kMaxVbaThrottleTimeMs = 500;
524
525 {
526 // Initial value.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200527 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
528 .Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200529 observer->OnBitrateAllocationUpdated(alloc);
530 }
531
532 {
533 // Sending same allocation again, this one should be throttled.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200534 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
535 .Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200536 observer->OnBitrateAllocationUpdated(alloc);
537 }
538
539 fake_clock.AdvanceTimeMicros(kMaxVbaThrottleTimeMs * 1000);
540
541 {
542 // Sending similar allocation again after timeout, should forward.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200543 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
544 .Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200545 observer->OnBitrateAllocationUpdated(alloc);
546 }
547
548 {
549 // Sending similar allocation again without timeout, throttle.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200550 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
551 .Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200552 observer->OnBitrateAllocationUpdated(alloc);
553 }
554
555 {
556 // Send encoded image, should be a noop.
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200557 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
558 .Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200559 static_cast<EncodedImageCallback*>(vss_impl.get())
560 ->OnEncodedImage(encoded_image, &codec_specific, nullptr);
561 }
562
563 {
564 // Advance time and send encoded image, this should wake up and send
565 // cached bitrate allocation.
566 fake_clock.AdvanceTimeMicros(kMaxVbaThrottleTimeMs * 1000);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200567 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
568 .Times(1);
Erik Språng4e193e42018-09-14 19:01:58 +0200569 static_cast<EncodedImageCallback*>(vss_impl.get())
570 ->OnEncodedImage(encoded_image, &codec_specific, nullptr);
571 }
572
573 {
574 // Advance time and send encoded image, there should be no cached
575 // allocation to send.
576 fake_clock.AdvanceTimeMicros(kMaxVbaThrottleTimeMs * 1000);
Stefan Holmer64be7fa2018-10-04 15:21:55 +0200577 EXPECT_CALL(rtp_video_sender_, OnBitrateAllocationUpdated(alloc))
578 .Times(0);
Erik Språng4e193e42018-09-14 19:01:58 +0200579 static_cast<EncodedImageCallback*>(vss_impl.get())
580 ->OnEncodedImage(encoded_image, &codec_specific, nullptr);
581 }
582
583 vss_impl->Stop();
584 });
585}
586
Sebastian Jansson652dc912018-04-19 17:09:15 +0200587} // namespace internal
588} // namespace webrtc