From 253b8464ffe06426e5d603636039d75602eba6d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E6=81=A9?= Date: Fri, 18 Oct 2024 11:43:18 +0000 Subject: [PATCH] Fix AV1 encoder do't set end_of_picture when the top layer is dropped MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:357721007 Change-Id: I4e318618192aa9d58a2ef6338f7b1e2ee5140254 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/366100 Reviewed-by: Åsa Persson Commit-Queue: Sergey Silkin Reviewed-by: Sergey Silkin Cr-Commit-Position: refs/heads/main@{#43437} --- .../codecs/av1/libaom_av1_encoder.cc | 12 ++++++-- .../codecs/av1/libaom_av1_encoder_unittest.cc | 29 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc index a183704caa..a5a87eeed2 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_encoder.cc +++ b/modules/video_coding/codecs/av1/libaom_av1_encoder.cc @@ -645,6 +645,7 @@ int32_t LibaomAv1Encoder::Encode( const size_t num_spatial_layers = svc_params_ ? svc_params_->number_spatial_layers : 1; auto next_layer_frame = layer_frames.begin(); + std::vector> encoded_images; for (size_t i = 0; i < num_spatial_layers; ++i) { // The libaom AV1 encoder requires that `aom_codec_encode` is called for // every spatial layer, even if the configured bitrate for that layer is @@ -763,10 +764,17 @@ int32_t LibaomAv1Encoder::Encode( resolutions = {RenderResolution(cfg_.g_w, cfg_.g_h)}; } } - encoded_image_callback_->OnEncodedImage(encoded_image, - &codec_specific_info); + encoded_images.emplace_back(std::move(encoded_image), + std::move(codec_specific_info)); } } + if (!encoded_images.empty()) { + encoded_images.back().second.end_of_picture = true; + } + for (auto& [encoded_image, codec_specific_info] : encoded_images) { + encoded_image_callback_->OnEncodedImage(encoded_image, + &codec_specific_info); + } return WEBRTC_VIDEO_CODEC_OK; } 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 99ccea14fb..79275e1210 100644 --- a/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc +++ b/modules/video_coding/codecs/av1/libaom_av1_encoder_unittest.cc @@ -177,6 +177,35 @@ TEST(LibaomAv1EncoderTest, SetsEndOfPictureForLastFrameInTemporalUnit) { EXPECT_TRUE(encoded_frames[5].codec_specific_info.end_of_picture); } +TEST(LibaomAv1EncoderTest, + SetsEndOfPictureForLastFrameInTemporalUnitWhenLayerDrop) { + VideoBitrateAllocation allocation; + allocation.SetBitrate(0, 0, 30000); + allocation.SetBitrate(1, 0, 40000); + // Lower bitrate for the last spatial layer to provoke layer drop. + allocation.SetBitrate(2, 0, 500); + + std::unique_ptr encoder = + CreateLibaomAv1Encoder(CreateEnvironment()); + VideoCodec codec_settings = DefaultCodecSettings(); + // Configure encoder with 3 spatial layers. + codec_settings.SetScalabilityMode(ScalabilityMode::kL3T1); + codec_settings.startBitrate = allocation.get_sum_kbps(); + ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()), + WEBRTC_VIDEO_CODEC_OK); + + encoder->SetRates(VideoEncoder::RateControlParameters( + allocation, codec_settings.maxFramerate)); + + std::vector encoded_frames = + EncodedVideoFrameProducer(*encoder).SetNumInputFrames(2).Encode(); + ASSERT_THAT(encoded_frames, SizeIs(4)); + EXPECT_FALSE(encoded_frames[0].codec_specific_info.end_of_picture); + EXPECT_TRUE(encoded_frames[1].codec_specific_info.end_of_picture); + EXPECT_FALSE(encoded_frames[2].codec_specific_info.end_of_picture); + EXPECT_TRUE(encoded_frames[3].codec_specific_info.end_of_picture); +} + TEST(LibaomAv1EncoderTest, CheckOddDimensionsWithSpatialLayers) { VideoBitrateAllocation allocation; allocation.SetBitrate(0, 0, 30000);