blob: e9d24e8044933a535890049d8a28c88040b00dc6 [file] [log] [blame]
Åsa Persson31cb8f92018-06-27 08:44:561/*
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
Jonas Oreland1262eb52022-09-27 14:53:0411#include "video/config/simulcast.h"
Åsa Persson31cb8f92018-06-27 08:44:5612
Steve Anton10542f22019-01-11 17:11:0013#include "media/base/media_constants.h"
Danil Chapovalov9a55e892024-04-15 12:07:5214#include "test/explicit_key_value_config.h"
Åsa Persson31cb8f92018-06-27 08:44:5615#include "test/gtest.h"
16
17namespace webrtc {
18namespace {
Danil Chapovalov9a55e892024-04-15 12:07:5219
20using test::ExplicitKeyValueConfig;
21
Åsa Persson31cb8f92018-06-27 08:44:5622constexpr int kQpMax = 55;
23constexpr double kBitratePriority = 2.0;
Åsa Persson31cb8f92018-06-27 08:44:5624constexpr bool kScreenshare = true;
25constexpr int kDefaultTemporalLayers = 3; // Value from simulcast.cc.
26
27// Values from kSimulcastConfigs in simulcast.cc.
28const std::vector<VideoStream> GetSimulcastBitrates720p() {
29 std::vector<VideoStream> streams(3);
30 streams[0].min_bitrate_bps = 30000;
31 streams[0].target_bitrate_bps = 150000;
32 streams[0].max_bitrate_bps = 200000;
33 streams[1].min_bitrate_bps = 150000;
34 streams[1].target_bitrate_bps = 500000;
35 streams[1].max_bitrate_bps = 700000;
36 streams[2].min_bitrate_bps = 600000;
37 streams[2].target_bitrate_bps = 2500000;
38 streams[2].max_bitrate_bps = 2500000;
39 return streams;
40}
41} // namespace
42
43TEST(SimulcastTest, TotalMaxBitrateIsZeroForNoStreams) {
44 std::vector<VideoStream> streams;
Oskar Segersvärddc81e112020-02-12 15:45:5345 EXPECT_EQ(0, cricket::GetTotalMaxBitrate(streams).bps());
Åsa Persson31cb8f92018-06-27 08:44:5646}
47
48TEST(SimulcastTest, GetTotalMaxBitrateForSingleStream) {
49 std::vector<VideoStream> streams(1);
50 streams[0].max_bitrate_bps = 100000;
Oskar Segersvärddc81e112020-02-12 15:45:5351 EXPECT_EQ(100000, cricket::GetTotalMaxBitrate(streams).bps());
Åsa Persson31cb8f92018-06-27 08:44:5652}
53
54TEST(SimulcastTest, GetTotalMaxBitrateForMultipleStreams) {
55 std::vector<VideoStream> streams(3);
56 streams[0].target_bitrate_bps = 100000;
57 streams[1].target_bitrate_bps = 200000;
58 streams[2].max_bitrate_bps = 400000;
Oskar Segersvärddc81e112020-02-12 15:45:5359 EXPECT_EQ(700000, cricket::GetTotalMaxBitrate(streams).bps());
Åsa Persson31cb8f92018-06-27 08:44:5660}
61
62TEST(SimulcastTest, BandwidthAboveTotalMaxBitrateGivenToHighestStream) {
63 std::vector<VideoStream> streams(3);
64 streams[0].target_bitrate_bps = 100000;
65 streams[1].target_bitrate_bps = 200000;
66 streams[2].max_bitrate_bps = 400000;
67
Danil Chapovalovcad3e0e2020-02-17 17:46:0768 const webrtc::DataRate one_bps = webrtc::DataRate::BitsPerSec(1);
Oskar Segersvärddc81e112020-02-12 15:45:5369
Åsa Persson31cb8f92018-06-27 08:44:5670 // No bitrate above the total max to give to the highest stream.
Oskar Segersvärddc81e112020-02-12 15:45:5371 const webrtc::DataRate max_total_bitrate =
72 cricket::GetTotalMaxBitrate(streams);
73 cricket::BoostMaxSimulcastLayer(max_total_bitrate, &streams);
Åsa Persson31cb8f92018-06-27 08:44:5674 EXPECT_EQ(400000, streams[2].max_bitrate_bps);
Oskar Segersvärddc81e112020-02-12 15:45:5375 EXPECT_EQ(max_total_bitrate, cricket::GetTotalMaxBitrate(streams));
Åsa Persson31cb8f92018-06-27 08:44:5676
77 // The bitrate above the total max should be given to the highest stream.
Oskar Segersvärddc81e112020-02-12 15:45:5378 cricket::BoostMaxSimulcastLayer(max_total_bitrate + one_bps, &streams);
Åsa Persson31cb8f92018-06-27 08:44:5679 EXPECT_EQ(400000 + 1, streams[2].max_bitrate_bps);
Oskar Segersvärddc81e112020-02-12 15:45:5380 EXPECT_EQ(max_total_bitrate + one_bps, cricket::GetTotalMaxBitrate(streams));
Åsa Persson31cb8f92018-06-27 08:44:5681}
82
83TEST(SimulcastTest, GetConfig) {
Danil Chapovalov9a55e892024-04-15 12:07:5284 const ExplicitKeyValueConfig trials("");
85
Åsa Persson31cb8f92018-06-27 08:44:5686 const std::vector<VideoStream> kExpected = GetSimulcastBitrates720p();
87
Ilya Nikolaevskiy03d90962020-02-11 11:50:3888 const size_t kMinLayers = 1;
Åsa Persson31cb8f92018-06-27 08:44:5689 const size_t kMaxLayers = 3;
90 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
Ilya Nikolaevskiy03d90962020-02-11 11:50:3891 kMinLayers, kMaxLayers, 1280, 720, kBitratePriority, kQpMax,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:3292 !kScreenshare, true, trials, webrtc::kVideoCodecVP8);
Åsa Persson31cb8f92018-06-27 08:44:5693
94 EXPECT_EQ(kMaxLayers, streams.size());
95 EXPECT_EQ(320u, streams[0].width);
96 EXPECT_EQ(180u, streams[0].height);
97 EXPECT_EQ(640u, streams[1].width);
98 EXPECT_EQ(360u, streams[1].height);
99 EXPECT_EQ(1280u, streams[2].width);
100 EXPECT_EQ(720u, streams[2].height);
101
102 for (size_t i = 0; i < streams.size(); ++i) {
Mirko Bonadei3d72f6d2018-07-20 13:35:41103 EXPECT_EQ(size_t{kDefaultTemporalLayers}, streams[i].num_temporal_layers);
Åsa Persson8c1bf952018-09-13 08:42:19104 EXPECT_EQ(cricket::kDefaultVideoMaxFramerate, streams[i].max_framerate);
Åsa Persson31cb8f92018-06-27 08:44:56105 EXPECT_EQ(kQpMax, streams[i].max_qp);
106 EXPECT_EQ(kExpected[i].min_bitrate_bps, streams[i].min_bitrate_bps);
107 EXPECT_EQ(kExpected[i].target_bitrate_bps, streams[i].target_bitrate_bps);
108 EXPECT_EQ(kExpected[i].max_bitrate_bps, streams[i].max_bitrate_bps);
109 EXPECT_TRUE(streams[i].active);
110 }
111 // Currently set on lowest stream.
112 EXPECT_EQ(kBitratePriority, streams[0].bitrate_priority);
113 EXPECT_FALSE(streams[1].bitrate_priority);
114 EXPECT_FALSE(streams[2].bitrate_priority);
115}
116
Rasmus Brandt73d117f2018-10-02 09:12:52117TEST(SimulcastTest, GetConfigWithBaseHeavyVP8TL3RateAllocation) {
Danil Chapovalov9a55e892024-04-15 12:07:52118 ExplicitKeyValueConfig trials(
Rasmus Brandt73d117f2018-10-02 09:12:52119 "WebRTC-UseBaseHeavyVP8TL3RateAllocation/Enabled/");
120
121 const std::vector<VideoStream> kExpected = GetSimulcastBitrates720p();
122
Ilya Nikolaevskiy03d90962020-02-11 11:50:38123 const size_t kMinLayers = 1;
Rasmus Brandt73d117f2018-10-02 09:12:52124 const size_t kMaxLayers = 3;
125 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
Ilya Nikolaevskiy03d90962020-02-11 11:50:38126 kMinLayers, kMaxLayers, 1280, 720, kBitratePriority, kQpMax,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32127 !kScreenshare, true, trials, webrtc::kVideoCodecVP8);
Rasmus Brandt73d117f2018-10-02 09:12:52128
129 EXPECT_EQ(kExpected[0].min_bitrate_bps, streams[0].min_bitrate_bps);
130 EXPECT_EQ(static_cast<int>(0.4 * kExpected[0].target_bitrate_bps / 0.6),
131 streams[0].target_bitrate_bps);
132 EXPECT_EQ(static_cast<int>(0.4 * kExpected[0].max_bitrate_bps / 0.6),
133 streams[0].max_bitrate_bps);
134 for (size_t i = 1; i < streams.size(); ++i) {
135 EXPECT_EQ(kExpected[i].min_bitrate_bps, streams[i].min_bitrate_bps);
136 EXPECT_EQ(kExpected[i].target_bitrate_bps, streams[i].target_bitrate_bps);
137 EXPECT_EQ(kExpected[i].max_bitrate_bps, streams[i].max_bitrate_bps);
138 }
139}
140
Åsa Persson31cb8f92018-06-27 08:44:56141TEST(SimulcastTest, GetConfigWithLimitedMaxLayers) {
Danil Chapovalov9a55e892024-04-15 12:07:52142 ExplicitKeyValueConfig trials("");
143
Ilya Nikolaevskiy03d90962020-02-11 11:50:38144 const size_t kMinLayers = 1;
Åsa Persson31cb8f92018-06-27 08:44:56145 const size_t kMaxLayers = 2;
146 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
Ilya Nikolaevskiy03d90962020-02-11 11:50:38147 kMinLayers, kMaxLayers, 1280, 720, kBitratePriority, kQpMax,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32148 !kScreenshare, true, trials, webrtc::kVideoCodecVP8);
Åsa Persson31cb8f92018-06-27 08:44:56149
150 EXPECT_EQ(kMaxLayers, streams.size());
Florent Castelli668ce0c2019-07-04 15:06:04151 EXPECT_EQ(640u, streams[0].width);
152 EXPECT_EQ(360u, streams[0].height);
153 EXPECT_EQ(1280u, streams[1].width);
154 EXPECT_EQ(720u, streams[1].height);
Åsa Persson31cb8f92018-06-27 08:44:56155}
156
Åsa Persson645512b2018-09-14 14:42:58157TEST(SimulcastTest, GetConfigWithLimitedMaxLayersForResolution) {
Danil Chapovalov9a55e892024-04-15 12:07:52158 ExplicitKeyValueConfig trials(
Florent Castelli9b1700c2019-08-05 15:12:20159 "WebRTC-LegacySimulcastLayerLimit/Enabled/");
Danil Chapovalov9a55e892024-04-15 12:07:52160
Ilya Nikolaevskiy03d90962020-02-11 11:50:38161 const size_t kMinLayers = 1;
Åsa Persson645512b2018-09-14 14:42:58162 const size_t kMaxLayers = 3;
163 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
Ilya Nikolaevskiy03d90962020-02-11 11:50:38164 kMinLayers, kMaxLayers, 800, 600, kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32165 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson645512b2018-09-14 14:42:58166
Florent Castelli9b1700c2019-08-05 15:12:20167 EXPECT_EQ(2u, streams.size());
168 EXPECT_EQ(400u, streams[0].width);
169 EXPECT_EQ(300u, streams[0].height);
170 EXPECT_EQ(800u, streams[1].width);
171 EXPECT_EQ(600u, streams[1].height);
Åsa Persson645512b2018-09-14 14:42:58172}
173
Ilya Nikolaevskiy9d7eb282019-10-01 13:43:14174TEST(SimulcastTest, GetConfigWithLowResolutionScreenshare) {
Danil Chapovalov9a55e892024-04-15 12:07:52175 ExplicitKeyValueConfig trials(
Ilya Nikolaevskiy9d7eb282019-10-01 13:43:14176 "WebRTC-LegacySimulcastLayerLimit/Enabled/");
Danil Chapovalov9a55e892024-04-15 12:07:52177
Ilya Nikolaevskiy03d90962020-02-11 11:50:38178 const size_t kMinLayers = 1;
Ilya Nikolaevskiy9d7eb282019-10-01 13:43:14179 const size_t kMaxLayers = 3;
Erik Språngceb44952020-09-22 09:36:35180 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
181 kMinLayers, kMaxLayers, 100, 100, kBitratePriority, kQpMax, kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32182 true, trials, webrtc::kVideoCodecVP8);
Ilya Nikolaevskiy9d7eb282019-10-01 13:43:14183
184 // Simulcast streams number is never decreased for screenshare,
185 // even for very low resolution.
186 EXPECT_GT(streams.size(), 1u);
187}
188
Åsa Persson645512b2018-09-14 14:42:58189TEST(SimulcastTest, GetConfigWithNotLimitedMaxLayersForResolution) {
Danil Chapovalov9a55e892024-04-15 12:07:52190 ExplicitKeyValueConfig trials(
Florent Castelli9b1700c2019-08-05 15:12:20191 "WebRTC-LegacySimulcastLayerLimit/Disabled/");
Danil Chapovalov9a55e892024-04-15 12:07:52192
Ilya Nikolaevskiy03d90962020-02-11 11:50:38193 const size_t kMinLayers = 1;
Åsa Persson645512b2018-09-14 14:42:58194 const size_t kMaxLayers = 3;
195 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
Ilya Nikolaevskiy03d90962020-02-11 11:50:38196 kMinLayers, kMaxLayers, 800, 600, kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32197 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson645512b2018-09-14 14:42:58198
199 EXPECT_EQ(kMaxLayers, streams.size());
200 EXPECT_EQ(200u, streams[0].width);
201 EXPECT_EQ(150u, streams[0].height);
202 EXPECT_EQ(400u, streams[1].width);
203 EXPECT_EQ(300u, streams[1].height);
204 EXPECT_EQ(800u, streams[2].width);
205 EXPECT_EQ(600u, streams[2].height);
206}
207
Åsa Persson31cb8f92018-06-27 08:44:56208TEST(SimulcastTest, GetConfigWithNormalizedResolution) {
Danil Chapovalov9a55e892024-04-15 12:07:52209 ExplicitKeyValueConfig trials("");
210
Ilya Nikolaevskiy03d90962020-02-11 11:50:38211 const size_t kMinLayers = 1;
Åsa Persson31cb8f92018-06-27 08:44:56212 const size_t kMaxLayers = 2;
213 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
Ilya Nikolaevskiy03d90962020-02-11 11:50:38214 kMinLayers, kMaxLayers, 640 + 1, 360 + 1, kBitratePriority, kQpMax,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32215 !kScreenshare, true, trials, webrtc::kVideoCodecVP8);
Åsa Persson31cb8f92018-06-27 08:44:56216
Åsa Persson1a35fbd2018-10-12 15:36:57217 // Must be divisible by |2 ^ (num_layers - 1)|.
Åsa Persson31cb8f92018-06-27 08:44:56218 EXPECT_EQ(kMaxLayers, streams.size());
219 EXPECT_EQ(320u, streams[0].width);
220 EXPECT_EQ(180u, streams[0].height);
221 EXPECT_EQ(640u, streams[1].width);
222 EXPECT_EQ(360u, streams[1].height);
223}
224
Åsa Persson1a35fbd2018-10-12 15:36:57225TEST(SimulcastTest, GetConfigWithNormalizedResolutionDivisibleBy4) {
Danil Chapovalov9a55e892024-04-15 12:07:52226 ExplicitKeyValueConfig trials(
Åsa Persson1a35fbd2018-10-12 15:36:57227 "WebRTC-NormalizeSimulcastResolution/Enabled-2/");
228
Ilya Nikolaevskiy03d90962020-02-11 11:50:38229 const size_t kMinLayers = 1;
Åsa Persson1a35fbd2018-10-12 15:36:57230 const size_t kMaxLayers = 2;
231 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
Ilya Nikolaevskiy03d90962020-02-11 11:50:38232 kMinLayers, kMaxLayers, 709, 501, kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32233 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson1a35fbd2018-10-12 15:36:57234
235 // Must be divisible by |2 ^ 2|.
236 EXPECT_EQ(kMaxLayers, streams.size());
237 EXPECT_EQ(354u, streams[0].width);
238 EXPECT_EQ(250u, streams[0].height);
239 EXPECT_EQ(708u, streams[1].width);
240 EXPECT_EQ(500u, streams[1].height);
241}
242
243TEST(SimulcastTest, GetConfigWithNormalizedResolutionDivisibleBy8) {
Danil Chapovalov9a55e892024-04-15 12:07:52244 ExplicitKeyValueConfig trials(
Åsa Persson1a35fbd2018-10-12 15:36:57245 "WebRTC-NormalizeSimulcastResolution/Enabled-3/");
246
Ilya Nikolaevskiy03d90962020-02-11 11:50:38247 const size_t kMinLayers = 1;
Åsa Persson1a35fbd2018-10-12 15:36:57248 const size_t kMaxLayers = 2;
249 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
Ilya Nikolaevskiy03d90962020-02-11 11:50:38250 kMinLayers, kMaxLayers, 709, 501, kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32251 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson1a35fbd2018-10-12 15:36:57252
253 // Must be divisible by |2 ^ 3|.
254 EXPECT_EQ(kMaxLayers, streams.size());
255 EXPECT_EQ(352u, streams[0].width);
256 EXPECT_EQ(248u, streams[0].height);
257 EXPECT_EQ(704u, streams[1].width);
258 EXPECT_EQ(496u, streams[1].height);
259}
260
Florent Castellia9fbb222019-07-24 14:06:45261TEST(SimulcastTest, GetConfigForLegacyLayerLimit) {
Danil Chapovalov9a55e892024-04-15 12:07:52262 ExplicitKeyValueConfig trials(
Florent Castellia9fbb222019-07-24 14:06:45263 "WebRTC-LegacySimulcastLayerLimit/Enabled/");
264
Ilya Nikolaevskiy03d90962020-02-11 11:50:38265 const size_t kMinLayers = 1;
Florent Castellia9fbb222019-07-24 14:06:45266 const int kMaxLayers = 3;
267 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
Ilya Nikolaevskiy03d90962020-02-11 11:50:38268 kMinLayers, kMaxLayers, 320, 180, kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32269 true, trials, webrtc::kVideoCodecVP8);
Florent Castellia9fbb222019-07-24 14:06:45270 EXPECT_EQ(1u, streams.size());
271
Ilya Nikolaevskiy03d90962020-02-11 11:50:38272 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 640, 360,
273 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32274 true, trials, webrtc::kVideoCodecVP8);
Florent Castellia9fbb222019-07-24 14:06:45275 EXPECT_EQ(2u, streams.size());
276
Ilya Nikolaevskiy03d90962020-02-11 11:50:38277 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 1920, 1080,
278 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32279 true, trials, webrtc::kVideoCodecVP8);
Ilya Nikolaevskiy03d90962020-02-11 11:50:38280 EXPECT_EQ(3u, streams.size());
281}
282
283TEST(SimulcastTest, GetConfigForLegacyLayerLimitWithRequiredHD) {
Danil Chapovalov9a55e892024-04-15 12:07:52284 ExplicitKeyValueConfig trials(
Ilya Nikolaevskiy03d90962020-02-11 11:50:38285 "WebRTC-LegacySimulcastLayerLimit/Enabled/");
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,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32291 true, trials, webrtc::kVideoCodecVP8);
Ilya Nikolaevskiy03d90962020-02-11 11:50:38292 EXPECT_EQ(3u, streams.size());
293
294 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 640, 360,
295 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32296 true, trials, webrtc::kVideoCodecVP8);
Ilya Nikolaevskiy03d90962020-02-11 11:50:38297 EXPECT_EQ(3u, streams.size());
298
299 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 1920, 1080,
300 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32301 true, trials, webrtc::kVideoCodecVP8);
Florent Castellia9fbb222019-07-24 14:06:45302 EXPECT_EQ(3u, streams.size());
303}
304
Åsa Persson31cb8f92018-06-27 08:44:56305TEST(SimulcastTest, GetConfigForScreenshareSimulcast) {
Danil Chapovalov9a55e892024-04-15 12:07:52306 ExplicitKeyValueConfig trials("");
Ilya Nikolaevskiy03d90962020-02-11 11:50:38307 const size_t kMinLayers = 1;
Åsa Persson31cb8f92018-06-27 08:44:56308 const size_t kMaxLayers = 3;
Erik Språngceb44952020-09-22 09:36:35309 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
310 kMinLayers, kMaxLayers, 1400, 800, kBitratePriority, kQpMax, kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32311 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson31cb8f92018-06-27 08:44:56312
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);
Mirko Bonadei3d72f6d2018-07-20 13:35:41319 EXPECT_GT(streams[i].num_temporal_layers, size_t{1});
Åsa Persson31cb8f92018-06-27 08:44:56320 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
327TEST(SimulcastTest, GetConfigForScreenshareSimulcastWithLimitedMaxLayers) {
Danil Chapovalov9a55e892024-04-15 12:07:52328 ExplicitKeyValueConfig trials("");
Ilya Nikolaevskiy03d90962020-02-11 11:50:38329 const size_t kMinLayers = 1;
Åsa Persson31cb8f92018-06-27 08:44:56330 const size_t kMaxLayers = 1;
Erik Språngceb44952020-09-22 09:36:35331 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
332 kMinLayers, kMaxLayers, 1400, 800, kBitratePriority, kQpMax, kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32333 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson31cb8f92018-06-27 08:44:56334
335 EXPECT_EQ(kMaxLayers, streams.size());
336}
337
Ilya Nikolaevskiy73ceed52019-09-16 12:53:29338TEST(SimulcastTest, AveragesBitratesForNonStandardResolution) {
Danil Chapovalov9a55e892024-04-15 12:07:52339 ExplicitKeyValueConfig trials("");
Ilya Nikolaevskiy03d90962020-02-11 11:50:38340 const size_t kMinLayers = 1;
Ilya Nikolaevskiy73ceed52019-09-16 12:53:29341 const size_t kMaxLayers = 3;
342 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
Ilya Nikolaevskiy03d90962020-02-11 11:50:38343 kMinLayers, kMaxLayers, 900, 800, kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32344 true, trials, webrtc::kVideoCodecVP8);
Ilya Nikolaevskiy73ceed52019-09-16 12:53:29345
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
354TEST(SimulcastTest, BitratesForCloseToStandardResolution) {
Danil Chapovalov9a55e892024-04-15 12:07:52355 ExplicitKeyValueConfig trials("");
356
Ilya Nikolaevskiy03d90962020-02-11 11:50:38357 const size_t kMinLayers = 1;
Ilya Nikolaevskiy73ceed52019-09-16 12:53:29358 const size_t kMaxLayers = 3;
359 // Resolution very close to 720p in number of pixels
360 const size_t kWidth = 1280;
361 const size_t kHeight = 716;
362 const std::vector<VideoStream> kExpectedNear = GetSimulcastBitrates720p();
363
364 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
Ilya Nikolaevskiy03d90962020-02-11 11:50:38365 kMinLayers, kMaxLayers, kWidth, kHeight, kBitratePriority, kQpMax,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32366 !kScreenshare, true, trials, webrtc::kVideoCodecVP8);
Ilya Nikolaevskiy73ceed52019-09-16 12:53:29367
368 EXPECT_EQ(kMaxLayers, streams.size());
369 EXPECT_EQ(kWidth, streams[2].width);
370 EXPECT_EQ(kHeight, streams[2].height);
371 for (size_t i = 0; i < streams.size(); ++i) {
372 EXPECT_NEAR(kExpectedNear[i].max_bitrate_bps, streams[i].max_bitrate_bps,
373 20000);
374 EXPECT_NEAR(kExpectedNear[i].target_bitrate_bps,
375 streams[i].target_bitrate_bps, 20000);
376 EXPECT_NEAR(kExpectedNear[i].min_bitrate_bps, streams[i].min_bitrate_bps,
377 20000);
378 }
379}
380
Åsa Persson2afff372021-02-11 16:31:11381TEST(SimulcastTest, MaxLayersWithRoundUpDisabled) {
Danil Chapovalov9a55e892024-04-15 12:07:52382 ExplicitKeyValueConfig trials(
Åsa Persson2afff372021-02-11 16:31:11383 "WebRTC-SimulcastLayerLimitRoundUp/max_ratio:0.0/");
Danil Chapovalov9a55e892024-04-15 12:07:52384
Åsa Persson29bd8632021-01-18 08:15:07385 const size_t kMinLayers = 1;
386 const int kMaxLayers = 3;
387
388 std::vector<VideoStream> streams;
389 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 540,
390 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32391 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson29bd8632021-01-18 08:15:07392 EXPECT_EQ(3u, streams.size());
393 // <960x540: 2 layers
394 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 539,
395 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32396 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson29bd8632021-01-18 08:15:07397 EXPECT_EQ(2u, streams.size());
398 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 270,
399 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32400 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson29bd8632021-01-18 08:15:07401 EXPECT_EQ(2u, streams.size());
402 // <480x270: 1 layer
403 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 269,
404 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32405 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson29bd8632021-01-18 08:15:07406 EXPECT_EQ(1u, streams.size());
407}
408
Åsa Persson2afff372021-02-11 16:31:11409TEST(SimulcastTest, MaxLayersWithDefaultRoundUpRatio) {
410 // Default: "WebRTC-SimulcastLayerLimitRoundUp/max_ratio:0.1/"
Danil Chapovalov9a55e892024-04-15 12:07:52411 ExplicitKeyValueConfig trials("");
Åsa Persson29bd8632021-01-18 08:15:07412 const size_t kMinLayers = 1;
413 const int kMaxLayers = 3;
414
415 std::vector<VideoStream> streams;
416 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 540,
417 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32418 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson29bd8632021-01-18 08:15:07419 EXPECT_EQ(3u, streams.size());
420 // Lowest cropped height where max layers from higher resolution is used.
421 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 512,
422 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32423 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson29bd8632021-01-18 08:15:07424 EXPECT_EQ(3u, streams.size());
Åsa Persson2afff372021-02-11 16:31:11425 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 508,
Åsa Persson29bd8632021-01-18 08:15:07426 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32427 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson29bd8632021-01-18 08:15:07428 EXPECT_EQ(2u, streams.size());
429 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 270,
430 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32431 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson29bd8632021-01-18 08:15:07432 EXPECT_EQ(2u, streams.size());
433 // Lowest cropped height where max layers from higher resolution is used.
434 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 256,
435 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32436 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson29bd8632021-01-18 08:15:07437 EXPECT_EQ(2u, streams.size());
438 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 254,
439 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32440 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson29bd8632021-01-18 08:15:07441 EXPECT_EQ(1u, streams.size());
442}
443
Åsa Persson2afff372021-02-11 16:31:11444TEST(SimulcastTest, MaxLayersWithRoundUpRatio) {
Danil Chapovalov9a55e892024-04-15 12:07:52445 ExplicitKeyValueConfig trials(
Åsa Persson2afff372021-02-11 16:31:11446 "WebRTC-SimulcastLayerLimitRoundUp/max_ratio:0.13/");
Danil Chapovalov9a55e892024-04-15 12:07:52447
Åsa Persson2afff372021-02-11 16:31:11448 const size_t kMinLayers = 1;
449 const int kMaxLayers = 3;
450
451 std::vector<VideoStream> streams;
452 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 270,
453 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32454 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson2afff372021-02-11 16:31:11455 EXPECT_EQ(2u, streams.size());
456 // Lowest cropped height where max layers from higher resolution is used.
457 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 252,
458 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32459 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson2afff372021-02-11 16:31:11460 EXPECT_EQ(2u, streams.size());
461 streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 250,
462 kBitratePriority, kQpMax, !kScreenshare,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32463 true, trials, webrtc::kVideoCodecVP8);
Åsa Persson2afff372021-02-11 16:31:11464 EXPECT_EQ(1u, streams.size());
465}
466
Rasmus Brandt9673ca42021-01-29 12:21:16467TEST(SimulcastTest, BitratesInterpolatedForResBelow180p) {
468 // TODO(webrtc:12415): Remove when feature launches.
Danil Chapovalov9a55e892024-04-15 12:07:52469 ExplicitKeyValueConfig trials(
Rasmus Brandt9673ca42021-01-29 12:21:16470 "WebRTC-LowresSimulcastBitrateInterpolation/Enabled/");
471
472 const size_t kMaxLayers = 3;
Rasmus Brandt9673ca42021-01-29 12:21:16473 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
474 /* min_layers = */ 1, kMaxLayers, /* width = */ 960, /* height = */ 540,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32475 kBitratePriority, kQpMax, !kScreenshare, true, trials,
476 webrtc::kVideoCodecVP8);
Rasmus Brandt9673ca42021-01-29 12:21:16477
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
486TEST(SimulcastTest, BitratesConsistentForVerySmallRes) {
487 // TODO(webrtc:12415): Remove when feature launches.
Danil Chapovalov9a55e892024-04-15 12:07:52488 ExplicitKeyValueConfig trials(
Rasmus Brandt9673ca42021-01-29 12:21:16489 "WebRTC-LowresSimulcastBitrateInterpolation/Enabled/");
490
Rasmus Brandt9673ca42021-01-29 12:21:16491 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
492 /* min_layers = */ 1, /* max_layers = */ 3, /* width = */ 1,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32493 /* height = */ 1, kBitratePriority, kQpMax, !kScreenshare, true, trials,
494 webrtc::kVideoCodecVP8);
Rasmus Brandt9673ca42021-01-29 12:21:16495
496 ASSERT_TRUE(!streams.empty());
497 EXPECT_EQ(1u, streams[0].width);
498 EXPECT_EQ(1u, streams[0].height);
499 EXPECT_EQ(streams[0].max_bitrate_bps, 30000);
500 EXPECT_EQ(streams[0].target_bitrate_bps, 30000);
501 EXPECT_EQ(streams[0].min_bitrate_bps, 30000);
502}
503
504TEST(SimulcastTest,
505 BitratesNotInterpolatedForResBelow180pWhenDisabledTrialSet) {
Danil Chapovalov9a55e892024-04-15 12:07:52506 ExplicitKeyValueConfig trials(
Rasmus Brandt9673ca42021-01-29 12:21:16507 "WebRTC-LowresSimulcastBitrateInterpolation/Disabled/");
508
509 const size_t kMaxLayers = 3;
Rasmus Brandt9673ca42021-01-29 12:21:16510 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
511 /* min_layers = */ 1, kMaxLayers, /* width = */ 960, /* height = */ 540,
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32512 kBitratePriority, kQpMax, !kScreenshare, true, trials,
513 webrtc::kVideoCodecVP8);
Rasmus Brandt9673ca42021-01-29 12:21:16514
515 ASSERT_EQ(streams.size(), kMaxLayers);
516 EXPECT_EQ(240u, streams[0].width);
517 EXPECT_EQ(135u, streams[0].height);
518 EXPECT_EQ(streams[0].max_bitrate_bps, 200000);
519 EXPECT_EQ(streams[0].target_bitrate_bps, 150000);
520 EXPECT_EQ(streams[0].min_bitrate_bps, 30000);
521}
522
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32523TEST(SimulcastTest, BitratesBasedOnCodec) {
Danil Chapovalov9a55e892024-04-15 12:07:52524 ExplicitKeyValueConfig trials("");
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32525
Danil Chapovalov9a55e892024-04-15 12:07:52526 const size_t kMaxLayers = 3;
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32527 std::vector<VideoStream> streams_vp8 = cricket::GetSimulcastConfig(
528 /* min_layers = */ 1, /* max_layers = */ 3, /* width = */ 1280,
529 /* height = */ 720, kBitratePriority, kQpMax, !kScreenshare, true, trials,
530 webrtc::kVideoCodecVP8);
531
532 std::vector<VideoStream> streams_vp9 = cricket::GetSimulcastConfig(
533 /* min_layers = */ 1, /* max_layers = */ 3, /* width = */ 1280,
534 /* height = */ 720, kBitratePriority, kQpMax, !kScreenshare, true, trials,
535 webrtc::kVideoCodecVP9);
536
537 ASSERT_EQ(streams_vp8.size(), kMaxLayers);
538 ASSERT_EQ(streams_vp9.size(), kMaxLayers);
539
540 EXPECT_EQ(streams_vp9[0].width, streams_vp8[0].width);
541 EXPECT_EQ(streams_vp9[0].height, streams_vp8[0].height);
542
543 EXPECT_NE(streams_vp9[0].max_bitrate_bps, streams_vp8[0].max_bitrate_bps);
544 EXPECT_NE(streams_vp9[0].target_bitrate_bps,
545 streams_vp8[0].target_bitrate_bps);
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32546
547 EXPECT_NE(streams_vp9[1].max_bitrate_bps, streams_vp8[1].max_bitrate_bps);
548 EXPECT_NE(streams_vp9[1].target_bitrate_bps,
549 streams_vp8[1].target_bitrate_bps);
550 EXPECT_NE(streams_vp9[1].min_bitrate_bps, streams_vp8[1].min_bitrate_bps);
551
552 EXPECT_NE(streams_vp9[2].max_bitrate_bps, streams_vp8[2].max_bitrate_bps);
553 EXPECT_NE(streams_vp9[2].target_bitrate_bps,
554 streams_vp8[2].target_bitrate_bps);
555 EXPECT_NE(streams_vp9[2].min_bitrate_bps, streams_vp8[2].min_bitrate_bps);
556}
557
558TEST(SimulcastTest, BitratesForVP9) {
Danil Chapovalov9a55e892024-04-15 12:07:52559 ExplicitKeyValueConfig trials("");
560
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32561 const size_t kMaxLayers = 3;
Ilya Nikolaevskiy98aba6b2024-03-15 13:28:32562
563 std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
564 /* min_layers = */ 1, kMaxLayers, /* width = */ 1280, /* height = */ 720,
565 kBitratePriority, kQpMax, !kScreenshare, true, trials,
566 webrtc::kVideoCodecVP9);
567
568 ASSERT_EQ(streams.size(), kMaxLayers);
569 EXPECT_EQ(1280u, streams[2].width);
570 EXPECT_EQ(720u, streams[2].height);
571 EXPECT_EQ(streams[2].max_bitrate_bps, 1524000);
572 EXPECT_EQ(streams[2].target_bitrate_bps, 1524000);
573 EXPECT_EQ(streams[2].min_bitrate_bps, 481000);
574
575 streams = cricket::GetSimulcastConfig(
576 /* min_layers = */ 1, kMaxLayers, /* width = */ 1276, /* height = */ 716,
577 kBitratePriority, kQpMax, !kScreenshare, true, trials,
578 webrtc::kVideoCodecVP9);
579
580 ASSERT_EQ(streams.size(), kMaxLayers);
581 EXPECT_EQ(1276u, streams[2].width);
582 EXPECT_EQ(716u, streams[2].height);
583 EXPECT_NEAR(streams[2].max_bitrate_bps, 1524000, 20000);
584 EXPECT_NEAR(streams[2].target_bitrate_bps, 1524000, 20000);
585 EXPECT_NEAR(streams[2].min_bitrate_bps, 481000, 20000);
586}
587
Åsa Persson31cb8f92018-06-27 08:44:56588} // namespace webrtc