1 /*
2 * Copyright (c) 2016 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 "modules/video_coding/utility/simulcast_rate_allocator.h"
12
13 #include <limits>
14 #include <memory>
15 #include <utility>
16 #include <vector>
17
18 #include "api/video_codecs/vp8_frame_buffer_controller.h"
19 #include "api/video_codecs/vp8_frame_config.h"
20 #include "api/video_codecs/vp8_temporal_layers.h"
21 #include "rtc_base/checks.h"
22 #include "test/field_trial.h"
23 #include "test/gmock.h"
24 #include "test/gtest.h"
25
26 namespace webrtc {
27 namespace {
28 using ::testing::_;
29
30 constexpr uint32_t kFramerateFps = 5;
31 constexpr uint32_t kMinBitrateKbps = 50;
32 // These correspond to kLegacyScreenshareTl(0|1)BitrateKbps in cc.
33 constexpr uint32_t kLegacyScreenshareTargetBitrateKbps = 200;
34 constexpr uint32_t kLegacyScreenshareMaxBitrateKbps = 1000;
35 // Bitrates for upper simulcast screenshare layer.
36 constexpr uint32_t kSimulcastScreenshareMinBitrateKbps = 600;
37 constexpr uint32_t kSimulcastScreenshareMaxBitrateKbps = 1250;
38 // Default video hysteresis factor: allocatable bitrate for next layer must
39 // exceed 20% of min setting in order to be initially turned on.
40 const double kDefaultHysteresis = 1.2;
41
42 class MockTemporalLayers : public Vp8FrameBufferController {
43 public:
44 MOCK_METHOD(Vp8FrameConfig, NextFrameConfig, (size_t, uint32_t), (override));
45 MOCK_METHOD(void,
46 OnRatesUpdated,
47 (size_t, const std::vector<uint32_t>&, int),
48 (override));
49 MOCK_METHOD(Vp8EncoderConfig, UpdateConfiguration, (size_t), (override));
50 MOCK_METHOD(void,
51 OnEncodeDone,
52 (size_t, uint32_t, size_t, bool, int, CodecSpecificInfo*),
53 (override));
54 };
55 } // namespace
56
57 class SimulcastRateAllocatorTest : public ::testing::TestWithParam<bool> {
58 public:
SimulcastRateAllocatorTest()59 SimulcastRateAllocatorTest() {
60 codec_.codecType = kVideoCodecVP8;
61 codec_.minBitrate = kMinBitrateKbps;
62 codec_.maxBitrate = kLegacyScreenshareMaxBitrateKbps;
63 codec_.active = true;
64 CreateAllocator();
65 }
~SimulcastRateAllocatorTest()66 virtual ~SimulcastRateAllocatorTest() {}
67
68 template <size_t S>
ExpectEqual(uint32_t (& expected)[S],const std::vector<uint32_t> & actual)69 void ExpectEqual(uint32_t (&expected)[S],
70 const std::vector<uint32_t>& actual) {
71 EXPECT_EQ(S, actual.size());
72 for (size_t i = 0; i < S; ++i)
73 EXPECT_EQ(expected[i], actual[i]) << "Mismatch at index " << i;
74 }
75
76 template <size_t S>
ExpectEqual(uint32_t (& expected)[S],const VideoBitrateAllocation & actual)77 void ExpectEqual(uint32_t (&expected)[S],
78 const VideoBitrateAllocation& actual) {
79 // EXPECT_EQ(S, actual.size());
80 uint32_t sum = 0;
81 for (size_t i = 0; i < S; ++i) {
82 uint32_t layer_bitrate = actual.GetSpatialLayerSum(i);
83 if (layer_bitrate == 0) {
84 EXPECT_FALSE(actual.IsSpatialLayerUsed(i));
85 }
86 EXPECT_EQ(expected[i] * 1000U, layer_bitrate)
87 << "Mismatch at index " << i;
88 sum += layer_bitrate;
89 }
90 EXPECT_EQ(sum, actual.get_sum_bps());
91 }
92
CreateAllocator(bool legacy_conference_mode=false)93 void CreateAllocator(bool legacy_conference_mode = false) {
94 allocator_.reset(new SimulcastRateAllocator(codec_));
95 allocator_->SetLegacyConferenceMode(legacy_conference_mode);
96 }
97
SetupCodec3SL3TL(const std::vector<bool> & active_streams)98 void SetupCodec3SL3TL(const std::vector<bool>& active_streams) {
99 const size_t num_simulcast_layers = 3;
100 RTC_DCHECK_GE(active_streams.size(), num_simulcast_layers);
101 SetupCodec2SL3TL(active_streams);
102 codec_.numberOfSimulcastStreams = num_simulcast_layers;
103 codec_.simulcastStream[2].numberOfTemporalLayers = 3;
104 codec_.simulcastStream[2].maxBitrate = 4000;
105 codec_.simulcastStream[2].targetBitrate = 3000;
106 codec_.simulcastStream[2].minBitrate = 2000;
107 codec_.simulcastStream[2].active = active_streams[2];
108 }
109
SetupCodec2SL3TL(const std::vector<bool> & active_streams)110 void SetupCodec2SL3TL(const std::vector<bool>& active_streams) {
111 const size_t num_simulcast_layers = 2;
112 RTC_DCHECK_GE(active_streams.size(), num_simulcast_layers);
113 SetupCodec1SL3TL(active_streams);
114 codec_.numberOfSimulcastStreams = num_simulcast_layers;
115 codec_.simulcastStream[1].numberOfTemporalLayers = 3;
116 codec_.simulcastStream[1].maxBitrate = 1000;
117 codec_.simulcastStream[1].targetBitrate = 500;
118 codec_.simulcastStream[1].minBitrate = 50;
119 codec_.simulcastStream[1].active = active_streams[1];
120 }
121
SetupCodec1SL3TL(const std::vector<bool> & active_streams)122 void SetupCodec1SL3TL(const std::vector<bool>& active_streams) {
123 const size_t num_simulcast_layers = 2;
124 RTC_DCHECK_GE(active_streams.size(), num_simulcast_layers);
125 SetupCodec3TL();
126 codec_.numberOfSimulcastStreams = num_simulcast_layers;
127 codec_.simulcastStream[0].numberOfTemporalLayers = 3;
128 codec_.simulcastStream[0].maxBitrate = 500;
129 codec_.simulcastStream[0].targetBitrate = 100;
130 codec_.simulcastStream[0].minBitrate = 10;
131 codec_.simulcastStream[0].active = active_streams[0];
132 }
133
SetupCodec3TL()134 void SetupCodec3TL() {
135 codec_.maxBitrate = 0;
136 codec_.VP8()->numberOfTemporalLayers = 3;
137 }
138
GetAllocation(uint32_t target_bitrate)139 VideoBitrateAllocation GetAllocation(uint32_t target_bitrate) {
140 return allocator_->Allocate(VideoBitrateAllocationParameters(
141 DataRate::KilobitsPerSec(target_bitrate), kDefaultFrameRate));
142 }
143
GetAllocation(DataRate target_rate,DataRate stable_rate)144 VideoBitrateAllocation GetAllocation(DataRate target_rate,
145 DataRate stable_rate) {
146 return allocator_->Allocate(VideoBitrateAllocationParameters(
147 target_rate, stable_rate, kDefaultFrameRate));
148 }
149
MinRate(size_t layer_index) const150 DataRate MinRate(size_t layer_index) const {
151 return DataRate::KilobitsPerSec(
152 codec_.simulcastStream[layer_index].minBitrate);
153 }
154
TargetRate(size_t layer_index) const155 DataRate TargetRate(size_t layer_index) const {
156 return DataRate::KilobitsPerSec(
157 codec_.simulcastStream[layer_index].targetBitrate);
158 }
159
MaxRate(size_t layer_index) const160 DataRate MaxRate(size_t layer_index) const {
161 return DataRate::KilobitsPerSec(
162 codec_.simulcastStream[layer_index].maxBitrate);
163 }
164
165 protected:
166 static const int kDefaultFrameRate = 30;
167 VideoCodec codec_;
168 std::unique_ptr<SimulcastRateAllocator> allocator_;
169 };
170
TEST_F(SimulcastRateAllocatorTest,NoSimulcastBelowMin)171 TEST_F(SimulcastRateAllocatorTest, NoSimulcastBelowMin) {
172 uint32_t expected[] = {codec_.minBitrate};
173 codec_.active = true;
174 ExpectEqual(expected, GetAllocation(codec_.minBitrate - 1));
175 ExpectEqual(expected, GetAllocation(1));
176 ExpectEqual(expected, GetAllocation(0));
177 }
178
TEST_F(SimulcastRateAllocatorTest,NoSimulcastAboveMax)179 TEST_F(SimulcastRateAllocatorTest, NoSimulcastAboveMax) {
180 uint32_t expected[] = {codec_.maxBitrate};
181 codec_.active = true;
182 ExpectEqual(expected, GetAllocation(codec_.maxBitrate + 1));
183 ExpectEqual(expected, GetAllocation(std::numeric_limits<uint32_t>::max()));
184 }
185
TEST_F(SimulcastRateAllocatorTest,NoSimulcastNoMax)186 TEST_F(SimulcastRateAllocatorTest, NoSimulcastNoMax) {
187 const uint32_t kMax = VideoBitrateAllocation::kMaxBitrateBps / 1000;
188 codec_.active = true;
189 codec_.maxBitrate = 0;
190 CreateAllocator();
191
192 uint32_t expected[] = {kMax};
193 ExpectEqual(expected, GetAllocation(kMax));
194 }
195
TEST_F(SimulcastRateAllocatorTest,NoSimulcastWithinLimits)196 TEST_F(SimulcastRateAllocatorTest, NoSimulcastWithinLimits) {
197 codec_.active = true;
198 for (uint32_t bitrate = codec_.minBitrate; bitrate <= codec_.maxBitrate;
199 ++bitrate) {
200 uint32_t expected[] = {bitrate};
201 ExpectEqual(expected, GetAllocation(bitrate));
202 }
203 }
204
205 // Tests that when we aren't using simulcast and the codec is marked inactive no
206 // bitrate will be allocated.
TEST_F(SimulcastRateAllocatorTest,NoSimulcastInactive)207 TEST_F(SimulcastRateAllocatorTest, NoSimulcastInactive) {
208 codec_.active = false;
209 uint32_t expected[] = {0};
210 CreateAllocator();
211
212 ExpectEqual(expected, GetAllocation(kMinBitrateKbps - 10));
213 ExpectEqual(expected, GetAllocation(kLegacyScreenshareTargetBitrateKbps));
214 ExpectEqual(expected, GetAllocation(kLegacyScreenshareMaxBitrateKbps + 10));
215 }
216
TEST_F(SimulcastRateAllocatorTest,SingleSimulcastBelowMin)217 TEST_F(SimulcastRateAllocatorTest, SingleSimulcastBelowMin) {
218 // With simulcast, use the min bitrate from the ss spec instead of the global.
219 codec_.numberOfSimulcastStreams = 1;
220 const uint32_t kMin = codec_.minBitrate - 10;
221 codec_.simulcastStream[0].minBitrate = kMin;
222 codec_.simulcastStream[0].targetBitrate = kLegacyScreenshareTargetBitrateKbps;
223 codec_.simulcastStream[0].active = true;
224 CreateAllocator();
225
226 uint32_t expected[] = {kMin};
227 ExpectEqual(expected, GetAllocation(kMin - 1));
228 ExpectEqual(expected, GetAllocation(1));
229 ExpectEqual(expected, GetAllocation(0));
230 }
231
TEST_F(SimulcastRateAllocatorTest,SignalsBwLimited)232 TEST_F(SimulcastRateAllocatorTest, SignalsBwLimited) {
233 // Enough to enable all layers.
234 const int kVeryBigBitrate = 100000;
235
236 // With simulcast, use the min bitrate from the ss spec instead of the global.
237 SetupCodec3SL3TL({true, true, true});
238 CreateAllocator();
239
240 EXPECT_TRUE(
241 GetAllocation(codec_.simulcastStream[0].minBitrate - 10).is_bw_limited());
242 EXPECT_TRUE(
243 GetAllocation(codec_.simulcastStream[0].targetBitrate).is_bw_limited());
244 EXPECT_TRUE(GetAllocation(codec_.simulcastStream[0].targetBitrate +
245 codec_.simulcastStream[1].minBitrate)
246 .is_bw_limited());
247 EXPECT_FALSE(
248 GetAllocation(
249 codec_.simulcastStream[0].targetBitrate +
250 codec_.simulcastStream[1].targetBitrate +
251 static_cast<uint32_t>(
252 codec_.simulcastStream[2].minBitrate * kDefaultHysteresis + 0.5))
253 .is_bw_limited());
254 EXPECT_FALSE(GetAllocation(kVeryBigBitrate).is_bw_limited());
255 }
256
TEST_F(SimulcastRateAllocatorTest,SingleSimulcastAboveMax)257 TEST_F(SimulcastRateAllocatorTest, SingleSimulcastAboveMax) {
258 codec_.numberOfSimulcastStreams = 1;
259 codec_.simulcastStream[0].minBitrate = kMinBitrateKbps;
260 const uint32_t kMax = codec_.simulcastStream[0].maxBitrate + 1000;
261 codec_.simulcastStream[0].maxBitrate = kMax;
262 codec_.simulcastStream[0].active = true;
263 CreateAllocator();
264
265 uint32_t expected[] = {kMax};
266 ExpectEqual(expected, GetAllocation(kMax));
267 ExpectEqual(expected, GetAllocation(kMax + 1));
268 ExpectEqual(expected, GetAllocation(std::numeric_limits<uint32_t>::max()));
269 }
270
TEST_F(SimulcastRateAllocatorTest,SingleSimulcastWithinLimits)271 TEST_F(SimulcastRateAllocatorTest, SingleSimulcastWithinLimits) {
272 codec_.numberOfSimulcastStreams = 1;
273 codec_.simulcastStream[0].minBitrate = kMinBitrateKbps;
274 codec_.simulcastStream[0].targetBitrate = kLegacyScreenshareTargetBitrateKbps;
275 codec_.simulcastStream[0].maxBitrate = kLegacyScreenshareMaxBitrateKbps;
276 codec_.simulcastStream[0].active = true;
277 CreateAllocator();
278
279 for (uint32_t bitrate = kMinBitrateKbps;
280 bitrate <= kLegacyScreenshareMaxBitrateKbps; ++bitrate) {
281 uint32_t expected[] = {bitrate};
282 ExpectEqual(expected, GetAllocation(bitrate));
283 }
284 }
285
TEST_F(SimulcastRateAllocatorTest,Regular3TLTemporalRateAllocation)286 TEST_F(SimulcastRateAllocatorTest, Regular3TLTemporalRateAllocation) {
287 SetupCodec3SL3TL({true, true, true});
288 CreateAllocator();
289
290 const VideoBitrateAllocation alloc = GetAllocation(kMinBitrateKbps);
291 // 40/20/40.
292 EXPECT_EQ(static_cast<uint32_t>(0.4 * kMinBitrateKbps),
293 alloc.GetBitrate(0, 0) / 1000);
294 EXPECT_EQ(static_cast<uint32_t>(0.2 * kMinBitrateKbps),
295 alloc.GetBitrate(0, 1) / 1000);
296 EXPECT_EQ(static_cast<uint32_t>(0.4 * kMinBitrateKbps),
297 alloc.GetBitrate(0, 2) / 1000);
298 }
299
TEST_F(SimulcastRateAllocatorTest,BaseHeavy3TLTemporalRateAllocation)300 TEST_F(SimulcastRateAllocatorTest, BaseHeavy3TLTemporalRateAllocation) {
301 test::ScopedFieldTrials field_trials(
302 "WebRTC-UseBaseHeavyVP8TL3RateAllocation/Enabled/");
303
304 SetupCodec3SL3TL({true, true, true});
305 CreateAllocator();
306
307 const VideoBitrateAllocation alloc = GetAllocation(kMinBitrateKbps);
308 // 60/20/20.
309 EXPECT_EQ(static_cast<uint32_t>(0.6 * kMinBitrateKbps),
310 alloc.GetBitrate(0, 0) / 1000);
311 EXPECT_EQ(static_cast<uint32_t>(0.2 * kMinBitrateKbps),
312 alloc.GetBitrate(0, 1) / 1000);
313 EXPECT_EQ(static_cast<uint32_t>(0.2 * kMinBitrateKbps),
314 alloc.GetBitrate(0, 2) / 1000);
315 }
316
TEST_F(SimulcastRateAllocatorTest,SingleSimulcastInactive)317 TEST_F(SimulcastRateAllocatorTest, SingleSimulcastInactive) {
318 codec_.numberOfSimulcastStreams = 1;
319 codec_.simulcastStream[0].minBitrate = kMinBitrateKbps;
320 codec_.simulcastStream[0].targetBitrate = kLegacyScreenshareTargetBitrateKbps;
321 codec_.simulcastStream[0].maxBitrate = kLegacyScreenshareMaxBitrateKbps;
322 codec_.simulcastStream[0].active = false;
323 CreateAllocator();
324
325 uint32_t expected[] = {0};
326 ExpectEqual(expected, GetAllocation(kMinBitrateKbps - 10));
327 ExpectEqual(expected, GetAllocation(kLegacyScreenshareTargetBitrateKbps));
328 ExpectEqual(expected, GetAllocation(kLegacyScreenshareMaxBitrateKbps + 10));
329 }
330
TEST_F(SimulcastRateAllocatorTest,OneToThreeStreams)331 TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) {
332 SetupCodec3SL3TL({true, true, true});
333 CreateAllocator();
334
335 {
336 // Single stream, min bitrate.
337 const uint32_t bitrate = codec_.simulcastStream[0].minBitrate;
338 uint32_t expected[] = {bitrate, 0, 0};
339 ExpectEqual(expected, GetAllocation(bitrate));
340 }
341
342 {
343 // Single stream at target bitrate.
344 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate;
345 uint32_t expected[] = {bitrate, 0, 0};
346 ExpectEqual(expected, GetAllocation(bitrate));
347 }
348
349 uint32_t kMinInitialRateTwoLayers =
350 codec_.simulcastStream[0].targetBitrate +
351 static_cast<uint32_t>(codec_.simulcastStream[1].minBitrate *
352 kDefaultHysteresis);
353 {
354 // Bitrate above target for first stream, but below min for the next one.
355 const uint32_t bitrate = kMinInitialRateTwoLayers - 1;
356 uint32_t expected[] = {bitrate, 0, 0};
357 ExpectEqual(expected, GetAllocation(bitrate));
358 }
359
360 {
361 // Just enough for two streams.
362 const uint32_t bitrate = kMinInitialRateTwoLayers;
363 uint32_t expected[] = {
364 codec_.simulcastStream[0].targetBitrate,
365 kMinInitialRateTwoLayers - codec_.simulcastStream[0].targetBitrate, 0};
366 ExpectEqual(expected, GetAllocation(bitrate));
367 }
368
369 {
370 // Second stream maxed out, but not enough for third.
371 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate +
372 codec_.simulcastStream[1].maxBitrate;
373 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate,
374 codec_.simulcastStream[1].maxBitrate, 0};
375 ExpectEqual(expected, GetAllocation(bitrate));
376 }
377
378 uint32_t kMinInitialRateThreeLayers =
379 codec_.simulcastStream[0].targetBitrate +
380 codec_.simulcastStream[1].targetBitrate +
381 static_cast<uint32_t>(codec_.simulcastStream[2].minBitrate *
382 kDefaultHysteresis);
383 {
384 // First two streams maxed out, but not enough for third. Nowhere to put
385 // remaining bits.
386 const uint32_t bitrate = kMinInitialRateThreeLayers - 1;
387 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate,
388 codec_.simulcastStream[1].maxBitrate, 0};
389 ExpectEqual(expected, GetAllocation(bitrate));
390 }
391
392 {
393 // Just enough for all three streams.
394 const uint32_t bitrate = kMinInitialRateThreeLayers;
395 uint32_t expected[] = {
396 codec_.simulcastStream[0].targetBitrate,
397 codec_.simulcastStream[1].targetBitrate,
398 static_cast<uint32_t>(codec_.simulcastStream[2].minBitrate *
399 kDefaultHysteresis)};
400 ExpectEqual(expected, GetAllocation(bitrate));
401 }
402
403 {
404 // Third maxed out.
405 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate +
406 codec_.simulcastStream[1].targetBitrate +
407 codec_.simulcastStream[2].maxBitrate;
408 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate,
409 codec_.simulcastStream[1].targetBitrate,
410 codec_.simulcastStream[2].maxBitrate};
411 ExpectEqual(expected, GetAllocation(bitrate));
412 }
413
414 {
415 // Enough to max out all streams which will allocate the target amount to
416 // the lower streams.
417 const uint32_t bitrate = codec_.simulcastStream[0].maxBitrate +
418 codec_.simulcastStream[1].maxBitrate +
419 codec_.simulcastStream[2].maxBitrate;
420 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate,
421 codec_.simulcastStream[1].targetBitrate,
422 codec_.simulcastStream[2].maxBitrate};
423 ExpectEqual(expected, GetAllocation(bitrate));
424 }
425 }
426
427 // If three simulcast streams that are all inactive, none of them should be
428 // allocated bitrate.
TEST_F(SimulcastRateAllocatorTest,ThreeStreamsInactive)429 TEST_F(SimulcastRateAllocatorTest, ThreeStreamsInactive) {
430 SetupCodec3SL3TL({false, false, false});
431 CreateAllocator();
432
433 // Just enough to allocate the min.
434 const uint32_t min_bitrate = codec_.simulcastStream[0].minBitrate +
435 codec_.simulcastStream[1].minBitrate +
436 codec_.simulcastStream[2].minBitrate;
437 // Enough bitrate to allocate target to all streams.
438 const uint32_t target_bitrate = codec_.simulcastStream[0].targetBitrate +
439 codec_.simulcastStream[1].targetBitrate +
440 codec_.simulcastStream[2].targetBitrate;
441 // Enough bitrate to allocate max to all streams.
442 const uint32_t max_bitrate = codec_.simulcastStream[0].maxBitrate +
443 codec_.simulcastStream[1].maxBitrate +
444 codec_.simulcastStream[2].maxBitrate;
445 uint32_t expected[] = {0, 0, 0};
446 ExpectEqual(expected, GetAllocation(0));
447 ExpectEqual(expected, GetAllocation(min_bitrate));
448 ExpectEqual(expected, GetAllocation(target_bitrate));
449 ExpectEqual(expected, GetAllocation(max_bitrate));
450 }
451
452 // If there are two simulcast streams, we expect the high active stream to be
453 // allocated as if it is a single active stream.
TEST_F(SimulcastRateAllocatorTest,TwoStreamsLowInactive)454 TEST_F(SimulcastRateAllocatorTest, TwoStreamsLowInactive) {
455 SetupCodec2SL3TL({false, true});
456 CreateAllocator();
457
458 const uint32_t kActiveStreamMinBitrate = codec_.simulcastStream[1].minBitrate;
459 const uint32_t kActiveStreamTargetBitrate =
460 codec_.simulcastStream[1].targetBitrate;
461 const uint32_t kActiveStreamMaxBitrate = codec_.simulcastStream[1].maxBitrate;
462 {
463 // Expect that the stream is always allocated its min bitrate.
464 uint32_t expected[] = {0, kActiveStreamMinBitrate};
465 ExpectEqual(expected, GetAllocation(0));
466 ExpectEqual(expected, GetAllocation(kActiveStreamMinBitrate - 10));
467 ExpectEqual(expected, GetAllocation(kActiveStreamMinBitrate));
468 }
469
470 {
471 // The stream should be allocated its target bitrate.
472 uint32_t expected[] = {0, kActiveStreamTargetBitrate};
473 ExpectEqual(expected, GetAllocation(kActiveStreamTargetBitrate));
474 }
475
476 {
477 // The stream should be allocated its max if the target input is sufficient.
478 uint32_t expected[] = {0, kActiveStreamMaxBitrate};
479 ExpectEqual(expected, GetAllocation(kActiveStreamMaxBitrate));
480 ExpectEqual(expected, GetAllocation(std::numeric_limits<uint32_t>::max()));
481 }
482 }
483
484 // If there are two simulcast streams, we expect the low active stream to be
485 // allocated as if it is a single active stream.
TEST_F(SimulcastRateAllocatorTest,TwoStreamsHighInactive)486 TEST_F(SimulcastRateAllocatorTest, TwoStreamsHighInactive) {
487 SetupCodec2SL3TL({true, false});
488 CreateAllocator();
489
490 const uint32_t kActiveStreamMinBitrate = codec_.simulcastStream[0].minBitrate;
491 const uint32_t kActiveStreamTargetBitrate =
492 codec_.simulcastStream[0].targetBitrate;
493 const uint32_t kActiveStreamMaxBitrate = codec_.simulcastStream[0].maxBitrate;
494 {
495 // Expect that the stream is always allocated its min bitrate.
496 uint32_t expected[] = {kActiveStreamMinBitrate, 0};
497 ExpectEqual(expected, GetAllocation(0));
498 ExpectEqual(expected, GetAllocation(kActiveStreamMinBitrate - 10));
499 ExpectEqual(expected, GetAllocation(kActiveStreamMinBitrate));
500 }
501
502 {
503 // The stream should be allocated its target bitrate.
504 uint32_t expected[] = {kActiveStreamTargetBitrate, 0};
505 ExpectEqual(expected, GetAllocation(kActiveStreamTargetBitrate));
506 }
507
508 {
509 // The stream should be allocated its max if the target input is sufficent.
510 uint32_t expected[] = {kActiveStreamMaxBitrate, 0};
511 ExpectEqual(expected, GetAllocation(kActiveStreamMaxBitrate));
512 ExpectEqual(expected, GetAllocation(std::numeric_limits<uint32_t>::max()));
513 }
514 }
515
516 // If there are three simulcast streams and the middle stream is inactive, the
517 // other two streams should be allocated bitrate the same as if they are two
518 // active simulcast streams.
TEST_F(SimulcastRateAllocatorTest,ThreeStreamsMiddleInactive)519 TEST_F(SimulcastRateAllocatorTest, ThreeStreamsMiddleInactive) {
520 SetupCodec3SL3TL({true, false, true});
521 CreateAllocator();
522
523 {
524 const uint32_t kLowStreamMinBitrate = codec_.simulcastStream[0].minBitrate;
525 // The lowest stream should always be allocated its minimum bitrate.
526 uint32_t expected[] = {kLowStreamMinBitrate, 0, 0};
527 ExpectEqual(expected, GetAllocation(0));
528 ExpectEqual(expected, GetAllocation(kLowStreamMinBitrate - 10));
529 ExpectEqual(expected, GetAllocation(kLowStreamMinBitrate));
530 }
531
532 {
533 // The lowest stream gets its target bitrate.
534 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, 0, 0};
535 ExpectEqual(expected,
536 GetAllocation(codec_.simulcastStream[0].targetBitrate));
537 }
538
539 {
540 // The lowest stream gets its max bitrate, but not enough for the high
541 // stream.
542 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate +
543 codec_.simulcastStream[2].minBitrate - 1;
544 uint32_t expected[] = {codec_.simulcastStream[0].maxBitrate, 0, 0};
545 ExpectEqual(expected, GetAllocation(bitrate));
546 }
547
548 {
549 // Both active streams get allocated target bitrate.
550 const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate +
551 codec_.simulcastStream[2].targetBitrate;
552 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, 0,
553 codec_.simulcastStream[2].targetBitrate};
554 ExpectEqual(expected, GetAllocation(bitrate));
555 }
556
557 {
558 // Lowest stream gets its target bitrate, high stream gets its max bitrate.
559 uint32_t bitrate = codec_.simulcastStream[0].targetBitrate +
560 codec_.simulcastStream[2].maxBitrate;
561 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, 0,
562 codec_.simulcastStream[2].maxBitrate};
563 ExpectEqual(expected, GetAllocation(bitrate));
564 ExpectEqual(expected, GetAllocation(bitrate + 10));
565 ExpectEqual(expected, GetAllocation(std::numeric_limits<uint32_t>::max()));
566 }
567 }
568
TEST_F(SimulcastRateAllocatorTest,NonConferenceModeScreenshare)569 TEST_F(SimulcastRateAllocatorTest, NonConferenceModeScreenshare) {
570 codec_.mode = VideoCodecMode::kScreensharing;
571 SetupCodec3SL3TL({true, true, true});
572 CreateAllocator();
573
574 // Make sure we have enough bitrate for all 3 simulcast layers
575 const uint32_t bitrate = codec_.simulcastStream[0].maxBitrate +
576 codec_.simulcastStream[1].maxBitrate +
577 codec_.simulcastStream[2].maxBitrate;
578 const VideoBitrateAllocation alloc = GetAllocation(bitrate);
579
580 EXPECT_EQ(alloc.GetTemporalLayerAllocation(0).size(), 3u);
581 EXPECT_EQ(alloc.GetTemporalLayerAllocation(1).size(), 3u);
582 EXPECT_EQ(alloc.GetTemporalLayerAllocation(2).size(), 3u);
583 }
584
TEST_F(SimulcastRateAllocatorTest,StableRate)585 TEST_F(SimulcastRateAllocatorTest, StableRate) {
586 webrtc::test::ScopedFieldTrials field_trials(
587 "WebRTC-StableTargetRate/"
588 "enabled:true,"
589 "video_hysteresis_factor:1.1/");
590
591 SetupCodec3SL3TL({true, true, true});
592 CreateAllocator();
593
594 // Let the volatile rate always be be enough for all streams, in this test we
595 // are only interested in how the stable rate affects enablement.
596 const DataRate volatile_rate =
597 (TargetRate(0) + TargetRate(1) + MinRate(2)) * 1.1;
598
599 {
600 // On the first call to a new SimulcastRateAllocator instance, hysteresis
601 // is disabled, but stable rate still caps layers.
602 uint32_t expected[] = {TargetRate(0).kbps<uint32_t>(),
603 MaxRate(1).kbps<uint32_t>()};
604 ExpectEqual(expected,
605 GetAllocation(volatile_rate, TargetRate(0) + MinRate(1)));
606 }
607
608 {
609 // Let stable rate go to a bitrate below what is needed for two streams.
610 uint32_t expected[] = {MaxRate(0).kbps<uint32_t>(), 0};
611 ExpectEqual(expected,
612 GetAllocation(volatile_rate, TargetRate(0) + MinRate(1) -
613 DataRate::BitsPerSec(1)));
614 }
615
616 {
617 // Don't enable stream as we need to get up above hysteresis threshold.
618 uint32_t expected[] = {MaxRate(0).kbps<uint32_t>(), 0};
619 ExpectEqual(expected,
620 GetAllocation(volatile_rate, TargetRate(0) + MinRate(1)));
621 }
622
623 {
624 // Above threshold with hysteresis, enable second stream.
625 uint32_t expected[] = {TargetRate(0).kbps<uint32_t>(),
626 MaxRate(1).kbps<uint32_t>()};
627 ExpectEqual(expected, GetAllocation(volatile_rate,
628 (TargetRate(0) + MinRate(1)) * 1.1));
629 }
630
631 {
632 // Enough to enable all thee layers.
633 uint32_t expected[] = {
634 TargetRate(0).kbps<uint32_t>(), TargetRate(1).kbps<uint32_t>(),
635 (volatile_rate - TargetRate(0) - TargetRate(1)).kbps<uint32_t>()};
636 ExpectEqual(expected, GetAllocation(volatile_rate, volatile_rate));
637 }
638
639 {
640 // Drop hysteresis, all three still on.
641 uint32_t expected[] = {
642 TargetRate(0).kbps<uint32_t>(), TargetRate(1).kbps<uint32_t>(),
643 (volatile_rate - TargetRate(0) - TargetRate(1)).kbps<uint32_t>()};
644 ExpectEqual(expected,
645 GetAllocation(volatile_rate,
646 TargetRate(0) + TargetRate(1) + MinRate(2)));
647 }
648 }
649
650 class ScreenshareRateAllocationTest : public SimulcastRateAllocatorTest {
651 public:
SetupConferenceScreenshare(bool use_simulcast,bool active=true)652 void SetupConferenceScreenshare(bool use_simulcast, bool active = true) {
653 codec_.mode = VideoCodecMode::kScreensharing;
654 codec_.minBitrate = kMinBitrateKbps;
655 codec_.maxBitrate =
656 kLegacyScreenshareMaxBitrateKbps + kSimulcastScreenshareMaxBitrateKbps;
657 if (use_simulcast) {
658 codec_.numberOfSimulcastStreams = 2;
659 codec_.simulcastStream[0].minBitrate = kMinBitrateKbps;
660 codec_.simulcastStream[0].targetBitrate =
661 kLegacyScreenshareTargetBitrateKbps;
662 codec_.simulcastStream[0].maxBitrate = kLegacyScreenshareMaxBitrateKbps;
663 codec_.simulcastStream[0].numberOfTemporalLayers = 2;
664 codec_.simulcastStream[0].active = active;
665
666 codec_.simulcastStream[1].minBitrate =
667 kSimulcastScreenshareMinBitrateKbps;
668 codec_.simulcastStream[1].targetBitrate =
669 kSimulcastScreenshareMaxBitrateKbps;
670 codec_.simulcastStream[1].maxBitrate =
671 kSimulcastScreenshareMaxBitrateKbps;
672 codec_.simulcastStream[1].numberOfTemporalLayers = 2;
673 codec_.simulcastStream[1].active = active;
674 } else {
675 codec_.numberOfSimulcastStreams = 0;
676 codec_.VP8()->numberOfTemporalLayers = 2;
677 codec_.active = active;
678 }
679 }
680 };
681
682 INSTANTIATE_TEST_SUITE_P(ScreenshareTest,
683 ScreenshareRateAllocationTest,
684 ::testing::Bool());
685
TEST_P(ScreenshareRateAllocationTest,ConferenceBitrateBelowTl0)686 TEST_P(ScreenshareRateAllocationTest, ConferenceBitrateBelowTl0) {
687 SetupConferenceScreenshare(GetParam());
688 CreateAllocator(true);
689
690 VideoBitrateAllocation allocation =
691 allocator_->Allocate(VideoBitrateAllocationParameters(
692 kLegacyScreenshareTargetBitrateKbps * 1000, kFramerateFps));
693
694 // All allocation should go in TL0.
695 EXPECT_EQ(kLegacyScreenshareTargetBitrateKbps, allocation.get_sum_kbps());
696 EXPECT_EQ(kLegacyScreenshareTargetBitrateKbps,
697 allocation.GetBitrate(0, 0) / 1000);
698 EXPECT_EQ(allocation.is_bw_limited(), GetParam());
699 }
700
TEST_P(ScreenshareRateAllocationTest,ConferenceBitrateAboveTl0)701 TEST_P(ScreenshareRateAllocationTest, ConferenceBitrateAboveTl0) {
702 SetupConferenceScreenshare(GetParam());
703 CreateAllocator(true);
704
705 uint32_t target_bitrate_kbps =
706 (kLegacyScreenshareTargetBitrateKbps + kLegacyScreenshareMaxBitrateKbps) /
707 2;
708 VideoBitrateAllocation allocation =
709 allocator_->Allocate(VideoBitrateAllocationParameters(
710 target_bitrate_kbps * 1000, kFramerateFps));
711
712 // Fill TL0, then put the rest in TL1.
713 EXPECT_EQ(target_bitrate_kbps, allocation.get_sum_kbps());
714 EXPECT_EQ(kLegacyScreenshareTargetBitrateKbps,
715 allocation.GetBitrate(0, 0) / 1000);
716 EXPECT_EQ(target_bitrate_kbps - kLegacyScreenshareTargetBitrateKbps,
717 allocation.GetBitrate(0, 1) / 1000);
718 EXPECT_EQ(allocation.is_bw_limited(), GetParam());
719 }
720
TEST_F(ScreenshareRateAllocationTest,ConferenceBitrateAboveTl1)721 TEST_F(ScreenshareRateAllocationTest, ConferenceBitrateAboveTl1) {
722 // This test is only for the non-simulcast case.
723 SetupConferenceScreenshare(false);
724 CreateAllocator(true);
725
726 VideoBitrateAllocation allocation =
727 allocator_->Allocate(VideoBitrateAllocationParameters(
728 kLegacyScreenshareMaxBitrateKbps * 2000, kFramerateFps));
729
730 // Fill both TL0 and TL1, but no more.
731 EXPECT_EQ(kLegacyScreenshareMaxBitrateKbps, allocation.get_sum_kbps());
732 EXPECT_EQ(kLegacyScreenshareTargetBitrateKbps,
733 allocation.GetBitrate(0, 0) / 1000);
734 EXPECT_EQ(
735 kLegacyScreenshareMaxBitrateKbps - kLegacyScreenshareTargetBitrateKbps,
736 allocation.GetBitrate(0, 1) / 1000);
737 EXPECT_FALSE(allocation.is_bw_limited());
738 }
739
740 // This tests when the screenshare is inactive it should be allocated 0 bitrate
741 // for all layers.
TEST_P(ScreenshareRateAllocationTest,InactiveScreenshare)742 TEST_P(ScreenshareRateAllocationTest, InactiveScreenshare) {
743 SetupConferenceScreenshare(GetParam(), false);
744 CreateAllocator();
745
746 // Enough bitrate for TL0 and TL1.
747 uint32_t target_bitrate_kbps =
748 (kLegacyScreenshareTargetBitrateKbps + kLegacyScreenshareMaxBitrateKbps) /
749 2;
750 VideoBitrateAllocation allocation =
751 allocator_->Allocate(VideoBitrateAllocationParameters(
752 target_bitrate_kbps * 1000, kFramerateFps));
753
754 EXPECT_EQ(0U, allocation.get_sum_kbps());
755 }
756
TEST_F(ScreenshareRateAllocationTest,Hysteresis)757 TEST_F(ScreenshareRateAllocationTest, Hysteresis) {
758 // This test is only for the simulcast case.
759 SetupConferenceScreenshare(true);
760 CreateAllocator();
761
762 // The bitrate at which we would normally enable the upper simulcast stream.
763 const uint32_t default_enable_rate_bps =
764 codec_.simulcastStream[0].targetBitrate +
765 codec_.simulcastStream[1].minBitrate;
766 const uint32_t enable_rate_with_hysteresis_bps =
767 (default_enable_rate_bps * 135) / 100;
768
769 {
770 // On the first call to a new SimulcastRateAllocator instance, hysteresis
771 // is disabled.
772 const uint32_t bitrate = default_enable_rate_bps;
773 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate,
774 codec_.simulcastStream[1].minBitrate};
775 ExpectEqual(expected, GetAllocation(bitrate));
776 }
777
778 {
779 // Go down to a bitrate below what is needed for two streams.
780 const uint32_t bitrate = default_enable_rate_bps - 1;
781 uint32_t expected[] = {bitrate, 0};
782 ExpectEqual(expected, GetAllocation(bitrate));
783 }
784
785 {
786 // Don't enable stream as we need to get up above hysteresis threshold.
787 const uint32_t bitrate = default_enable_rate_bps;
788 uint32_t expected[] = {bitrate, 0};
789 ExpectEqual(expected, GetAllocation(bitrate));
790 }
791
792 {
793 // Above threshold, enable second stream.
794 const uint32_t bitrate = enable_rate_with_hysteresis_bps;
795 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate,
796 enable_rate_with_hysteresis_bps -
797 codec_.simulcastStream[0].targetBitrate};
798 ExpectEqual(expected, GetAllocation(bitrate));
799 }
800
801 {
802 // Go down again, still keep the second stream alive.
803 const uint32_t bitrate = default_enable_rate_bps;
804 uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate,
805 codec_.simulcastStream[1].minBitrate};
806 ExpectEqual(expected, GetAllocation(bitrate));
807 }
808
809 {
810 // Go down below default enable, second stream is shut down again.
811 const uint32_t bitrate = default_enable_rate_bps - 1;
812 uint32_t expected[] = {bitrate, 0};
813 ExpectEqual(expected, GetAllocation(bitrate));
814 }
815
816 {
817 // Go up, hysteresis is blocking us again.
818 const uint32_t bitrate = default_enable_rate_bps;
819 uint32_t expected[] = {bitrate, 0};
820 ExpectEqual(expected, GetAllocation(bitrate));
821 }
822 }
823
824 } // namespace webrtc
825