diff options
Diffstat (limited to 'third_party/libwebrtc/video/adaptation/bitrate_constraint_unittest.cc')
-rw-r--r-- | third_party/libwebrtc/video/adaptation/bitrate_constraint_unittest.cc | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/third_party/libwebrtc/video/adaptation/bitrate_constraint_unittest.cc b/third_party/libwebrtc/video/adaptation/bitrate_constraint_unittest.cc new file mode 100644 index 0000000000..f9cb87e3c1 --- /dev/null +++ b/third_party/libwebrtc/video/adaptation/bitrate_constraint_unittest.cc @@ -0,0 +1,320 @@ +/* + * Copyright 2021 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "video/adaptation/bitrate_constraint.h" + +#include <utility> +#include <vector> + +#include "api/video_codecs/scalability_mode.h" +#include "api/video_codecs/video_encoder.h" +#include "call/adaptation/encoder_settings.h" +#include "call/adaptation/test/fake_frame_rate_provider.h" +#include "call/adaptation/video_source_restrictions.h" +#include "call/adaptation/video_stream_input_state_provider.h" +#include "test/gtest.h" + +namespace webrtc { + +namespace { +const VideoSourceRestrictions k180p{/*max_pixels_per_frame=*/320 * 180, + /*target_pixels_per_frame=*/320 * 180, + /*max_frame_rate=*/30}; +const VideoSourceRestrictions k360p{/*max_pixels_per_frame=*/640 * 360, + /*target_pixels_per_frame=*/640 * 360, + /*max_frame_rate=*/30}; +const VideoSourceRestrictions k720p{/*max_pixels_per_frame=*/1280 * 720, + /*target_pixels_per_frame=*/1280 * 720, + /*max_frame_rate=*/30}; + +struct TestParams { + bool active; + absl::optional<ScalabilityMode> scalability_mode; +}; + +void FillCodecConfig(VideoCodec* video_codec, + VideoEncoderConfig* encoder_config, + int width_px, + int height_px, + const std::vector<TestParams>& params, + bool svc) { + size_t num_layers = params.size(); + video_codec->codecType = kVideoCodecVP8; + video_codec->numberOfSimulcastStreams = num_layers; + + encoder_config->number_of_streams = svc ? 1 : num_layers; + encoder_config->simulcast_layers.resize(num_layers); + + for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) { + int layer_width_px = width_px >> (num_layers - 1 - layer_idx); + int layer_height_px = height_px >> (num_layers - 1 - layer_idx); + + if (params[layer_idx].scalability_mode) + video_codec->SetScalabilityMode(*params[layer_idx].scalability_mode); + video_codec->simulcastStream[layer_idx].active = params[layer_idx].active; + video_codec->simulcastStream[layer_idx].width = layer_width_px; + video_codec->simulcastStream[layer_idx].height = layer_height_px; + + encoder_config->simulcast_layers[layer_idx].scalability_mode = + params[layer_idx].scalability_mode; + encoder_config->simulcast_layers[layer_idx].active = + params[layer_idx].active; + encoder_config->simulcast_layers[layer_idx].width = layer_width_px; + encoder_config->simulcast_layers[layer_idx].height = layer_height_px; + } +} + +constexpr int kStartBitrateBps360p = 500000; +constexpr int kStartBitrateBps720p = 1000000; + +VideoEncoder::EncoderInfo MakeEncoderInfo() { + VideoEncoder::EncoderInfo encoder_info; + encoder_info.resolution_bitrate_limits = { + {640 * 360, kStartBitrateBps360p, 0, 5000000}, + {1280 * 720, kStartBitrateBps720p, 0, 5000000}, + {1920 * 1080, 2000000, 0, 5000000}}; + return encoder_info; +} + +} // namespace + +class BitrateConstraintTest : public ::testing::Test { + public: + BitrateConstraintTest() + : frame_rate_provider_(), input_state_provider_(&frame_rate_provider_) {} + + protected: + void OnEncoderSettingsUpdated(int width_px, + int height_px, + const std::vector<TestParams>& params, + bool svc = false) { + VideoCodec video_codec; + VideoEncoderConfig encoder_config; + FillCodecConfig(&video_codec, &encoder_config, width_px, height_px, params, + svc); + + EncoderSettings encoder_settings(MakeEncoderInfo(), + std::move(encoder_config), video_codec); + bitrate_constraint_.OnEncoderSettingsUpdated(encoder_settings); + input_state_provider_.OnEncoderSettingsChanged(encoder_settings); + } + + FakeFrameRateProvider frame_rate_provider_; + VideoStreamInputStateProvider input_state_provider_; + BitrateConstraint bitrate_constraint_; +}; + +TEST_F(BitrateConstraintTest, AdaptUpAllowedAtSinglecastIfBitrateIsEnough) { + OnEncoderSettingsUpdated(/*width_px=*/640, /*height_px=*/360, + {{.active = true}}); + + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p); + + EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k360p, + /*restrictions_after=*/k720p)); +} + +TEST_F(BitrateConstraintTest, + AdaptUpDisallowedAtSinglecastIfBitrateIsNotEnough) { + OnEncoderSettingsUpdated(/*width_px=*/640, /*height_px=*/360, + {{.active = true}}); + + // 1 bps less than needed for 720p. + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p - 1); + + EXPECT_FALSE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k360p, + /*restrictions_after=*/k720p)); +} + +TEST_F(BitrateConstraintTest, + AdaptUpAllowedAtSinglecastIfBitrateIsEnoughForOneSpatialLayer) { + OnEncoderSettingsUpdated( + /*width_px=*/640, /*height_px=*/360, + {{.active = true, .scalability_mode = ScalabilityMode::kL1T1}}); + + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p); + + EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k360p, + /*restrictions_after=*/k720p)); +} + +TEST_F(BitrateConstraintTest, + AdaptUpDisallowedAtSinglecastIfBitrateIsNotEnoughForOneSpatialLayer) { + OnEncoderSettingsUpdated( + /*width_px=*/640, /*height_px=*/360, + {{.active = true, .scalability_mode = ScalabilityMode::kL1T1}}); + + // 1 bps less than needed for 720p. + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p - 1); + + EXPECT_FALSE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k360p, + /*restrictions_after=*/k720p)); +} + +TEST_F(BitrateConstraintTest, + AdaptUpAllowedAtSinglecastIfBitrateIsNotEnoughForMultipleSpatialLayers) { + OnEncoderSettingsUpdated( + /*width_px=*/640, /*height_px=*/360, + {{.active = true, .scalability_mode = ScalabilityMode::kL2T1}}); + + // 1 bps less than needed for 720p. + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p - 1); + + EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k360p, + /*restrictions_after=*/k720p)); +} + +TEST_F(BitrateConstraintTest, + AdaptUpAllowedAtSinglecastUpperLayerActiveIfBitrateIsEnough) { + OnEncoderSettingsUpdated( + /*width_px=*/640, /*height_px=*/360, + {{.active = false, .scalability_mode = ScalabilityMode::kL2T1}, + {.active = true}}); + + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p); + + EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k360p, + /*restrictions_after=*/k720p)); +} + +TEST_F(BitrateConstraintTest, + AdaptUpDisallowedAtSinglecastUpperLayerActiveIfBitrateIsNotEnough) { + OnEncoderSettingsUpdated( + /*width_px=*/640, /*height_px=*/360, + {{.active = false, .scalability_mode = ScalabilityMode::kL2T1}, + {.active = true}}); + + // 1 bps less than needed for 720p. + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p - 1); + + EXPECT_FALSE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k360p, + /*restrictions_after=*/k720p)); +} + +TEST_F(BitrateConstraintTest, AdaptUpAllowedLowestActiveIfBitrateIsNotEnough) { + OnEncoderSettingsUpdated(/*width_px=*/640, /*height_px=*/360, + {{.active = true}, {.active = false}}); + + // 1 bps less than needed for 360p. + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps360p - 1); + + EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k180p, + /*restrictions_after=*/k360p)); +} + +TEST_F(BitrateConstraintTest, + AdaptUpAllowedLowestActiveIfBitrateIsNotEnoughForOneSpatialLayer) { + OnEncoderSettingsUpdated( + /*width_px=*/640, /*height_px=*/360, + {{.active = true, .scalability_mode = ScalabilityMode::kL1T2}, + {.active = false}}); + + // 1 bps less than needed for 360p. + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps360p - 1); + + EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k180p, + /*restrictions_after=*/k360p)); +} + +TEST_F(BitrateConstraintTest, + AdaptUpAllowedLowestActiveIfBitrateIsEnoughForOneSpatialLayerSvc) { + OnEncoderSettingsUpdated( + /*width_px=*/640, /*height_px=*/360, + {{.active = true, .scalability_mode = ScalabilityMode::kL1T1}, + {.active = false}}, + /*svc=*/true); + + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps360p); + + EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k180p, + /*restrictions_after=*/k360p)); +} + +TEST_F(BitrateConstraintTest, + AdaptUpDisallowedLowestActiveIfBitrateIsNotEnoughForOneSpatialLayerSvc) { + OnEncoderSettingsUpdated( + /*width_px=*/640, /*height_px=*/360, + {{.active = true, .scalability_mode = ScalabilityMode::kL1T1}, + {.active = false}}, + /*svc=*/true); + + // 1 bps less than needed for 360p. + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps360p - 1); + + EXPECT_FALSE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k180p, + /*restrictions_after=*/k360p)); +} + +TEST_F(BitrateConstraintTest, + AdaptUpAllowedLowestActiveIfBitrateIsNotEnoughForTwoSpatialLayersSvc) { + OnEncoderSettingsUpdated( + /*width_px=*/640, /*height_px=*/360, + {{.active = true, .scalability_mode = ScalabilityMode::kL2T1}, + {.active = false}}, + /*svc=*/true); + + // 1 bps less than needed for 360p. + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps360p - 1); + + EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k180p, + /*restrictions_after=*/k360p)); +} + +TEST_F(BitrateConstraintTest, AdaptUpAllowedAtSimulcastIfBitrateIsNotEnough) { + OnEncoderSettingsUpdated(/*width_px=*/640, /*height_px=*/360, + {{.active = true}, {.active = true}}); + + // 1 bps less than needed for 720p. + bitrate_constraint_.OnEncoderTargetBitrateUpdated(kStartBitrateBps720p - 1); + + EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k360p, + /*restrictions_after=*/k720p)); +} + +TEST_F(BitrateConstraintTest, + AdaptUpInFpsAllowedAtNoResolutionIncreaseIfBitrateIsNotEnough) { + OnEncoderSettingsUpdated(/*width_px=*/640, /*height_px=*/360, + {{.active = true}}); + + bitrate_constraint_.OnEncoderTargetBitrateUpdated(1); + + EXPECT_TRUE(bitrate_constraint_.IsAdaptationUpAllowed( + input_state_provider_.InputState(), + /*restrictions_before=*/k360p, + /*restrictions_after=*/k360p)); +} + +} // namespace webrtc |