xref: /aosp_15_r20/external/webrtc/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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