RC: Implement send_firstpass and tests Bug: b:450252793 Change-Id: Ie9135bb4974b886f5b55ee1bb4369e6d903ef016
diff --git a/av1/encoder/av1_ext_ratectrl.c b/av1/encoder/av1_ext_ratectrl.c index bf24fb9..65e1092 100644 --- a/av1/encoder/av1_ext_ratectrl.c +++ b/av1/encoder/av1_ext_ratectrl.c
@@ -50,6 +50,61 @@ return AOM_CODEC_OK; } +static void gen_rc_firstpass_stats(const FIRSTPASS_STATS *stats, + aom_rc_frame_stats_t *rc_frame_stats) { + rc_frame_stats->frame = stats->frame; + rc_frame_stats->weight = stats->weight; + rc_frame_stats->intra_error = stats->intra_error; + rc_frame_stats->coded_error = stats->coded_error; + rc_frame_stats->sr_coded_error = stats->sr_coded_error; + rc_frame_stats->frame_avg_wavelet_energy = stats->frame_avg_wavelet_energy; + rc_frame_stats->pcnt_inter = stats->pcnt_inter; + rc_frame_stats->pcnt_motion = stats->pcnt_motion; + rc_frame_stats->pcnt_second_ref = stats->pcnt_second_ref; + rc_frame_stats->pcnt_neutral = stats->pcnt_neutral; + rc_frame_stats->intra_skip_pct = stats->intra_skip_pct; + rc_frame_stats->inactive_zone_rows = stats->inactive_zone_rows; + rc_frame_stats->inactive_zone_cols = stats->inactive_zone_cols; + rc_frame_stats->MVr = stats->MVr; + rc_frame_stats->mvr_abs = stats->mvr_abs; + rc_frame_stats->MVc = stats->MVc; + rc_frame_stats->mvc_abs = stats->mvc_abs; + rc_frame_stats->MVrv = stats->MVrv; + rc_frame_stats->MVcv = stats->MVcv; + rc_frame_stats->mv_in_out_count = stats->mv_in_out_count; + rc_frame_stats->duration = stats->duration; + rc_frame_stats->count = stats->count; + rc_frame_stats->new_mv_count = stats->new_mv_count; + rc_frame_stats->raw_error_stdev = stats->raw_error_stdev; + rc_frame_stats->is_flash = stats->is_flash; + rc_frame_stats->noise_var = stats->noise_var; + rc_frame_stats->cor_coeff = stats->cor_coeff; + rc_frame_stats->log_intra_error = stats->log_intra_error; + rc_frame_stats->log_coded_error = stats->log_coded_error; +} + +aom_codec_err_t av1_extrc_send_firstpass_stats( + AOM_EXT_RATECTRL *ext_ratectrl, const FIRSTPASS_INFO *first_pass_info) { + assert(first_pass_info != NULL); + assert(ext_ratectrl != NULL); + if (ext_ratectrl->ready) { + aom_rc_status_t rc_status; + aom_rc_firstpass_stats_t *rc_firstpass_stats = + &ext_ratectrl->rc_firstpass_stats; + assert(rc_firstpass_stats->num_frames == first_pass_info->stats_buf_size); + for (int i = 0; i < rc_firstpass_stats->num_frames; ++i) { + gen_rc_firstpass_stats(&first_pass_info->stats_buf[i], + &rc_firstpass_stats->frame_stats[i]); + } + rc_status = ext_ratectrl->funcs.send_firstpass_stats(ext_ratectrl->model, + rc_firstpass_stats); + if (rc_status == AOM_RC_ERROR) { + return AOM_CODEC_ERROR; + } + } + return AOM_CODEC_OK; +} + aom_codec_err_t av1_extrc_delete(AOM_EXT_RATECTRL *ext_ratectrl) { if (ext_ratectrl == NULL) { return AOM_CODEC_INVALID_PARAM;
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c index a1d6640..9cd5225 100644 --- a/av1/encoder/pass2_strategy.c +++ b/av1/encoder/pass2_strategy.c
@@ -3757,6 +3757,16 @@ return; } + if (cpi->common.current_frame.frame_number == 0 && + cpi->ext_ratectrl.funcs.send_firstpass_stats != NULL) { + const aom_codec_err_t codec_status = av1_extrc_send_firstpass_stats( + &cpi->ext_ratectrl, &cpi->ppi->twopass.firstpass_info); + if (codec_status != AOM_CODEC_OK) { + aom_internal_error(cpi->common.error, codec_status, + "av1_extrc_send_firstpass_stats() failed"); + } + } + const FIRSTPASS_STATS *const start_pos = cpi->twopass_frame.stats_in; int update_total_stats = 0;
diff --git a/test/ext_ratectrl_test.cc b/test/ext_ratectrl_test.cc index ef7f92e..a84def7 100644 --- a/test/ext_ratectrl_test.cc +++ b/test/ext_ratectrl_test.cc
@@ -33,6 +33,9 @@ // A flag to indicate if delete_model() is called. bool is_delete_model_called = false; +// A flag to indicate if send_firstpass_stats() is called. +bool is_send_firstpass_stats_called = false; + aom_rc_status_t mock_create_model(void *priv, const aom_rc_config_t *ratectrl_config, aom_rc_model_t *ratectrl_model) { @@ -54,8 +57,11 @@ aom_rc_status_t mock_send_firstpass_stats( aom_rc_model_t ratectrl_model, const aom_rc_firstpass_stats_t *firstpass_stats) { - (void)ratectrl_model; - (void)firstpass_stats; + EXPECT_NE(ratectrl_model, nullptr); + EXPECT_NE(firstpass_stats, nullptr); + EXPECT_EQ(firstpass_stats->num_frames, kFrameNum); + EXPECT_NE(firstpass_stats->frame_stats, nullptr); + is_send_firstpass_stats_called = true; return AOM_RC_OK; } @@ -94,6 +100,9 @@ InitializeConfig(static_cast<libaom_test::TestMode>(GET_PARAM(1))); cfg_.g_threads = 1; cfg_.g_limit = kFrameNum; + is_create_model_called = false; + is_delete_model_called = false; + is_send_firstpass_stats_called = false; } void PreEncodeFrameHook(::libaom_test::VideoSource *video, @@ -112,6 +121,7 @@ ::libaom_test::Y4mVideoSource video("screendata.y4m", 0, kFrameNum); ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); EXPECT_TRUE(is_create_model_called); + EXPECT_TRUE(is_send_firstpass_stats_called); EXPECT_TRUE(is_delete_model_called); }