Make AV1 respect spatial layer active flag.
Bug: webrtc:12788
Change-Id: Ied629e1635b6ff9bf92fab2d1af708163f9dd28c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/220928
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34189}
diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
index 8c82476..84f3453 100644
--- a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
+++ b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc
@@ -671,8 +671,15 @@
encoded_image.content_type_ = VideoContentType::UNSPECIFIED;
// If encoded image width/height info are added to aom_codec_cx_pkt_t,
// use those values in lieu of the values in frame.
- encoded_image._encodedHeight = frame.height();
- encoded_image._encodedWidth = frame.width();
+ if (svc_params_) {
+ int n = svc_params_->scaling_factor_num[layer_frame.SpatialId()];
+ int d = svc_params_->scaling_factor_den[layer_frame.SpatialId()];
+ encoded_image._encodedWidth = cfg_.g_w * n / d;
+ encoded_image._encodedHeight = cfg_.g_h * n / d;
+ } else {
+ encoded_image._encodedWidth = cfg_.g_w;
+ encoded_image._encodedHeight = cfg_.g_h;
+ }
encoded_image.timing_.flags = VideoSendTiming::kInvalid;
int qp = -1;
ret = aom_codec_control(&ctx_, AOME_GET_LAST_QUANTIZER, &qp);
diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc
index ea77e09..96057a0 100644
--- a/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc
+++ b/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc
@@ -25,6 +25,7 @@
namespace {
using ::testing::ElementsAre;
+using ::testing::Field;
using ::testing::IsEmpty;
using ::testing::SizeIs;
@@ -135,5 +136,36 @@
EXPECT_THAT(encoder_info.fps_allocation[3], IsEmpty());
}
+TEST(LibaomAv1EncoderTest, PopulatesEncodedFrameSize) {
+ std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
+ VideoCodec codec_settings = DefaultCodecSettings();
+ ASSERT_GT(codec_settings.width, 4);
+ // Configure encoder with 3 spatial layers.
+ codec_settings.SetScalabilityMode("L3T1");
+ ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
+ WEBRTC_VIDEO_CODEC_OK);
+
+ using Frame = EncodedVideoFrameProducer::EncodedFrame;
+ std::vector<Frame> encoded_frames =
+ EncodedVideoFrameProducer(*encoder).SetNumInputFrames(1).Encode();
+ EXPECT_THAT(
+ encoded_frames,
+ ElementsAre(
+ Field(&Frame::encoded_image,
+ AllOf(Field(&EncodedImage::_encodedWidth,
+ codec_settings.width / 4),
+ Field(&EncodedImage::_encodedHeight,
+ codec_settings.height / 4))),
+ Field(&Frame::encoded_image,
+ AllOf(Field(&EncodedImage::_encodedWidth,
+ codec_settings.width / 2),
+ Field(&EncodedImage::_encodedHeight,
+ codec_settings.height / 2))),
+ Field(&Frame::encoded_image,
+ AllOf(Field(&EncodedImage::_encodedWidth, codec_settings.width),
+ Field(&EncodedImage::_encodedHeight,
+ codec_settings.height)))));
+}
+
} // namespace
} // namespace webrtc
diff --git a/modules/video_coding/video_codec_initializer.cc b/modules/video_coding/video_codec_initializer.cc
index 90a02e0..17ea66a 100644
--- a/modules/video_coding/video_codec_initializer.cc
+++ b/modules/video_coding/video_codec_initializer.cc
@@ -262,7 +262,11 @@
break;
}
case kVideoCodecAV1:
- if (!SetAv1SvcConfig(video_codec)) {
+ if (SetAv1SvcConfig(video_codec)) {
+ for (size_t i = 0; i < config.spatial_layers.size(); ++i) {
+ video_codec.spatialLayers[i].active = config.spatial_layers[i].active;
+ }
+ } else {
RTC_LOG(LS_WARNING) << "Failed to configure svc bitrates for av1.";
}
break;
diff --git a/modules/video_coding/video_codec_initializer_unittest.cc b/modules/video_coding/video_codec_initializer_unittest.cc
index da3d80d..6c1c2e7 100644
--- a/modules/video_coding/video_codec_initializer_unittest.cc
+++ b/modules/video_coding/video_codec_initializer_unittest.cc
@@ -461,4 +461,34 @@
codec.spatialLayers[1].maxBitrate);
}
+TEST_F(VideoCodecInitializerTest, Av1TwoSpatialLayersActiveByDefault) {
+ VideoEncoderConfig config;
+ config.codec_type = VideoCodecType::kVideoCodecAV1;
+ std::vector<VideoStream> streams = {DefaultStream()};
+ streams[0].scalability_mode = "L2T2";
+ config.spatial_layers = {};
+
+ VideoCodec codec;
+ EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
+
+ EXPECT_TRUE(codec.spatialLayers[0].active);
+ EXPECT_TRUE(codec.spatialLayers[1].active);
+}
+
+TEST_F(VideoCodecInitializerTest, Av1TwoSpatialLayersOneDeactivated) {
+ VideoEncoderConfig config;
+ config.codec_type = VideoCodecType::kVideoCodecAV1;
+ std::vector<VideoStream> streams = {DefaultStream()};
+ streams[0].scalability_mode = "L2T2";
+ config.spatial_layers.resize(2);
+ config.spatial_layers[0].active = true;
+ config.spatial_layers[1].active = false;
+
+ VideoCodec codec;
+ EXPECT_TRUE(VideoCodecInitializer::SetupCodec(config, streams, &codec));
+
+ EXPECT_TRUE(codec.spatialLayers[0].active);
+ EXPECT_FALSE(codec.spatialLayers[1].active);
+}
+
} // namespace webrtc