xref: /aosp_15_r20/external/webrtc/video/config/simulcast_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "video/config/simulcast.h"
12 
13 #include "api/transport/field_trial_based_config.h"
14 #include "media/base/media_constants.h"
15 #include "test/field_trial.h"
16 #include "test/gtest.h"
17 
18 namespace webrtc {
19 namespace {
20 constexpr int kQpMax = 55;
21 constexpr double kBitratePriority = 2.0;
22 constexpr bool kScreenshare = true;
23 constexpr int kDefaultTemporalLayers = 3;  // Value from simulcast.cc.
24 
25 // Values from kSimulcastConfigs in simulcast.cc.
GetSimulcastBitrates720p()26 const std::vector<VideoStream> GetSimulcastBitrates720p() {
27   std::vector<VideoStream> streams(3);
28   streams[0].min_bitrate_bps = 30000;
29   streams[0].target_bitrate_bps = 150000;
30   streams[0].max_bitrate_bps = 200000;
31   streams[1].min_bitrate_bps = 150000;
32   streams[1].target_bitrate_bps = 500000;
33   streams[1].max_bitrate_bps = 700000;
34   streams[2].min_bitrate_bps = 600000;
35   streams[2].target_bitrate_bps = 2500000;
36   streams[2].max_bitrate_bps = 2500000;
37   return streams;
38 }
39 }  // namespace
40 
TEST(SimulcastTest,TotalMaxBitrateIsZeroForNoStreams)41 TEST(SimulcastTest, TotalMaxBitrateIsZeroForNoStreams) {
42   std::vector<VideoStream> streams;
43   EXPECT_EQ(0, cricket::GetTotalMaxBitrate(streams).bps());
44 }
45 
TEST(SimulcastTest,GetTotalMaxBitrateForSingleStream)46 TEST(SimulcastTest, GetTotalMaxBitrateForSingleStream) {
47   std::vector<VideoStream> streams(1);
48   streams[0].max_bitrate_bps = 100000;
49   EXPECT_EQ(100000, cricket::GetTotalMaxBitrate(streams).bps());
50 }
51 
TEST(SimulcastTest,GetTotalMaxBitrateForMultipleStreams)52 TEST(SimulcastTest, GetTotalMaxBitrateForMultipleStreams) {
53   std::vector<VideoStream> streams(3);
54   streams[0].target_bitrate_bps = 100000;
55   streams[1].target_bitrate_bps = 200000;
56   streams[2].max_bitrate_bps = 400000;
57   EXPECT_EQ(700000, cricket::GetTotalMaxBitrate(streams).bps());
58 }
59 
TEST(SimulcastTest,BandwidthAboveTotalMaxBitrateGivenToHighestStream)60 TEST(SimulcastTest, BandwidthAboveTotalMaxBitrateGivenToHighestStream) {
61   std::vector<VideoStream> streams(3);
62   streams[0].target_bitrate_bps = 100000;
63   streams[1].target_bitrate_bps = 200000;
64   streams[2].max_bitrate_bps = 400000;
65 
66   const webrtc::DataRate one_bps = webrtc::DataRate::BitsPerSec(1);
67 
68   // No bitrate above the total max to give to the highest stream.
69   const webrtc::DataRate max_total_bitrate =
70       cricket::GetTotalMaxBitrate(streams);
71   cricket::BoostMaxSimulcastLayer(max_total_bitrate, &streams);
72   EXPECT_EQ(400000, streams[2].max_bitrate_bps);
73   EXPECT_EQ(max_total_bitrate, cricket::GetTotalMaxBitrate(streams));
74 
75   // The bitrate above the total max should be given to the highest stream.
76   cricket::BoostMaxSimulcastLayer(max_total_bitrate + one_bps, &streams);
77   EXPECT_EQ(400000 + 1, streams[2].max_bitrate_bps);
78   EXPECT_EQ(max_total_bitrate + one_bps, cricket::GetTotalMaxBitrate(streams));
79 }
80 
TEST(SimulcastTest,GetConfig)81 TEST(SimulcastTest, GetConfig) {
82   const std::vector<VideoStream> kExpected = GetSimulcastBitrates720p();
83   const FieldTrialBasedConfig trials;
84 
85   const size_t kMinLayers = 1;
86   const size_t kMaxLayers = 3;
87   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
88       kMinLayers, kMaxLayers, 1280, 720, kBitratePriority, kQpMax,
89       !kScreenshare, true, trials);
90 
91   EXPECT_EQ(kMaxLayers, streams.size());
92   EXPECT_EQ(320u, streams[0].width);
93   EXPECT_EQ(180u, streams[0].height);
94   EXPECT_EQ(640u, streams[1].width);
95   EXPECT_EQ(360u, streams[1].height);
96   EXPECT_EQ(1280u, streams[2].width);
97   EXPECT_EQ(720u, streams[2].height);
98 
99   for (size_t i = 0; i < streams.size(); ++i) {
100     EXPECT_EQ(size_t{kDefaultTemporalLayers}, streams[i].num_temporal_layers);
101     EXPECT_EQ(cricket::kDefaultVideoMaxFramerate, streams[i].max_framerate);
102     EXPECT_EQ(kQpMax, streams[i].max_qp);
103     EXPECT_EQ(kExpected[i].min_bitrate_bps, streams[i].min_bitrate_bps);
104     EXPECT_EQ(kExpected[i].target_bitrate_bps, streams[i].target_bitrate_bps);
105     EXPECT_EQ(kExpected[i].max_bitrate_bps, streams[i].max_bitrate_bps);
106     EXPECT_TRUE(streams[i].active);
107   }
108   // Currently set on lowest stream.
109   EXPECT_EQ(kBitratePriority, streams[0].bitrate_priority);
110   EXPECT_FALSE(streams[1].bitrate_priority);
111   EXPECT_FALSE(streams[2].bitrate_priority);
112 }
113 
TEST(SimulcastTest,GetConfigWithBaseHeavyVP8TL3RateAllocation)114 TEST(SimulcastTest, GetConfigWithBaseHeavyVP8TL3RateAllocation) {
115   test::ScopedFieldTrials field_trials(
116       "WebRTC-UseBaseHeavyVP8TL3RateAllocation/Enabled/");
117   FieldTrialBasedConfig trials;
118 
119   const std::vector<VideoStream> kExpected = GetSimulcastBitrates720p();
120 
121   const size_t kMinLayers = 1;
122   const size_t kMaxLayers = 3;
123   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
124       kMinLayers, kMaxLayers, 1280, 720, kBitratePriority, kQpMax,
125       !kScreenshare, true, trials);
126 
127   EXPECT_EQ(kExpected[0].min_bitrate_bps, streams[0].min_bitrate_bps);
128   EXPECT_EQ(static_cast<int>(0.4 * kExpected[0].target_bitrate_bps / 0.6),
129             streams[0].target_bitrate_bps);
130   EXPECT_EQ(static_cast<int>(0.4 * kExpected[0].max_bitrate_bps / 0.6),
131             streams[0].max_bitrate_bps);
132   for (size_t i = 1; i < streams.size(); ++i) {
133     EXPECT_EQ(kExpected[i].min_bitrate_bps, streams[i].min_bitrate_bps);
134     EXPECT_EQ(kExpected[i].target_bitrate_bps, streams[i].target_bitrate_bps);
135     EXPECT_EQ(kExpected[i].max_bitrate_bps, streams[i].max_bitrate_bps);
136   }
137 }
138 
TEST(SimulcastTest,GetConfigWithLimitedMaxLayers)139 TEST(SimulcastTest, GetConfigWithLimitedMaxLayers) {
140   const size_t kMinLayers = 1;
141   const size_t kMaxLayers = 2;
142   FieldTrialBasedConfig trials;
143   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
144       kMinLayers, kMaxLayers, 1280, 720, kBitratePriority, kQpMax,
145       !kScreenshare, true, trials);
146 
147   EXPECT_EQ(kMaxLayers, streams.size());
148   EXPECT_EQ(640u, streams[0].width);
149   EXPECT_EQ(360u, streams[0].height);
150   EXPECT_EQ(1280u, streams[1].width);
151   EXPECT_EQ(720u, streams[1].height);
152 }
153 
TEST(SimulcastTest,GetConfigWithLimitedMaxLayersForResolution)154 TEST(SimulcastTest, GetConfigWithLimitedMaxLayersForResolution) {
155   test::ScopedFieldTrials field_trials(
156       "WebRTC-LegacySimulcastLayerLimit/Enabled/");
157   FieldTrialBasedConfig trials;
158   const size_t kMinLayers = 1;
159   const size_t kMaxLayers = 3;
160   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
161       kMinLayers, kMaxLayers, 800, 600, kBitratePriority, kQpMax, !kScreenshare,
162       true, trials);
163 
164   EXPECT_EQ(2u, streams.size());
165   EXPECT_EQ(400u, streams[0].width);
166   EXPECT_EQ(300u, streams[0].height);
167   EXPECT_EQ(800u, streams[1].width);
168   EXPECT_EQ(600u, streams[1].height);
169 }
170 
TEST(SimulcastTest,GetConfigWithLowResolutionScreenshare)171 TEST(SimulcastTest, GetConfigWithLowResolutionScreenshare) {
172   test::ScopedFieldTrials field_trials(
173       "WebRTC-LegacySimulcastLayerLimit/Enabled/");
174   FieldTrialBasedConfig trials;
175   const size_t kMinLayers = 1;
176   const size_t kMaxLayers = 3;
177   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
178       kMinLayers, kMaxLayers, 100, 100, kBitratePriority, kQpMax, kScreenshare,
179       true, trials);
180 
181   // Simulcast streams number is never decreased for screenshare,
182   // even for very low resolution.
183   EXPECT_GT(streams.size(), 1u);
184 }
185 
TEST(SimulcastTest,GetConfigWithNotLimitedMaxLayersForResolution)186 TEST(SimulcastTest, GetConfigWithNotLimitedMaxLayersForResolution) {
187   test::ScopedFieldTrials field_trials(
188       "WebRTC-LegacySimulcastLayerLimit/Disabled/");
189   FieldTrialBasedConfig trials;
190   const size_t kMinLayers = 1;
191   const size_t kMaxLayers = 3;
192   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
193       kMinLayers, kMaxLayers, 800, 600, kBitratePriority, kQpMax, !kScreenshare,
194       true, trials);
195 
196   EXPECT_EQ(kMaxLayers, streams.size());
197   EXPECT_EQ(200u, streams[0].width);
198   EXPECT_EQ(150u, streams[0].height);
199   EXPECT_EQ(400u, streams[1].width);
200   EXPECT_EQ(300u, streams[1].height);
201   EXPECT_EQ(800u, streams[2].width);
202   EXPECT_EQ(600u, streams[2].height);
203 }
204 
TEST(SimulcastTest,GetConfigWithNormalizedResolution)205 TEST(SimulcastTest, GetConfigWithNormalizedResolution) {
206   FieldTrialBasedConfig trials;
207   const size_t kMinLayers = 1;
208   const size_t kMaxLayers = 2;
209   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
210       kMinLayers, kMaxLayers, 640 + 1, 360 + 1, kBitratePriority, kQpMax,
211       !kScreenshare, true, trials);
212 
213   // Must be divisible by |2 ^ (num_layers - 1)|.
214   EXPECT_EQ(kMaxLayers, streams.size());
215   EXPECT_EQ(320u, streams[0].width);
216   EXPECT_EQ(180u, streams[0].height);
217   EXPECT_EQ(640u, streams[1].width);
218   EXPECT_EQ(360u, streams[1].height);
219 }
220 
TEST(SimulcastTest,GetConfigWithNormalizedResolutionDivisibleBy4)221 TEST(SimulcastTest, GetConfigWithNormalizedResolutionDivisibleBy4) {
222   test::ScopedFieldTrials field_trials(
223       "WebRTC-NormalizeSimulcastResolution/Enabled-2/");
224   FieldTrialBasedConfig trials;
225 
226   const size_t kMinLayers = 1;
227   const size_t kMaxLayers = 2;
228   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
229       kMinLayers, kMaxLayers, 709, 501, kBitratePriority, kQpMax, !kScreenshare,
230       true, trials);
231 
232   // Must be divisible by |2 ^ 2|.
233   EXPECT_EQ(kMaxLayers, streams.size());
234   EXPECT_EQ(354u, streams[0].width);
235   EXPECT_EQ(250u, streams[0].height);
236   EXPECT_EQ(708u, streams[1].width);
237   EXPECT_EQ(500u, streams[1].height);
238 }
239 
TEST(SimulcastTest,GetConfigWithNormalizedResolutionDivisibleBy8)240 TEST(SimulcastTest, GetConfigWithNormalizedResolutionDivisibleBy8) {
241   test::ScopedFieldTrials field_trials(
242       "WebRTC-NormalizeSimulcastResolution/Enabled-3/");
243   FieldTrialBasedConfig trials;
244 
245   const size_t kMinLayers = 1;
246   const size_t kMaxLayers = 2;
247   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
248       kMinLayers, kMaxLayers, 709, 501, kBitratePriority, kQpMax, !kScreenshare,
249       true, trials);
250 
251   // Must be divisible by |2 ^ 3|.
252   EXPECT_EQ(kMaxLayers, streams.size());
253   EXPECT_EQ(352u, streams[0].width);
254   EXPECT_EQ(248u, streams[0].height);
255   EXPECT_EQ(704u, streams[1].width);
256   EXPECT_EQ(496u, streams[1].height);
257 }
258 
TEST(SimulcastTest,GetConfigForLegacyLayerLimit)259 TEST(SimulcastTest, GetConfigForLegacyLayerLimit) {
260   test::ScopedFieldTrials field_trials(
261       "WebRTC-LegacySimulcastLayerLimit/Enabled/");
262   FieldTrialBasedConfig trials;
263 
264   const size_t kMinLayers = 1;
265   const int kMaxLayers = 3;
266   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
267       kMinLayers, kMaxLayers, 320, 180, kBitratePriority, kQpMax, !kScreenshare,
268       true, trials);
269   EXPECT_EQ(1u, streams.size());
270 
271   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 640, 360,
272                                         kBitratePriority, kQpMax, !kScreenshare,
273                                         true, trials);
274   EXPECT_EQ(2u, streams.size());
275 
276   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 1920, 1080,
277                                         kBitratePriority, kQpMax, !kScreenshare,
278                                         true, trials);
279   EXPECT_EQ(3u, streams.size());
280 }
281 
TEST(SimulcastTest,GetConfigForLegacyLayerLimitWithRequiredHD)282 TEST(SimulcastTest, GetConfigForLegacyLayerLimitWithRequiredHD) {
283   test::ScopedFieldTrials field_trials(
284       "WebRTC-LegacySimulcastLayerLimit/Enabled/");
285   FieldTrialBasedConfig trials;
286 
287   const size_t kMinLayers = 3;  // "HD" layer must be present!
288   const int kMaxLayers = 3;
289   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
290       kMinLayers, kMaxLayers, 320, 180, kBitratePriority, kQpMax, !kScreenshare,
291       true, trials);
292   EXPECT_EQ(3u, streams.size());
293 
294   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 640, 360,
295                                         kBitratePriority, kQpMax, !kScreenshare,
296                                         true, trials);
297   EXPECT_EQ(3u, streams.size());
298 
299   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 1920, 1080,
300                                         kBitratePriority, kQpMax, !kScreenshare,
301                                         true, trials);
302   EXPECT_EQ(3u, streams.size());
303 }
304 
TEST(SimulcastTest,GetConfigForScreenshareSimulcast)305 TEST(SimulcastTest, GetConfigForScreenshareSimulcast) {
306   FieldTrialBasedConfig trials;
307   const size_t kMinLayers = 1;
308   const size_t kMaxLayers = 3;
309   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
310       kMinLayers, kMaxLayers, 1400, 800, kBitratePriority, kQpMax, kScreenshare,
311       true, trials);
312 
313   EXPECT_GT(streams.size(), 1u);
314   for (size_t i = 0; i < streams.size(); ++i) {
315     EXPECT_EQ(1400u, streams[i].width) << "Screen content never scaled.";
316     EXPECT_EQ(800u, streams[i].height) << "Screen content never scaled.";
317     EXPECT_EQ(kQpMax, streams[i].max_qp);
318     EXPECT_TRUE(streams[i].active);
319     EXPECT_GT(streams[i].num_temporal_layers, size_t{1});
320     EXPECT_GT(streams[i].max_framerate, 0);
321     EXPECT_GT(streams[i].min_bitrate_bps, 0);
322     EXPECT_GT(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps);
323     EXPECT_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps);
324   }
325 }
326 
TEST(SimulcastTest,GetConfigForScreenshareSimulcastWithLimitedMaxLayers)327 TEST(SimulcastTest, GetConfigForScreenshareSimulcastWithLimitedMaxLayers) {
328   FieldTrialBasedConfig trials;
329   const size_t kMinLayers = 1;
330   const size_t kMaxLayers = 1;
331   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
332       kMinLayers, kMaxLayers, 1400, 800, kBitratePriority, kQpMax, kScreenshare,
333       true, trials);
334 
335   EXPECT_EQ(kMaxLayers, streams.size());
336 }
337 
TEST(SimulcastTest,AveragesBitratesForNonStandardResolution)338 TEST(SimulcastTest, AveragesBitratesForNonStandardResolution) {
339   FieldTrialBasedConfig trials;
340   const size_t kMinLayers = 1;
341   const size_t kMaxLayers = 3;
342   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
343       kMinLayers, kMaxLayers, 900, 800, kBitratePriority, kQpMax, !kScreenshare,
344       true, trials);
345 
346   EXPECT_EQ(kMaxLayers, streams.size());
347   EXPECT_EQ(900u, streams[2].width);
348   EXPECT_EQ(800u, streams[2].height);
349   EXPECT_EQ(1850000, streams[2].max_bitrate_bps);
350   EXPECT_EQ(1850000, streams[2].target_bitrate_bps);
351   EXPECT_EQ(475000, streams[2].min_bitrate_bps);
352 }
353 
TEST(SimulcastTest,BitratesForCloseToStandardResolution)354 TEST(SimulcastTest, BitratesForCloseToStandardResolution) {
355   const size_t kMinLayers = 1;
356   const size_t kMaxLayers = 3;
357   // Resolution very close to 720p in number of pixels
358   const size_t kWidth = 1280;
359   const size_t kHeight = 716;
360   const std::vector<VideoStream> kExpectedNear = GetSimulcastBitrates720p();
361   FieldTrialBasedConfig trials;
362 
363   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
364       kMinLayers, kMaxLayers, kWidth, kHeight, kBitratePriority, kQpMax,
365       !kScreenshare, true, trials);
366 
367   EXPECT_EQ(kMaxLayers, streams.size());
368   EXPECT_EQ(kWidth, streams[2].width);
369   EXPECT_EQ(kHeight, streams[2].height);
370   for (size_t i = 0; i < streams.size(); ++i) {
371     EXPECT_NEAR(kExpectedNear[i].max_bitrate_bps, streams[i].max_bitrate_bps,
372                 20000);
373     EXPECT_NEAR(kExpectedNear[i].target_bitrate_bps,
374                 streams[i].target_bitrate_bps, 20000);
375     EXPECT_NEAR(kExpectedNear[i].min_bitrate_bps, streams[i].min_bitrate_bps,
376                 20000);
377   }
378 }
379 
TEST(SimulcastTest,MaxLayersWithRoundUpDisabled)380 TEST(SimulcastTest, MaxLayersWithRoundUpDisabled) {
381   test::ScopedFieldTrials field_trials(
382       "WebRTC-SimulcastLayerLimitRoundUp/max_ratio:0.0/");
383   FieldTrialBasedConfig trials;
384   const size_t kMinLayers = 1;
385   const int kMaxLayers = 3;
386 
387   std::vector<VideoStream> streams;
388   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 540,
389                                         kBitratePriority, kQpMax, !kScreenshare,
390                                         true, trials);
391   EXPECT_EQ(3u, streams.size());
392   // <960x540: 2 layers
393   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 539,
394                                         kBitratePriority, kQpMax, !kScreenshare,
395                                         true, trials);
396   EXPECT_EQ(2u, streams.size());
397   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 270,
398                                         kBitratePriority, kQpMax, !kScreenshare,
399                                         true, trials);
400   EXPECT_EQ(2u, streams.size());
401   // <480x270: 1 layer
402   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 269,
403                                         kBitratePriority, kQpMax, !kScreenshare,
404                                         true, trials);
405   EXPECT_EQ(1u, streams.size());
406 }
407 
TEST(SimulcastTest,MaxLayersWithDefaultRoundUpRatio)408 TEST(SimulcastTest, MaxLayersWithDefaultRoundUpRatio) {
409   // Default: "WebRTC-SimulcastLayerLimitRoundUp/max_ratio:0.1/"
410   FieldTrialBasedConfig trials;
411   const size_t kMinLayers = 1;
412   const int kMaxLayers = 3;
413 
414   std::vector<VideoStream> streams;
415   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 540,
416                                         kBitratePriority, kQpMax, !kScreenshare,
417                                         true, trials);
418   EXPECT_EQ(3u, streams.size());
419   // Lowest cropped height where max layers from higher resolution is used.
420   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 512,
421                                         kBitratePriority, kQpMax, !kScreenshare,
422                                         true, trials);
423   EXPECT_EQ(3u, streams.size());
424   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 508,
425                                         kBitratePriority, kQpMax, !kScreenshare,
426                                         true, trials);
427   EXPECT_EQ(2u, streams.size());
428   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 270,
429                                         kBitratePriority, kQpMax, !kScreenshare,
430                                         true, trials);
431   EXPECT_EQ(2u, streams.size());
432   // Lowest cropped height where max layers from higher resolution is used.
433   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 256,
434                                         kBitratePriority, kQpMax, !kScreenshare,
435                                         true, trials);
436   EXPECT_EQ(2u, streams.size());
437   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 254,
438                                         kBitratePriority, kQpMax, !kScreenshare,
439                                         true, trials);
440   EXPECT_EQ(1u, streams.size());
441 }
442 
TEST(SimulcastTest,MaxLayersWithRoundUpRatio)443 TEST(SimulcastTest, MaxLayersWithRoundUpRatio) {
444   test::ScopedFieldTrials field_trials(
445       "WebRTC-SimulcastLayerLimitRoundUp/max_ratio:0.13/");
446   FieldTrialBasedConfig trials;
447   const size_t kMinLayers = 1;
448   const int kMaxLayers = 3;
449 
450   std::vector<VideoStream> streams;
451   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 270,
452                                         kBitratePriority, kQpMax, !kScreenshare,
453                                         true, trials);
454   EXPECT_EQ(2u, streams.size());
455   // Lowest cropped height where max layers from higher resolution is used.
456   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 252,
457                                         kBitratePriority, kQpMax, !kScreenshare,
458                                         true, trials);
459   EXPECT_EQ(2u, streams.size());
460   streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 250,
461                                         kBitratePriority, kQpMax, !kScreenshare,
462                                         true, trials);
463   EXPECT_EQ(1u, streams.size());
464 }
465 
TEST(SimulcastTest,BitratesInterpolatedForResBelow180p)466 TEST(SimulcastTest, BitratesInterpolatedForResBelow180p) {
467   // TODO(webrtc:12415): Remove when feature launches.
468   test::ScopedFieldTrials field_trials(
469       "WebRTC-LowresSimulcastBitrateInterpolation/Enabled/");
470 
471   const size_t kMaxLayers = 3;
472   FieldTrialBasedConfig trials;
473 
474   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
475       /* min_layers = */ 1, kMaxLayers, /* width = */ 960, /* height = */ 540,
476       kBitratePriority, kQpMax, !kScreenshare, true, trials);
477 
478   ASSERT_EQ(streams.size(), kMaxLayers);
479   EXPECT_EQ(240u, streams[0].width);
480   EXPECT_EQ(135u, streams[0].height);
481   EXPECT_EQ(streams[0].max_bitrate_bps, 112500);
482   EXPECT_EQ(streams[0].target_bitrate_bps, 84375);
483   EXPECT_EQ(streams[0].min_bitrate_bps, 30000);
484 }
485 
TEST(SimulcastTest,BitratesConsistentForVerySmallRes)486 TEST(SimulcastTest, BitratesConsistentForVerySmallRes) {
487   // TODO(webrtc:12415): Remove when feature launches.
488   test::ScopedFieldTrials field_trials(
489       "WebRTC-LowresSimulcastBitrateInterpolation/Enabled/");
490 
491   FieldTrialBasedConfig trials;
492 
493   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
494       /* min_layers = */ 1, /* max_layers = */ 3, /* width = */ 1,
495       /* height = */ 1, kBitratePriority, kQpMax, !kScreenshare, true, trials);
496 
497   ASSERT_TRUE(!streams.empty());
498   EXPECT_EQ(1u, streams[0].width);
499   EXPECT_EQ(1u, streams[0].height);
500   EXPECT_EQ(streams[0].max_bitrate_bps, 30000);
501   EXPECT_EQ(streams[0].target_bitrate_bps, 30000);
502   EXPECT_EQ(streams[0].min_bitrate_bps, 30000);
503 }
504 
TEST(SimulcastTest,BitratesNotInterpolatedForResBelow180pWhenDisabledTrialSet)505 TEST(SimulcastTest,
506      BitratesNotInterpolatedForResBelow180pWhenDisabledTrialSet) {
507   test::ScopedFieldTrials field_trials(
508       "WebRTC-LowresSimulcastBitrateInterpolation/Disabled/");
509 
510   const size_t kMaxLayers = 3;
511   FieldTrialBasedConfig trials;
512 
513   std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
514       /* min_layers = */ 1, kMaxLayers, /* width = */ 960, /* height = */ 540,
515       kBitratePriority, kQpMax, !kScreenshare, true, trials);
516 
517   ASSERT_EQ(streams.size(), kMaxLayers);
518   EXPECT_EQ(240u, streams[0].width);
519   EXPECT_EQ(135u, streams[0].height);
520   EXPECT_EQ(streams[0].max_bitrate_bps, 200000);
521   EXPECT_EQ(streams[0].target_bitrate_bps, 150000);
522   EXPECT_EQ(streams[0].min_bitrate_bps, 30000);
523 }
524 
525 }  // namespace webrtc
526