diff --git a/api/video_codecs/BUILD.gn b/api/video_codecs/BUILD.gn index 093b0bd3d2..b780a9c329 100644 --- a/api/video_codecs/BUILD.gn +++ b/api/video_codecs/BUILD.gn @@ -379,7 +379,10 @@ rtc_library("libaom_av1_encoder_factory") { "//third_party/libaom", ] - absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container" ] + absl_deps = [ + "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/cleanup", + ] } rtc_library("libaom_av1_encoder_factory_test") { diff --git a/api/video_codecs/libaom_av1_encoder_factory.cc b/api/video_codecs/libaom_av1_encoder_factory.cc index 4ee8c7faef..c2d933f890 100644 --- a/api/video_codecs/libaom_av1_encoder_factory.cc +++ b/api/video_codecs/libaom_av1_encoder_factory.cc @@ -18,6 +18,7 @@ #include #include "absl/algorithm/container.h" +#include "absl/cleanup/cleanup.h" #include "api/video_codecs/video_encoder_interface.h" #include "rtc_base/logging.h" #include "rtc_base/strings/string_builder.h" @@ -25,10 +26,9 @@ #include "third_party/libaom/source/libaom/aom/aom_encoder.h" #include "third_party/libaom/source/libaom/aom/aomcx.h" -#define SET_OR_DO_ERROR_CALLBACK_AND_RETURN(param_id, param_value) \ +#define SET_OR_RETURN(param_id, param_value) \ do { \ if (!SetEncoderControlParameters(&ctx_, param_id, param_value)) { \ - DoErrorCallback(frame_settings); \ return; \ } \ } while (0) @@ -616,36 +616,33 @@ aom_svc_params_t GetSvcParams( return svc_params; } -void DoErrorCallback(std::vector& frame_settings) { - for (FrameEncodeSettings& settings : frame_settings) { - if (settings.frame_output) { - settings.frame_output->EncodeComplete({}); - // To avoid invoking any callback more than once. - settings.frame_output = nullptr; - } - } -} - void LibaomAv1Encoder::Encode( rtc::scoped_refptr frame_buffer, const TemporalUnitSettings& tu_settings, std::vector frame_settings) { + absl::Cleanup on_return = [&] { + // On return call `EncodeComplete` with EncodingError result unless they + // were already called with an EncodedData result. + for (FrameEncodeSettings& settings : frame_settings) { + if (settings.frame_output) { + settings.frame_output->EncodeComplete(EncodingError()); + } + } + }; + if (!ValidateEncodeParams(*frame_buffer, tu_settings, frame_settings, last_resolution_in_buffer_, cfg_.rc_end_usage)) { - DoErrorCallback(frame_settings); return; } if (current_content_type_ != tu_settings.content_hint) { if (tu_settings.content_hint == VideoCodecMode::kScreensharing) { // TD: Set speed 11? - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AV1E_SET_TUNE_CONTENT, - AOM_CONTENT_SCREEN); - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AV1E_SET_ENABLE_PALETTE, 1); + SET_OR_RETURN(AV1E_SET_TUNE_CONTENT, AOM_CONTENT_SCREEN); + SET_OR_RETURN(AV1E_SET_ENABLE_PALETTE, 1); } else { - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AV1E_SET_TUNE_CONTENT, - AOM_CONTENT_DEFAULT); - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AV1E_SET_ENABLE_PALETTE, 0); + SET_OR_RETURN(AV1E_SET_TUNE_CONTENT, AOM_CONTENT_DEFAULT); + SET_OR_RETURN(AV1E_SET_ENABLE_PALETTE, 0); } current_content_type_ = tu_settings.content_hint; } @@ -668,12 +665,9 @@ void LibaomAv1Encoder::Encode( << frame_buffer->height(); ThreadTilesAndSuperblockSizeInfo ttsbi = GetThreadingTilesAndSuperblockSize( frame_buffer->width(), frame_buffer->height(), max_number_of_threads_); - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AV1E_SET_SUPERBLOCK_SIZE, - ttsbi.superblock_size); - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AV1E_SET_TILE_ROWS, - ttsbi.exp_tile_rows); - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AV1E_SET_TILE_COLUMNS, - ttsbi.exp_tile_colums); + SET_OR_RETURN(AV1E_SET_SUPERBLOCK_SIZE, ttsbi.superblock_size); + SET_OR_RETURN(AV1E_SET_TILE_ROWS, ttsbi.exp_tile_rows); + SET_OR_RETURN(AV1E_SET_TILE_COLUMNS, ttsbi.exp_tile_colums); cfg_.g_threads = ttsbi.num_threads; cfg_.g_w = frame_buffer->width(); cfg_.g_h = frame_buffer->height(); @@ -687,11 +681,10 @@ void LibaomAv1Encoder::Encode( if (aom_codec_err_t ret = aom_codec_enc_config_set(&ctx_, &cfg_); ret != AOM_CODEC_OK) { RTC_LOG(LS_ERROR) << "aom_codec_enc_config_set returned " << ret; - DoErrorCallback(frame_settings); return; } aom_svc_params_t svc_params = GetSvcParams(*frame_buffer, frame_settings); - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AV1E_SET_SVC_PARAMS, &svc_params); + SET_OR_RETURN(AV1E_SET_SVC_PARAMS, &svc_params); // The libaom AV1 encoder requires that `aom_codec_encode` is called for // every spatial layer, even if no frame should be encoded for that layer. @@ -714,10 +707,9 @@ void LibaomAv1Encoder::Encode( .spatial_layer_id = sid, .temporal_layer_id = settings.temporal_id, }; - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AV1E_SET_SVC_LAYER_ID, &layer_id); + SET_OR_RETURN(AV1E_SET_SVC_LAYER_ID, &layer_id); aom_svc_ref_frame_config_t ref_config = GetSvcRefFrameConfig(settings); - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AV1E_SET_SVC_REF_FRAME_CONFIG, - &ref_config); + SET_OR_RETURN(AV1E_SET_SVC_REF_FRAME_CONFIG, &ref_config); // TD: Duration can't be zero, what does it matter when the layer is // not being encoded? @@ -733,8 +725,7 @@ void LibaomAv1Encoder::Encode( if (settings.effort_level != current_effort_level_[settings.spatial_id]) { // For RTC we use speed level 6 to 10, with 8 being the default. Note // that low effort means higher speed. - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AOME_SET_CPUUSED, - 8 - settings.effort_level); + SET_OR_RETURN(AOME_SET_CPUUSED, 8 - settings.effort_level); current_effort_level_[settings.spatial_id] = settings.effort_level; } } @@ -751,7 +742,6 @@ void LibaomAv1Encoder::Encode( settings.frame_type == FrameType::kKeyframe ? AOM_EFLAG_FORCE_KF : 0); if (ret != AOM_CODEC_OK) { RTC_LOG(LS_WARNING) << "aom_codec_encode returned " << ret; - DoErrorCallback(frame_settings); return; } @@ -773,8 +763,7 @@ void LibaomAv1Encoder::Encode( while (const aom_codec_cx_pkt_t* pkt = aom_codec_get_cx_data(&ctx_, &iter)) { if (pkt->kind == AOM_CODEC_CX_FRAME_PKT && pkt->data.frame.sz > 0) { - SET_OR_DO_ERROR_CALLBACK_AND_RETURN(AOME_GET_LAST_QUANTIZER_64, - &result.encoded_qp); + SET_OR_RETURN(AOME_GET_LAST_QUANTIZER_64, &result.encoded_qp); result.frame_type = pkt->data.frame.flags & AOM_EFLAG_FORCE_KF ? FrameType::kKeyframe : FrameType::kDeltaFrame; @@ -782,7 +771,6 @@ void LibaomAv1Encoder::Encode( settings.frame_output->GetBitstreamOutputBuffer( DataSize::Bytes(pkt->data.frame.sz)); if (output_buffer.size() != pkt->data.frame.sz) { - DoErrorCallback(frame_settings); return; } memcpy(output_buffer.data(), pkt->data.frame.buf, pkt->data.frame.sz); @@ -792,7 +780,6 @@ void LibaomAv1Encoder::Encode( } if (!bitstream_produced) { - DoErrorCallback(frame_settings); return; } else { RTC_CHECK(settings.frame_output);