xref: /aosp_15_r20/external/webrtc/modules/video_coding/svc/svc_rate_allocator_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 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 "modules/video_coding/svc/svc_rate_allocator.h"
12 
13 #include <algorithm>
14 #include <vector>
15 
16 #include "modules/video_coding/codecs/vp9/svc_config.h"
17 #include "rtc_base/checks.h"
18 #include "test/field_trial.h"
19 #include "test/gtest.h"
20 
21 namespace webrtc {
22 namespace test {
23 namespace {
Configure(size_t width,size_t height,size_t num_spatial_layers,size_t num_temporal_layers,bool is_screen_sharing)24 static VideoCodec Configure(size_t width,
25                             size_t height,
26                             size_t num_spatial_layers,
27                             size_t num_temporal_layers,
28                             bool is_screen_sharing) {
29   VideoCodec codec;
30   codec.width = width;
31   codec.height = height;
32   codec.codecType = kVideoCodecVP9;
33   codec.mode = is_screen_sharing ? VideoCodecMode::kScreensharing
34                                  : VideoCodecMode::kRealtimeVideo;
35 
36   std::vector<SpatialLayer> spatial_layers =
37       GetSvcConfig(width, height, 30, /*first_active_layer=*/0,
38                    num_spatial_layers, num_temporal_layers, is_screen_sharing);
39   RTC_CHECK_LE(spatial_layers.size(), kMaxSpatialLayers);
40 
41   codec.VP9()->numberOfSpatialLayers =
42       std::min<unsigned char>(num_spatial_layers, spatial_layers.size());
43   codec.VP9()->numberOfTemporalLayers = std::min<unsigned char>(
44       num_temporal_layers, spatial_layers.back().numberOfTemporalLayers);
45 
46   for (size_t sl_idx = 0; sl_idx < spatial_layers.size(); ++sl_idx) {
47     codec.spatialLayers[sl_idx] = spatial_layers[sl_idx];
48   }
49 
50   return codec;
51 }
52 
53 }  // namespace
54 
TEST(SvcRateAllocatorTest,SingleLayerFor320x180Input)55 TEST(SvcRateAllocatorTest, SingleLayerFor320x180Input) {
56   VideoCodec codec = Configure(320, 180, 3, 3, false);
57   SvcRateAllocator allocator = SvcRateAllocator(codec);
58 
59   VideoBitrateAllocation allocation =
60       allocator.Allocate(VideoBitrateAllocationParameters(1000 * 1000, 30));
61 
62   EXPECT_GT(allocation.GetSpatialLayerSum(0), 0u);
63   EXPECT_EQ(allocation.GetSpatialLayerSum(1), 0u);
64 }
65 
TEST(SvcRateAllocatorTest,TwoLayersFor640x360Input)66 TEST(SvcRateAllocatorTest, TwoLayersFor640x360Input) {
67   VideoCodec codec = Configure(640, 360, 3, 3, false);
68   SvcRateAllocator allocator = SvcRateAllocator(codec);
69 
70   VideoBitrateAllocation allocation =
71       allocator.Allocate(VideoBitrateAllocationParameters(1000 * 1000, 30));
72 
73   EXPECT_GT(allocation.GetSpatialLayerSum(0), 0u);
74   EXPECT_GT(allocation.GetSpatialLayerSum(1), 0u);
75   EXPECT_EQ(allocation.GetSpatialLayerSum(2), 0u);
76 }
77 
TEST(SvcRateAllocatorTest,ThreeLayersFor1280x720Input)78 TEST(SvcRateAllocatorTest, ThreeLayersFor1280x720Input) {
79   VideoCodec codec = Configure(1280, 720, 3, 3, false);
80   SvcRateAllocator allocator = SvcRateAllocator(codec);
81 
82   VideoBitrateAllocation allocation =
83       allocator.Allocate(VideoBitrateAllocationParameters(1000 * 1000, 30));
84 
85   EXPECT_GT(allocation.GetSpatialLayerSum(0), 0u);
86   EXPECT_GT(allocation.GetSpatialLayerSum(1), 0u);
87   EXPECT_GT(allocation.GetSpatialLayerSum(2), 0u);
88 }
89 
TEST(SvcRateAllocatorTest,BaseLayerNonZeroBitrateEvenIfTotalIfLessThanMinimum)90 TEST(SvcRateAllocatorTest,
91      BaseLayerNonZeroBitrateEvenIfTotalIfLessThanMinimum) {
92   VideoCodec codec = Configure(1280, 720, 3, 3, false);
93   SvcRateAllocator allocator = SvcRateAllocator(codec);
94 
95   const SpatialLayer* layers = codec.spatialLayers;
96 
97   VideoBitrateAllocation allocation = allocator.Allocate(
98       VideoBitrateAllocationParameters(layers[0].minBitrate * 1000 / 2, 30));
99 
100   EXPECT_GT(allocation.GetSpatialLayerSum(0), 0u);
101   EXPECT_LT(allocation.GetSpatialLayerSum(0), layers[0].minBitrate * 1000);
102   EXPECT_EQ(allocation.GetSpatialLayerSum(1), 0u);
103 }
104 
TEST(SvcRateAllocatorTest,Disable640x360Layer)105 TEST(SvcRateAllocatorTest, Disable640x360Layer) {
106   VideoCodec codec = Configure(1280, 720, 3, 3, false);
107   SvcRateAllocator allocator = SvcRateAllocator(codec);
108 
109   const SpatialLayer* layers = codec.spatialLayers;
110 
111   size_t min_bitrate_for_640x360_layer_kbps =
112       layers[0].minBitrate + layers[1].minBitrate;
113 
114   VideoBitrateAllocation allocation =
115       allocator.Allocate(VideoBitrateAllocationParameters(
116           min_bitrate_for_640x360_layer_kbps * 1000 - 1, 30));
117 
118   EXPECT_GT(allocation.GetSpatialLayerSum(0), 0u);
119   EXPECT_EQ(allocation.GetSpatialLayerSum(1), 0u);
120 }
121 
TEST(SvcRateAllocatorTest,Disable1280x720Layer)122 TEST(SvcRateAllocatorTest, Disable1280x720Layer) {
123   VideoCodec codec = Configure(1280, 720, 3, 3, false);
124   SvcRateAllocator allocator = SvcRateAllocator(codec);
125 
126   const SpatialLayer* layers = codec.spatialLayers;
127 
128   size_t min_bitrate_for_1280x720_layer_kbps =
129       layers[0].minBitrate + layers[1].minBitrate + layers[2].minBitrate;
130 
131   VideoBitrateAllocation allocation =
132       allocator.Allocate(VideoBitrateAllocationParameters(
133           min_bitrate_for_1280x720_layer_kbps * 1000 - 1, 30));
134 
135   EXPECT_GT(allocation.GetSpatialLayerSum(0), 0u);
136   EXPECT_GT(allocation.GetSpatialLayerSum(1), 0u);
137   EXPECT_EQ(allocation.GetSpatialLayerSum(2), 0u);
138 }
139 
TEST(SvcRateAllocatorTest,BitrateIsCapped)140 TEST(SvcRateAllocatorTest, BitrateIsCapped) {
141   VideoCodec codec = Configure(1280, 720, 3, 3, false);
142   SvcRateAllocator allocator = SvcRateAllocator(codec);
143 
144   const SpatialLayer* layers = codec.spatialLayers;
145 
146   const uint32_t link_mbps = 100;
147   VideoBitrateAllocation allocation = allocator.Allocate(
148       VideoBitrateAllocationParameters(link_mbps * 1000000, 30));
149 
150   EXPECT_EQ(allocation.get_sum_kbps(),
151             layers[0].maxBitrate + layers[1].maxBitrate + layers[2].maxBitrate);
152   EXPECT_EQ(allocation.GetSpatialLayerSum(0) / 1000, layers[0].maxBitrate);
153   EXPECT_EQ(allocation.GetSpatialLayerSum(1) / 1000, layers[1].maxBitrate);
154   EXPECT_EQ(allocation.GetSpatialLayerSum(2) / 1000, layers[2].maxBitrate);
155 }
156 
TEST(SvcRateAllocatorTest,MinBitrateToGetQualityLayer)157 TEST(SvcRateAllocatorTest, MinBitrateToGetQualityLayer) {
158   VideoCodec codec = Configure(1280, 720, 3, 1, true);
159   SvcRateAllocator allocator = SvcRateAllocator(codec);
160 
161   const SpatialLayer* layers = codec.spatialLayers;
162 
163   EXPECT_LE(codec.VP9()->numberOfSpatialLayers, 3U);
164 
165   VideoBitrateAllocation allocation = allocator.Allocate(
166       VideoBitrateAllocationParameters(layers[0].minBitrate * 1000, 30));
167   EXPECT_EQ(allocation.GetSpatialLayerSum(0) / 1000, layers[0].minBitrate);
168   EXPECT_EQ(allocation.GetSpatialLayerSum(1), 0UL);
169 
170   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
171       (layers[0].targetBitrate + layers[1].minBitrate) * 1000, 30));
172   EXPECT_EQ(allocation.GetSpatialLayerSum(0) / 1000, layers[0].targetBitrate);
173   EXPECT_EQ(allocation.GetSpatialLayerSum(1) / 1000, layers[1].minBitrate);
174 }
175 
TEST(SvcRateAllocatorTest,DeactivateHigherLayers)176 TEST(SvcRateAllocatorTest, DeactivateHigherLayers) {
177   for (int deactivated_idx = 2; deactivated_idx >= 0; --deactivated_idx) {
178     VideoCodec codec = Configure(1280, 720, 3, 1, false);
179     EXPECT_LE(codec.VP9()->numberOfSpatialLayers, 3U);
180 
181     for (int i = deactivated_idx; i < 3; ++i)
182       codec.spatialLayers[i].active = false;
183 
184     SvcRateAllocator allocator = SvcRateAllocator(codec);
185 
186     VideoBitrateAllocation allocation = allocator.Allocate(
187         VideoBitrateAllocationParameters(10 * 1000 * 1000, 30));
188 
189     // Ensure layers spatial_idx < deactivated_idx are activated.
190     for (int spatial_idx = 0; spatial_idx < deactivated_idx; ++spatial_idx) {
191       EXPECT_GT(allocation.GetSpatialLayerSum(spatial_idx), 0UL);
192     }
193 
194     // Ensure layers spatial_idx >= deactivated_idx are deactivated.
195     for (int spatial_idx = deactivated_idx; spatial_idx < 3; ++spatial_idx) {
196       EXPECT_EQ(allocation.GetSpatialLayerSum(spatial_idx), 0UL);
197     }
198   }
199 }
200 
TEST(SvcRateAllocatorTest,DeactivateLowerLayers)201 TEST(SvcRateAllocatorTest, DeactivateLowerLayers) {
202   for (int deactivated_idx = 0; deactivated_idx < 3; ++deactivated_idx) {
203     VideoCodec codec = Configure(1280, 720, 3, 1, false);
204     EXPECT_LE(codec.VP9()->numberOfSpatialLayers, 3U);
205 
206     for (int i = deactivated_idx; i >= 0; --i)
207       codec.spatialLayers[i].active = false;
208 
209     SvcRateAllocator allocator = SvcRateAllocator(codec);
210 
211     VideoBitrateAllocation allocation = allocator.Allocate(
212         VideoBitrateAllocationParameters(10 * 1000 * 1000, 30));
213 
214     // Ensure layers spatial_idx <= deactivated_idx are deactivated.
215     for (int spatial_idx = 0; spatial_idx <= deactivated_idx; ++spatial_idx) {
216       EXPECT_EQ(allocation.GetSpatialLayerSum(spatial_idx), 0UL);
217     }
218 
219     // Ensure layers spatial_idx > deactivated_idx are activated.
220     for (int spatial_idx = deactivated_idx + 1; spatial_idx < 3;
221          ++spatial_idx) {
222       EXPECT_GT(allocation.GetSpatialLayerSum(spatial_idx), 0UL);
223     }
224   }
225 }
226 
TEST(SvcRateAllocatorTest,SignalsBwLimited)227 TEST(SvcRateAllocatorTest, SignalsBwLimited) {
228   VideoCodec codec = Configure(1280, 720, 3, 1, false);
229   SvcRateAllocator allocator = SvcRateAllocator(codec);
230 
231   // Rough estimate calculated by hand.
232   uint32_t min_to_enable_all = 900000;
233 
234   EXPECT_TRUE(
235       allocator
236           .Allocate(VideoBitrateAllocationParameters(min_to_enable_all / 2, 30))
237           .is_bw_limited());
238 
239   EXPECT_FALSE(
240       allocator
241           .Allocate(VideoBitrateAllocationParameters(min_to_enable_all, 30))
242           .is_bw_limited());
243 }
244 
TEST(SvcRateAllocatorTest,NoPaddingIfAllLayersAreDeactivated)245 TEST(SvcRateAllocatorTest, NoPaddingIfAllLayersAreDeactivated) {
246   VideoCodec codec = Configure(1280, 720, 3, 1, false);
247   EXPECT_EQ(codec.VP9()->numberOfSpatialLayers, 3U);
248   // Deactivation of base layer deactivates all layers.
249   codec.spatialLayers[0].active = false;
250   codec.spatialLayers[1].active = false;
251   codec.spatialLayers[2].active = false;
252   DataRate padding_rate = SvcRateAllocator::GetPaddingBitrate(codec);
253   EXPECT_EQ(padding_rate, DataRate::Zero());
254 }
255 
TEST(SvcRateAllocatorTest,FindLayerTogglingThreshold)256 TEST(SvcRateAllocatorTest, FindLayerTogglingThreshold) {
257   // Let's unit test a utility method of the unit test...
258 
259   // Predetermined constants indicating the min bitrate needed for two and three
260   // layers to be enabled respectively, using the config from Configure() with
261   // 1280x720 resolution and three spatial layers.
262   const DataRate kTwoLayerMinRate = DataRate::BitsPerSec(299150);
263   const DataRate kThreeLayerMinRate = DataRate::BitsPerSec(891052);
264 
265   VideoCodec codec = Configure(1280, 720, 3, 1, false);
266   absl::InlinedVector<DataRate, kMaxSpatialLayers> layer_start_bitrates =
267       SvcRateAllocator::GetLayerStartBitrates(codec);
268   ASSERT_EQ(layer_start_bitrates.size(), 3u);
269   EXPECT_EQ(layer_start_bitrates[1], kTwoLayerMinRate);
270   EXPECT_EQ(layer_start_bitrates[2], kThreeLayerMinRate);
271 }
272 
TEST(SvcRateAllocatorTest,SupportsAv1)273 TEST(SvcRateAllocatorTest, SupportsAv1) {
274   VideoCodec codec;
275   codec.width = 640;
276   codec.height = 360;
277   codec.codecType = kVideoCodecAV1;
278   codec.SetScalabilityMode(ScalabilityMode::kL3T3);
279   codec.spatialLayers[0].active = true;
280   codec.spatialLayers[0].minBitrate = 30;
281   codec.spatialLayers[0].targetBitrate = 51;
282   codec.spatialLayers[0].maxBitrate = 73;
283   codec.spatialLayers[1].active = true;
284   codec.spatialLayers[1].minBitrate = 49;
285   codec.spatialLayers[1].targetBitrate = 64;
286   codec.spatialLayers[1].maxBitrate = 97;
287   codec.spatialLayers[2].active = true;
288   codec.spatialLayers[2].minBitrate = 193;
289   codec.spatialLayers[2].targetBitrate = 305;
290   codec.spatialLayers[2].maxBitrate = 418;
291 
292   SvcRateAllocator allocator(codec);
293 
294   VideoBitrateAllocation allocation =
295       allocator.Allocate(VideoBitrateAllocationParameters(1'000'000, 30));
296 
297   EXPECT_GT(allocation.GetSpatialLayerSum(0), 0u);
298   EXPECT_GT(allocation.GetSpatialLayerSum(1), 0u);
299   EXPECT_GT(allocation.GetSpatialLayerSum(2), 0u);
300 }
301 
TEST(SvcRateAllocatorTest,SupportsAv1WithSkippedLayer)302 TEST(SvcRateAllocatorTest, SupportsAv1WithSkippedLayer) {
303   VideoCodec codec;
304   codec.width = 640;
305   codec.height = 360;
306   codec.codecType = kVideoCodecAV1;
307   codec.SetScalabilityMode(ScalabilityMode::kL3T3);
308   codec.spatialLayers[0].active = false;
309   codec.spatialLayers[0].minBitrate = 30;
310   codec.spatialLayers[0].targetBitrate = 51;
311   codec.spatialLayers[0].maxBitrate = 73;
312   codec.spatialLayers[1].active = true;
313   codec.spatialLayers[1].minBitrate = 49;
314   codec.spatialLayers[1].targetBitrate = 64;
315   codec.spatialLayers[1].maxBitrate = 97;
316   codec.spatialLayers[2].active = true;
317   codec.spatialLayers[2].minBitrate = 193;
318   codec.spatialLayers[2].targetBitrate = 305;
319   codec.spatialLayers[2].maxBitrate = 418;
320 
321   SvcRateAllocator allocator(codec);
322 
323   VideoBitrateAllocation allocation =
324       allocator.Allocate(VideoBitrateAllocationParameters(1'000'000, 30));
325 
326   EXPECT_EQ(allocation.GetSpatialLayerSum(0), 0u);
327   EXPECT_GT(allocation.GetSpatialLayerSum(1), 0u);
328   EXPECT_GT(allocation.GetSpatialLayerSum(2), 0u);
329 }
330 
TEST(SvcRateAllocatorTest,UsesScalabilityModeToGetNumberOfLayers)331 TEST(SvcRateAllocatorTest, UsesScalabilityModeToGetNumberOfLayers) {
332   VideoCodec codec;
333   codec.width = 640;
334   codec.height = 360;
335   codec.codecType = kVideoCodecAV1;
336   codec.SetScalabilityMode(ScalabilityMode::kL2T2);
337   codec.spatialLayers[0].active = true;
338   codec.spatialLayers[0].minBitrate = 30;
339   codec.spatialLayers[0].targetBitrate = 51;
340   codec.spatialLayers[0].maxBitrate = 73;
341   codec.spatialLayers[1].active = true;
342   codec.spatialLayers[1].minBitrate = 49;
343   codec.spatialLayers[1].targetBitrate = 64;
344   codec.spatialLayers[1].maxBitrate = 97;
345   codec.spatialLayers[2].active = true;
346   codec.spatialLayers[2].minBitrate = 193;
347   codec.spatialLayers[2].targetBitrate = 305;
348   codec.spatialLayers[2].maxBitrate = 418;
349 
350   SvcRateAllocator allocator(codec);
351   VideoBitrateAllocation allocation =
352       allocator.Allocate(VideoBitrateAllocationParameters(1'000'000, 30));
353 
354   // Expect bitrates for 2 temporal layers.
355   EXPECT_TRUE(allocation.HasBitrate(1, /*temporal_index=*/0));
356   EXPECT_TRUE(allocation.HasBitrate(1, /*temporal_index=*/1));
357   EXPECT_FALSE(allocation.HasBitrate(1, /*temporal_index=*/2));
358 
359   // expect codec.spatialLayers[2].active is ignored because scability mode uses
360   // just 2 spatial layers.
361   EXPECT_EQ(allocation.GetSpatialLayerSum(2), 0u);
362 }
363 
364 class SvcRateAllocatorTestParametrizedContentType
365     : public ::testing::Test,
366       public ::testing::WithParamInterface<bool> {
367  public:
SvcRateAllocatorTestParametrizedContentType()368   SvcRateAllocatorTestParametrizedContentType()
369       : is_screen_sharing_(GetParam()) {}
370 
371   const bool is_screen_sharing_;
372 };
373 
TEST_P(SvcRateAllocatorTestParametrizedContentType,MaxBitrate)374 TEST_P(SvcRateAllocatorTestParametrizedContentType, MaxBitrate) {
375   VideoCodec codec = Configure(1280, 720, 3, 1, is_screen_sharing_);
376   EXPECT_EQ(SvcRateAllocator::GetMaxBitrate(codec),
377             DataRate::KilobitsPerSec(codec.spatialLayers[0].maxBitrate +
378                                      codec.spatialLayers[1].maxBitrate +
379                                      codec.spatialLayers[2].maxBitrate));
380 
381   // Deactivate middle layer. This causes deactivation of top layer as well.
382   codec.spatialLayers[1].active = false;
383   EXPECT_EQ(SvcRateAllocator::GetMaxBitrate(codec),
384             DataRate::KilobitsPerSec(codec.spatialLayers[0].maxBitrate));
385 }
386 
TEST_P(SvcRateAllocatorTestParametrizedContentType,PaddingBitrate)387 TEST_P(SvcRateAllocatorTestParametrizedContentType, PaddingBitrate) {
388   VideoCodec codec = Configure(1280, 720, 3, 1, is_screen_sharing_);
389   SvcRateAllocator allocator = SvcRateAllocator(codec);
390 
391   DataRate padding_bitrate = SvcRateAllocator::GetPaddingBitrate(codec);
392 
393   VideoBitrateAllocation allocation =
394       allocator.Allocate(VideoBitrateAllocationParameters(padding_bitrate, 30));
395   EXPECT_GT(allocation.GetSpatialLayerSum(0), 0UL);
396   EXPECT_GT(allocation.GetSpatialLayerSum(1), 0UL);
397   EXPECT_GT(allocation.GetSpatialLayerSum(2), 0UL);
398 
399   // Allocate 90% of padding bitrate. Top layer should be disabled.
400   allocation = allocator.Allocate(
401       VideoBitrateAllocationParameters(9 * padding_bitrate / 10, 30));
402   EXPECT_GT(allocation.GetSpatialLayerSum(0), 0UL);
403   EXPECT_GT(allocation.GetSpatialLayerSum(1), 0UL);
404   EXPECT_EQ(allocation.GetSpatialLayerSum(2), 0UL);
405 
406   // Deactivate top layer.
407   codec.spatialLayers[2].active = false;
408 
409   padding_bitrate = SvcRateAllocator::GetPaddingBitrate(codec);
410   allocation =
411       allocator.Allocate(VideoBitrateAllocationParameters(padding_bitrate, 30));
412   EXPECT_GT(allocation.GetSpatialLayerSum(0), 0UL);
413   EXPECT_GT(allocation.GetSpatialLayerSum(1), 0UL);
414   EXPECT_EQ(allocation.GetSpatialLayerSum(2), 0UL);
415 
416   allocation = allocator.Allocate(
417       VideoBitrateAllocationParameters(9 * padding_bitrate / 10, 30));
418   EXPECT_GT(allocation.GetSpatialLayerSum(0), 0UL);
419   EXPECT_EQ(allocation.GetSpatialLayerSum(1), 0UL);
420   EXPECT_EQ(allocation.GetSpatialLayerSum(2), 0UL);
421 
422   // Deactivate all layers.
423   codec.spatialLayers[0].active = false;
424   codec.spatialLayers[1].active = false;
425   codec.spatialLayers[2].active = false;
426 
427   padding_bitrate = SvcRateAllocator::GetPaddingBitrate(codec);
428   // No padding expected.
429   EXPECT_EQ(DataRate::Zero(), padding_bitrate);
430 }
431 
TEST_P(SvcRateAllocatorTestParametrizedContentType,StableBitrate)432 TEST_P(SvcRateAllocatorTestParametrizedContentType, StableBitrate) {
433   ScopedFieldTrials field_trial(
434       "WebRTC-StableTargetRate/enabled:true,video_hysteresis_factor:1.0,"
435       "screenshare_hysteresis_factor:1.0/");
436 
437   const VideoCodec codec = Configure(1280, 720, 3, 1, is_screen_sharing_);
438   const auto start_rates = SvcRateAllocator::GetLayerStartBitrates(codec);
439   const DataRate min_rate_two_layers = start_rates[1];
440   const DataRate min_rate_three_layers = start_rates[2];
441 
442   const DataRate max_rate_one_layer =
443       DataRate::KilobitsPerSec(codec.spatialLayers[0].maxBitrate);
444   const DataRate max_rate_two_layers =
445       is_screen_sharing_
446           ? DataRate::KilobitsPerSec(codec.spatialLayers[0].targetBitrate +
447                                      codec.spatialLayers[1].maxBitrate)
448           : DataRate::KilobitsPerSec(codec.spatialLayers[0].maxBitrate +
449                                      codec.spatialLayers[1].maxBitrate);
450 
451   SvcRateAllocator allocator = SvcRateAllocator(codec);
452 
453   // Two layers, stable and target equal.
454   auto allocation = allocator.Allocate(VideoBitrateAllocationParameters(
455       /*total_bitrate=*/min_rate_two_layers,
456       /*stable_bitrate=*/min_rate_two_layers, /*fps=*/30.0));
457   EXPECT_TRUE(allocation.IsSpatialLayerUsed(1));
458   EXPECT_EQ(allocation.get_sum_bps(), min_rate_two_layers.bps());
459 
460   // Two layers, stable bitrate too low for two layers.
461   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
462       /*total_bitrate=*/min_rate_two_layers,
463       /*stable_bitrate=*/min_rate_two_layers - DataRate::BitsPerSec(1),
464       /*fps=*/30.0));
465   EXPECT_FALSE(allocation.IsSpatialLayerUsed(1));
466   EXPECT_EQ(DataRate::BitsPerSec(allocation.get_sum_bps()),
467             std::min(min_rate_two_layers - DataRate::BitsPerSec(1),
468                      max_rate_one_layer));
469 
470   // Three layers, stable and target equal.
471   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
472       /*total_bitrate=*/min_rate_three_layers,
473       /*stable_bitrate=*/min_rate_three_layers, /*fps=*/30.0));
474   EXPECT_TRUE(allocation.IsSpatialLayerUsed(2));
475   EXPECT_EQ(allocation.get_sum_bps(), min_rate_three_layers.bps());
476 
477   // Three layers, stable bitrate too low for three layers.
478   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
479       /*total_bitrate=*/min_rate_three_layers,
480       /*stable_bitrate=*/min_rate_three_layers - DataRate::BitsPerSec(1),
481       /*fps=*/30.0));
482   EXPECT_FALSE(allocation.IsSpatialLayerUsed(2));
483   EXPECT_EQ(DataRate::BitsPerSec(allocation.get_sum_bps()),
484             std::min(min_rate_three_layers - DataRate::BitsPerSec(1),
485                      max_rate_two_layers));
486 }
487 
TEST_P(SvcRateAllocatorTestParametrizedContentType,StableBitrateWithHysteresis)488 TEST_P(SvcRateAllocatorTestParametrizedContentType,
489        StableBitrateWithHysteresis) {
490   const VideoCodec codec = Configure(1280, 720, 3, 1, is_screen_sharing_);
491   const auto start_rates = SvcRateAllocator::GetLayerStartBitrates(codec);
492   const DataRate min_rate_single_layer = start_rates[0];
493   const DataRate min_rate_two_layers = start_rates[1];
494   const DataRate min_rate_three_layers = start_rates[2];
495 
496   ScopedFieldTrials field_trial(
497       "WebRTC-StableTargetRate/enabled:true,video_hysteresis_factor:1.1,"
498       "screenshare_hysteresis_factor:1.1/");
499   SvcRateAllocator allocator = SvcRateAllocator(codec);
500   // Always use max bitrate as target, verify only stable is used for layer
501   // count selection.
502   const DataRate max_bitrate = allocator.GetMaxBitrate(codec);
503 
504   // Start with a single layer.
505   auto allocation = allocator.Allocate(VideoBitrateAllocationParameters(
506       /*total_bitrate=*/max_bitrate,
507       /*stable_bitrate=*/min_rate_single_layer, /*fps=*/30.0));
508   EXPECT_TRUE(allocation.IsSpatialLayerUsed(0));
509   EXPECT_FALSE(allocation.IsSpatialLayerUsed(1));
510   EXPECT_FALSE(allocation.IsSpatialLayerUsed(2));
511 
512   // Min bitrate not enough to enable second layer due to 10% hysteresis.
513   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
514       /*total_bitrate=*/max_bitrate,
515       /*stable_bitrate=*/min_rate_two_layers, /*fps=*/30.0));
516   EXPECT_TRUE(allocation.IsSpatialLayerUsed(0));
517   EXPECT_FALSE(allocation.IsSpatialLayerUsed(1));
518   EXPECT_FALSE(allocation.IsSpatialLayerUsed(2));
519 
520   // Add hysteresis, second layer should turn on.
521   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
522       /*total_bitrate=*/max_bitrate,
523       /*stable_bitrate=*/min_rate_two_layers * 1.1, /*fps=*/30.0));
524   EXPECT_TRUE(allocation.IsSpatialLayerUsed(0));
525   EXPECT_TRUE(allocation.IsSpatialLayerUsed(1));
526   EXPECT_FALSE(allocation.IsSpatialLayerUsed(2));
527 
528   // Remove hysteresis, second layer should stay on.
529   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
530       /*total_bitrate=*/max_bitrate,
531       /*stable_bitrate=*/min_rate_two_layers, /*fps=*/30.0));
532   EXPECT_TRUE(allocation.IsSpatialLayerUsed(0));
533   EXPECT_TRUE(allocation.IsSpatialLayerUsed(1));
534   EXPECT_FALSE(allocation.IsSpatialLayerUsed(2));
535 
536   // Going below min for two layers, second layer should turn off again.
537   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
538       /*total_bitrate=*/max_bitrate,
539       /*stable_bitrate=*/min_rate_two_layers - DataRate::BitsPerSec(1),
540       /*fps=*/30.0));
541   EXPECT_TRUE(allocation.IsSpatialLayerUsed(0));
542   EXPECT_FALSE(allocation.IsSpatialLayerUsed(1));
543   EXPECT_FALSE(allocation.IsSpatialLayerUsed(2));
544 
545   // Min bitrate not enough to enable third layer due to 10% hysteresis.
546   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
547       /*total_bitrate=*/max_bitrate,
548       /*stable_bitrate=*/min_rate_three_layers, /*fps=*/30.0));
549   EXPECT_TRUE(allocation.IsSpatialLayerUsed(0));
550   EXPECT_TRUE(allocation.IsSpatialLayerUsed(1));
551   EXPECT_FALSE(allocation.IsSpatialLayerUsed(2));
552 
553   // Add hysteresis, third layer should turn on.
554   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
555       /*total_bitrate=*/max_bitrate,
556       /*stable_bitrate=*/min_rate_three_layers * 1.1, /*fps=*/30.0));
557   EXPECT_TRUE(allocation.IsSpatialLayerUsed(0));
558   EXPECT_TRUE(allocation.IsSpatialLayerUsed(1));
559   EXPECT_TRUE(allocation.IsSpatialLayerUsed(2));
560 
561   // Remove hysteresis, third layer should stay on.
562   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
563       /*total_bitrate=*/max_bitrate,
564       /*stable_bitrate=*/min_rate_three_layers, /*fps=*/30.0));
565   EXPECT_TRUE(allocation.IsSpatialLayerUsed(0));
566   EXPECT_TRUE(allocation.IsSpatialLayerUsed(1));
567   EXPECT_TRUE(allocation.IsSpatialLayerUsed(2));
568 
569   // Going below min for three layers, third layer should turn off again.
570   allocation = allocator.Allocate(VideoBitrateAllocationParameters(
571       /*total_bitrate=*/max_bitrate,
572       /*stable_bitrate=*/min_rate_three_layers - DataRate::BitsPerSec(1),
573       /*fps=*/30.0));
574   EXPECT_TRUE(allocation.IsSpatialLayerUsed(0));
575   EXPECT_TRUE(allocation.IsSpatialLayerUsed(1));
576   EXPECT_FALSE(allocation.IsSpatialLayerUsed(2));
577 }
578 
579 INSTANTIATE_TEST_SUITE_P(_,
580                          SvcRateAllocatorTestParametrizedContentType,
581                          ::testing::Bool());
582 
583 }  // namespace test
584 }  // namespace webrtc
585