blob: 29ebb6a9129f04a3be4ed22b8b5eb570c3a8ef96 [file] [log] [blame]
Sergey Silkin8c007ff2021-01-22 17:59:591/*
2 * Copyright 2021 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/adaptation/bitrate_constraint.h"
12
Sergey Silkin8c007ff2021-01-22 17:59:5913#include <utility>
14#include <vector>
15
Asa Persson2ee3e4d2022-05-20 12:22:2716#include "api/video_codecs/scalability_mode.h"
Sergey Silkin8c007ff2021-01-22 17:59:5917#include "api/video_codecs/video_encoder.h"
18#include "call/adaptation/encoder_settings.h"
Åsa Persson64f7da02021-03-01 08:38:5719#include "call/adaptation/test/fake_frame_rate_provider.h"
Sergey Silkin8c007ff2021-01-22 17:59:5920#include "call/adaptation/video_source_restrictions.h"
Åsa Persson64f7da02021-03-01 08:38:5721#include "call/adaptation/video_stream_input_state_provider.h"
Sergey Silkin8c007ff2021-01-22 17:59:5922#include "test/gtest.h"
23
24namespace webrtc {
25
Sergey Silkin8c007ff2021-01-22 17:59:5926namespace {
Asa Persson2ee3e4d2022-05-20 12:22:2727const VideoSourceRestrictions k180p{/*max_pixels_per_frame=*/320 * 180,
28 /*target_pixels_per_frame=*/320 * 180,
29 /*max_frame_rate=*/30};
Åsa Persson64f7da02021-03-01 08:38:5730const VideoSourceRestrictions k360p{/*max_pixels_per_frame=*/640 * 360,
31 /*target_pixels_per_frame=*/640 * 360,
32 /*max_frame_rate=*/30};
33const VideoSourceRestrictions k720p{/*max_pixels_per_frame=*/1280 * 720,
34 /*target_pixels_per_frame=*/1280 * 720,
35 /*max_frame_rate=*/30};
Sergey Silkin8c007ff2021-01-22 17:59:5936
Asa Persson2ee3e4d2022-05-20 12:22:2737struct TestParams {
38 bool active;
Florent Castelli8037fc62024-08-29 13:00:4039 std::optional<ScalabilityMode> scalability_mode;
Asa Persson2ee3e4d2022-05-20 12:22:2740};
41
Sergey Silkin8c007ff2021-01-22 17:59:5942void FillCodecConfig(VideoCodec* video_codec,
43 VideoEncoderConfig* encoder_config,
44 int width_px,
45 int height_px,
Asa Persson2ee3e4d2022-05-20 12:22:2746 const std::vector<TestParams>& params,
47 bool svc) {
48 size_t num_layers = params.size();
Sergey Silkin8c007ff2021-01-22 17:59:5949 video_codec->codecType = kVideoCodecVP8;
Henrik Boström2fec6442023-06-15 10:49:2650 video_codec->numberOfSimulcastStreams = svc ? 1 : num_layers;
Sergey Silkin8c007ff2021-01-22 17:59:5951
Asa Persson2ee3e4d2022-05-20 12:22:2752 encoder_config->number_of_streams = svc ? 1 : num_layers;
Sergey Silkin8c007ff2021-01-22 17:59:5953 encoder_config->simulcast_layers.resize(num_layers);
54
55 for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
56 int layer_width_px = width_px >> (num_layers - 1 - layer_idx);
57 int layer_height_px = height_px >> (num_layers - 1 - layer_idx);
58
Asa Persson2ee3e4d2022-05-20 12:22:2759 if (params[layer_idx].scalability_mode)
60 video_codec->SetScalabilityMode(*params[layer_idx].scalability_mode);
61 video_codec->simulcastStream[layer_idx].active = params[layer_idx].active;
Sergey Silkin8c007ff2021-01-22 17:59:5962 video_codec->simulcastStream[layer_idx].width = layer_width_px;
63 video_codec->simulcastStream[layer_idx].height = layer_height_px;
64
Asa Persson2ee3e4d2022-05-20 12:22:2765 encoder_config->simulcast_layers[layer_idx].scalability_mode =
66 params[layer_idx].scalability_mode;
Sergey Silkin8c007ff2021-01-22 17:59:5967 encoder_config->simulcast_layers[layer_idx].active =
Asa Persson2ee3e4d2022-05-20 12:22:2768 params[layer_idx].active;
Sergey Silkin8c007ff2021-01-22 17:59:5969 encoder_config->simulcast_layers[layer_idx].width = layer_width_px;
70 encoder_config->simulcast_layers[layer_idx].height = layer_height_px;
71 }
72}
73
Asa Persson2ee3e4d2022-05-20 12:22:2774constexpr int kStartBitrateBps360p = 500000;
Åsa Persson64f7da02021-03-01 08:38:5775constexpr int kStartBitrateBps720p = 1000000;
76
Sergey Silkin8c007ff2021-01-22 17:59:5977VideoEncoder::EncoderInfo MakeEncoderInfo() {
78 VideoEncoder::EncoderInfo encoder_info;
Åsa Persson64f7da02021-03-01 08:38:5779 encoder_info.resolution_bitrate_limits = {
Asa Persson2ee3e4d2022-05-20 12:22:2780 {640 * 360, kStartBitrateBps360p, 0, 5000000},
Åsa Persson64f7da02021-03-01 08:38:5781 {1280 * 720, kStartBitrateBps720p, 0, 5000000},
82 {1920 * 1080, 2000000, 0, 5000000}};
Sergey Silkin8c007ff2021-01-22 17:59:5983 return encoder_info;
84}
Åsa Persson64f7da02021-03-01 08:38:5785
Sergey Silkin8c007ff2021-01-22 17:59:5986} // namespace
87
Åsa Persson64f7da02021-03-01 08:38:5788class BitrateConstraintTest : public ::testing::Test {
89 public:
90 BitrateConstraintTest()
91 : frame_rate_provider_(), input_state_provider_(&frame_rate_provider_) {}
Sergey Silkin8c007ff2021-01-22 17:59:5992
Åsa Persson64f7da02021-03-01 08:38:5793 protected:
94 void OnEncoderSettingsUpdated(int width_px,
95 int height_px,
Asa Persson2ee3e4d2022-05-20 12:22:2796 const std::vector<TestParams>& params,
97 bool svc = false) {
Åsa Persson64f7da02021-03-01 08:38:5798 VideoCodec video_codec;
99 VideoEncoderConfig encoder_config;
Asa Persson2ee3e4d2022-05-20 12:22:27100 FillCodecConfig(&video_codec, &encoder_config, width_px, height_px, params,
101 svc);
Sergey Silkin8c007ff2021-01-22 17:59:59102
Åsa Persson64f7da02021-03-01 08:38:57103 EncoderSettings encoder_settings(MakeEncoderInfo(),
104 std::move(encoder_config), video_codec);
105 bitrate_constraint_.OnEncoderSettingsUpdated(encoder_settings);
106 input_state_provider_.OnEncoderSettingsChanged(encoder_settings);
107 }
Sergey Silkin8c007ff2021-01-22 17:59:59108
Åsa Persson64f7da02021-03-01 08:38:57109 FakeFrameRateProvider frame_rate_provider_;
110 VideoStreamInputStateProvider input_state_provider_;
111 BitrateConstraint bitrate_constraint_;
112};
Sergey Silkin8c007ff2021-01-22 17:59:59113
Åsa Persson64f7da02021-03-01 08:38:57114TEST_F(BitrateConstraintTest, AdaptUpAllowedAtSinglecastIfBitrateIsEnough) {
115 OnEncoderSettingsUpdated(/*width_px=*/640, /*height_px=*/360,
Asa Persson2ee3e4d2022-05-20 12:22:27116 {{.active = true}});
Åsa Persson64f7da02021-03-01 08:38:57117
118 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p);
119
120 EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed(
121 input_state_provider_.InputState(),
122 /*restrictions_before=*/k360p,
123 /*restrictions_after=*/k720p));
Sergey Silkin8c007ff2021-01-22 17:59:59124}
125
Åsa Persson64f7da02021-03-01 08:38:57126TEST_F(BitrateConstraintTest,
127 AdaptUpDisallowedAtSinglecastIfBitrateIsNotEnough) {
128 OnEncoderSettingsUpdated(/*width_px=*/640, /*height_px=*/360,
Asa Persson2ee3e4d2022-05-20 12:22:27129 {{.active = true}});
Sergey Silkin8c007ff2021-01-22 17:59:59130
Sergey Silkin8c007ff2021-01-22 17:59:59131 // 1 bps less than needed for 720p.
Åsa Persson64f7da02021-03-01 08:38:57132 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p - 1);
Sergey Silkin8c007ff2021-01-22 17:59:59133
Åsa Persson64f7da02021-03-01 08:38:57134 EXPECT_FALSE(bitrate_constraint_.IsAdaptationUpAllowed(
135 input_state_provider_.InputState(),
136 /*restrictions_before=*/k360p,
137 /*restrictions_after=*/k720p));
Sergey Silkin8c007ff2021-01-22 17:59:59138}
139
Åsa Persson64f7da02021-03-01 08:38:57140TEST_F(BitrateConstraintTest,
Asa Persson2ee3e4d2022-05-20 12:22:27141 AdaptUpAllowedAtSinglecastIfBitrateIsEnoughForOneSpatialLayer) {
142 OnEncoderSettingsUpdated(
143 /*width_px=*/640, /*height_px=*/360,
144 {{.active = true, .scalability_mode = ScalabilityMode::kL1T1}});
145
146 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p);
147
148 EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed(
149 input_state_provider_.InputState(),
150 /*restrictions_before=*/k360p,
151 /*restrictions_after=*/k720p));
152}
153
154TEST_F(BitrateConstraintTest,
155 AdaptUpDisallowedAtSinglecastIfBitrateIsNotEnoughForOneSpatialLayer) {
156 OnEncoderSettingsUpdated(
157 /*width_px=*/640, /*height_px=*/360,
158 {{.active = true, .scalability_mode = ScalabilityMode::kL1T1}});
159
160 // 1 bps less than needed for 720p.
161 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p - 1);
162
163 EXPECT_FALSE(bitrate_constraint_.IsAdaptationUpAllowed(
164 input_state_provider_.InputState(),
165 /*restrictions_before=*/k360p,
166 /*restrictions_after=*/k720p));
167}
168
169TEST_F(BitrateConstraintTest,
170 AdaptUpAllowedAtSinglecastIfBitrateIsNotEnoughForMultipleSpatialLayers) {
171 OnEncoderSettingsUpdated(
172 /*width_px=*/640, /*height_px=*/360,
173 {{.active = true, .scalability_mode = ScalabilityMode::kL2T1}});
174
175 // 1 bps less than needed for 720p.
176 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p - 1);
177
178 EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed(
179 input_state_provider_.InputState(),
180 /*restrictions_before=*/k360p,
181 /*restrictions_after=*/k720p));
182}
183
184TEST_F(BitrateConstraintTest,
Åsa Persson64f7da02021-03-01 08:38:57185 AdaptUpAllowedAtSinglecastUpperLayerActiveIfBitrateIsEnough) {
Asa Persson2ee3e4d2022-05-20 12:22:27186 OnEncoderSettingsUpdated(
187 /*width_px=*/640, /*height_px=*/360,
188 {{.active = false, .scalability_mode = ScalabilityMode::kL2T1},
189 {.active = true}});
Sergey Silkin8c007ff2021-01-22 17:59:59190
Åsa Persson64f7da02021-03-01 08:38:57191 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p);
Sergey Silkin8c007ff2021-01-22 17:59:59192
Åsa Persson64f7da02021-03-01 08:38:57193 EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed(
194 input_state_provider_.InputState(),
195 /*restrictions_before=*/k360p,
196 /*restrictions_after=*/k720p));
Sergey Silkin8c007ff2021-01-22 17:59:59197}
198
Åsa Persson64f7da02021-03-01 08:38:57199TEST_F(BitrateConstraintTest,
200 AdaptUpDisallowedAtSinglecastUpperLayerActiveIfBitrateIsNotEnough) {
Asa Persson2ee3e4d2022-05-20 12:22:27201 OnEncoderSettingsUpdated(
202 /*width_px=*/640, /*height_px=*/360,
203 {{.active = false, .scalability_mode = ScalabilityMode::kL2T1},
204 {.active = true}});
Sergey Silkin8c007ff2021-01-22 17:59:59205
Sergey Silkin8c007ff2021-01-22 17:59:59206 // 1 bps less than needed for 720p.
Åsa Persson64f7da02021-03-01 08:38:57207 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p - 1);
Sergey Silkin8c007ff2021-01-22 17:59:59208
Åsa Persson64f7da02021-03-01 08:38:57209 EXPECT_FALSE(bitrate_constraint_.IsAdaptationUpAllowed(
210 input_state_provider_.InputState(),
211 /*restrictions_before=*/k360p,
212 /*restrictions_after=*/k720p));
Sergey Silkin8c007ff2021-01-22 17:59:59213}
214
Asa Persson2ee3e4d2022-05-20 12:22:27215TEST_F(BitrateConstraintTest, AdaptUpAllowedLowestActiveIfBitrateIsNotEnough) {
Åsa Persson64f7da02021-03-01 08:38:57216 OnEncoderSettingsUpdated(/*width_px=*/640, /*height_px=*/360,
Asa Persson2ee3e4d2022-05-20 12:22:27217 {{.active = true}, {.active = false}});
Sergey Silkin8c007ff2021-01-22 17:59:59218
Asa Persson2ee3e4d2022-05-20 12:22:27219 // 1 bps less than needed for 360p.
220 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps360p - 1);
Sergey Silkin8c007ff2021-01-22 17:59:59221
Åsa Persson64f7da02021-03-01 08:38:57222 EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed(
223 input_state_provider_.InputState(),
Asa Persson2ee3e4d2022-05-20 12:22:27224 /*restrictions_before=*/k180p,
225 /*restrictions_after=*/k360p));
226}
227
228TEST_F(BitrateConstraintTest,
229 AdaptUpAllowedLowestActiveIfBitrateIsNotEnoughForOneSpatialLayer) {
230 OnEncoderSettingsUpdated(
231 /*width_px=*/640, /*height_px=*/360,
232 {{.active = true, .scalability_mode = ScalabilityMode::kL1T2},
233 {.active = false}});
234
235 // 1 bps less than needed for 360p.
236 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps360p - 1);
237
238 EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed(
239 input_state_provider_.InputState(),
240 /*restrictions_before=*/k180p,
241 /*restrictions_after=*/k360p));
242}
243
244TEST_F(BitrateConstraintTest,
245 AdaptUpAllowedLowestActiveIfBitrateIsEnoughForOneSpatialLayerSvc) {
246 OnEncoderSettingsUpdated(
247 /*width_px=*/640, /*height_px=*/360,
248 {{.active = true, .scalability_mode = ScalabilityMode::kL1T1},
249 {.active = false}},
250 /*svc=*/true);
251
252 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps360p);
253
254 EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed(
255 input_state_provider_.InputState(),
256 /*restrictions_before=*/k180p,
257 /*restrictions_after=*/k360p));
258}
259
260TEST_F(BitrateConstraintTest,
261 AdaptUpDisallowedLowestActiveIfBitrateIsNotEnoughForOneSpatialLayerSvc) {
262 OnEncoderSettingsUpdated(
263 /*width_px=*/640, /*height_px=*/360,
264 {{.active = true, .scalability_mode = ScalabilityMode::kL1T1},
265 {.active = false}},
266 /*svc=*/true);
267
268 // 1 bps less than needed for 360p.
269 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps360p - 1);
270
271 EXPECT_FALSE(bitrate_constraint_.IsAdaptationUpAllowed(
272 input_state_provider_.InputState(),
273 /*restrictions_before=*/k180p,
274 /*restrictions_after=*/k360p));
275}
276
277TEST_F(BitrateConstraintTest,
278 AdaptUpAllowedLowestActiveIfBitrateIsNotEnoughForTwoSpatialLayersSvc) {
279 OnEncoderSettingsUpdated(
280 /*width_px=*/640, /*height_px=*/360,
281 {{.active = true, .scalability_mode = ScalabilityMode::kL2T1},
282 {.active = false}},
283 /*svc=*/true);
284
285 // 1 bps less than needed for 360p.
286 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps360p - 1);
287
288 EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed(
289 input_state_provider_.InputState(),
290 /*restrictions_before=*/k180p,
291 /*restrictions_after=*/k360p));
Sergey Silkin8c007ff2021-01-22 17:59:59292}
293
Åsa Persson64f7da02021-03-01 08:38:57294TEST_F(BitrateConstraintTest, AdaptUpAllowedAtSimulcastIfBitrateIsNotEnough) {
295 OnEncoderSettingsUpdated(/*width_px=*/640, /*height_px=*/360,
Asa Persson2ee3e4d2022-05-20 12:22:27296 {{.active = true}, {.active = true}});
Sergey Silkin8c007ff2021-01-22 17:59:59297
Sergey Silkin8c007ff2021-01-22 17:59:59298 // 1 bps less than needed for 720p.
Åsa Persson64f7da02021-03-01 08:38:57299 bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p - 1);
Sergey Silkin8c007ff2021-01-22 17:59:59300
Åsa Persson64f7da02021-03-01 08:38:57301 EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed(
302 input_state_provider_.InputState(),
303 /*restrictions_before=*/k360p,
304 /*restrictions_after=*/k720p));
305}
Sergey Silkin8c007ff2021-01-22 17:59:59306
Åsa Persson64f7da02021-03-01 08:38:57307TEST_F(BitrateConstraintTest,
308 AdaptUpInFpsAllowedAtNoResolutionIncreaseIfBitrateIsNotEnough) {
309 OnEncoderSettingsUpdated(/*width_px=*/640, /*height_px=*/360,
Asa Persson2ee3e4d2022-05-20 12:22:27310 {{.active = true}});
Åsa Persson64f7da02021-03-01 08:38:57311
312 bitrate_constraint_.OnEncoderTargetBitrateUpdated(1);
313
314 EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed(
315 input_state_provider_.InputState(),
316 /*restrictions_before=*/k360p,
317 /*restrictions_after=*/k360p));
Sergey Silkin8c007ff2021-01-22 17:59:59318}
319
320} // namespace webrtc