Keep SVC max bitrate if number of spatial layers are reduced.
Bug: chromium:1423361
Change-Id: I02bcb11f2ac456db79ed835dd38d4d7621a49608
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/298446
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#39614}
diff --git a/modules/video_coding/codecs/vp9/svc_config.cc b/modules/video_coding/codecs/vp9/svc_config.cc
index 3a32a43..43def0f 100644
--- a/modules/video_coding/codecs/vp9/svc_config.cc
+++ b/modules/video_coding/codecs/vp9/svc_config.cc
@@ -203,12 +203,7 @@
codec.GetScalabilityMode() ? info : absl::nullopt);
RTC_DCHECK(!spatial_layers.empty());
- // Use codec bitrate limits if spatial layering is not requested.
- if (info->num_spatial_layers == 1) {
- spatial_layers.back().minBitrate = codec.minBitrate;
- spatial_layers.back().targetBitrate = codec.maxBitrate;
- spatial_layers.back().maxBitrate = codec.maxBitrate;
- }
+ spatial_layers[0].minBitrate = kMinVp9SvcBitrateKbps;
return spatial_layers;
}
diff --git a/modules/video_coding/video_codec_initializer.cc b/modules/video_coding/video_codec_initializer.cc
index b0b16d0..c468e99 100644
--- a/modules/video_coding/video_codec_initializer.cc
+++ b/modules/video_coding/video_codec_initializer.cc
@@ -237,6 +237,13 @@
spatial_layers = GetVp9SvcConfig(video_codec);
if (spatial_layers.empty())
break;
+ // Use codec bitrate limits if spatial layering is not requested.
+ if (config.simulcast_layers.size() <= 1 &&
+ ScalabilityModeToNumSpatialLayers(*scalability_mode) == 1) {
+ spatial_layers.back().minBitrate = video_codec.minBitrate;
+ spatial_layers.back().targetBitrate = video_codec.maxBitrate;
+ spatial_layers.back().maxBitrate = video_codec.maxBitrate;
+ }
} else {
size_t first_active_layer = 0;
for (size_t spatial_idx = 0;
diff --git a/modules/video_coding/video_codec_initializer_unittest.cc b/modules/video_coding/video_codec_initializer_unittest.cc
index e628680..b9d8465 100644
--- a/modules/video_coding/video_codec_initializer_unittest.cc
+++ b/modules/video_coding/video_codec_initializer_unittest.cc
@@ -332,6 +332,22 @@
}
TEST_F(VideoCodecInitializerTest,
+ Vp9SingleSpatialLayerMaxBitrateIsEqualToCodecMaxBitrateWithL1T1) {
+ SetUpFor(VideoCodecType::kVideoCodecVP9, 1, 1, 1, false);
+ VideoStream stream = DefaultStream();
+ stream.num_temporal_layers = 1;
+ stream.scalability_mode = ScalabilityMode::kL1T1;
+ streams_.push_back(stream);
+
+ EXPECT_TRUE(InitializeCodec());
+ EXPECT_EQ(1u, codec_out_.VP9()->numberOfSpatialLayers);
+ EXPECT_EQ(codec_out_.spatialLayers[0].minBitrate,
+ kDefaultMinBitrateBps / 1000);
+ EXPECT_EQ(codec_out_.spatialLayers[0].maxBitrate,
+ kDefaultMaxBitrateBps / 1000);
+}
+
+TEST_F(VideoCodecInitializerTest,
Vp9SingleSpatialLayerTargetBitrateIsEqualToCodecMaxBitrate) {
SetUpFor(VideoCodecType::kVideoCodecVP9, absl::nullopt, 1, 1, true);
VideoStream stream = DefaultStream();
@@ -360,6 +376,27 @@
kDefaultMaxBitrateBps / 1000);
}
+TEST_F(VideoCodecInitializerTest,
+ Vp9KeepBitrateLimitsIfNumberOfSpatialLayersIsReducedToOneWithL3T1) {
+ // Request 3 spatial layers for 320x180 input. Actual number of layers will be
+ // reduced to 1 due to low input resolution but SVC bitrate limits should be
+ // applied.
+ SetUpFor(VideoCodecType::kVideoCodecVP9, 1, 3, 1, false);
+ VideoStream stream = DefaultStream();
+ stream.width = 320;
+ stream.height = 180;
+ stream.num_temporal_layers = 1;
+ stream.scalability_mode = ScalabilityMode::kL3T1;
+ streams_.push_back(stream);
+
+ EXPECT_TRUE(InitializeCodec());
+ EXPECT_EQ(1u, codec_out_.VP9()->numberOfSpatialLayers);
+ EXPECT_LT(codec_out_.spatialLayers[0].minBitrate,
+ kDefaultMinBitrateBps / 1000);
+ EXPECT_LT(codec_out_.spatialLayers[0].maxBitrate,
+ kDefaultMaxBitrateBps / 1000);
+}
+
TEST_F(VideoCodecInitializerTest, Vp9DeactivateLayers) {
SetUpFor(VideoCodecType::kVideoCodecVP9, absl::nullopt, 3, 1, false);
VideoStream stream = DefaultStream();
@@ -537,4 +574,55 @@
EXPECT_FALSE(codec.spatialLayers[1].active);
}
+TEST_F(VideoCodecInitializerTest, Vp9SingleSpatialLayerBitratesAreConsistent) {
+ VideoEncoderConfig config;
+ config.simulcast_layers.resize(3);
+ config.simulcast_layers[0].active = true;
+ config.simulcast_layers[1].active = false;
+ config.simulcast_layers[2].active = false;
+
+ config.codec_type = VideoCodecType::kVideoCodecVP9;
+ std::vector<VideoStream> streams = {DefaultStream()};
+ streams[0].scalability_mode = ScalabilityMode::kL1T2;
+
+ VideoCodec codec;
+ EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
+
+ EXPECT_EQ(1u, codec.VP9()->numberOfSpatialLayers);
+ EXPECT_GE(codec.spatialLayers[0].targetBitrate,
+ codec.spatialLayers[0].minBitrate);
+ EXPECT_LE(codec.spatialLayers[0].targetBitrate,
+ codec.spatialLayers[0].maxBitrate);
+ EXPECT_LT(codec.spatialLayers[0].minBitrate, kDefaultMinBitrateBps / 1000);
+}
+
+TEST_F(VideoCodecInitializerTest, Vp9TwoSpatialLayersBitratesAreConsistent) {
+ VideoEncoderConfig config;
+ config.simulcast_layers.resize(3);
+ config.simulcast_layers[0].active = true;
+ config.simulcast_layers[1].active = false;
+ config.simulcast_layers[2].active = false;
+
+ config.codec_type = VideoCodecType::kVideoCodecVP9;
+ std::vector<VideoStream> streams = {DefaultStream()};
+ streams[0].scalability_mode = ScalabilityMode::kL2T2;
+
+ VideoCodec codec;
+ EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
+
+ EXPECT_EQ(2u, codec.VP9()->numberOfSpatialLayers);
+ EXPECT_GE(codec.spatialLayers[0].targetBitrate,
+ codec.spatialLayers[0].minBitrate);
+ EXPECT_LE(codec.spatialLayers[0].targetBitrate,
+ codec.spatialLayers[0].maxBitrate);
+ EXPECT_LT(codec.spatialLayers[0].minBitrate, kDefaultMinBitrateBps / 1000);
+
+ EXPECT_GE(codec.spatialLayers[1].targetBitrate,
+ codec.spatialLayers[1].minBitrate);
+ EXPECT_LE(codec.spatialLayers[1].targetBitrate,
+ codec.spatialLayers[1].maxBitrate);
+ EXPECT_GT(codec.spatialLayers[1].minBitrate,
+ codec.spatialLayers[0].maxBitrate);
+}
+
} // namespace webrtc
diff --git a/video/end_to_end_tests/resolution_bitrate_limits_tests.cc b/video/end_to_end_tests/resolution_bitrate_limits_tests.cc
index d550339..86167ac 100644
--- a/video/end_to_end_tests/resolution_bitrate_limits_tests.cc
+++ b/video/end_to_end_tests/resolution_bitrate_limits_tests.cc
@@ -229,6 +229,33 @@
}
TEST_F(ResolutionBitrateLimitsWithScalabilityModeTest,
+ OneStreamDefaultMaxBitrateAppliedForOneSpatialLayer) {
+ InitEncodeTest test("VP9",
+ {{.active = true,
+ .bitrate = {DataRate::KilobitsPerSec(30),
+ DataRate::KilobitsPerSec(3000)},
+ .scalability_mode = ScalabilityMode::kL1T1}},
+ // Expectations:
+ {{.pixels = 1280 * 720,
+ .eq_bitrate = {DataRate::KilobitsPerSec(30),
+ DataRate::KilobitsPerSec(3000)}}});
+ RunBaseTest(&test);
+}
+
+TEST_F(ResolutionBitrateLimitsWithScalabilityModeTest,
+ OneStreamSvcMaxBitrateAppliedForTwoSpatialLayers) {
+ InitEncodeTest test(
+ "VP9",
+ {{.active = true,
+ .bitrate = {DataRate::KilobitsPerSec(30),
+ DataRate::KilobitsPerSec(3000)},
+ .scalability_mode = ScalabilityMode::kL2T1}},
+ // Expectations:
+ {{.pixels = 1280 * 720,
+ .ne_bitrate = {absl::nullopt, DataRate::KilobitsPerSec(3000)}}});
+ RunBaseTest(&test);
+}
+TEST_F(ResolutionBitrateLimitsWithScalabilityModeTest,
OneStreamLimitsAppliedForOneSpatialLayer) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-GetEncoderInfoOverride/"