Add RATECTRL_LOG Since we need to record the rate control decision for vbr / q / bitrate_accuracy mode, separate the log object from VBR_RATECTRL_INFO Add several functions to interact with RATECTRL_LOG Other additional features: 1) Make bitrate_accuracy mode works with q mode. bitrate_accuracy with q mode will be used for training rate model parameters 2) Fix update_type bug. Properly set up update_type_list in vbr_rc_info BUG=aomedia:3045 Change-Id: I498bdedb42e14c566d95bfcae6a7adb80f09f120
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c index d60aa9e..caf7aa5 100644 --- a/av1/encoder/encode_strategy.c +++ b/av1/encoder/encode_strategy.c
@@ -1214,13 +1214,24 @@ aom_free(tpl_info); } av1_close_second_pass_log(cpi); - vbr_rc_info->base_q_index = av1_vbr_rc_info_estimate_base_q( - vbr_rc_info->total_bit_budget, cm->seq_params->bit_depth, - vbr_rc_info->scale_factors, vbr_rc_info->total_frame_count, - vbr_rc_info->update_type_list, vbr_rc_info->qstep_ratio_list, - vbr_rc_info->txfm_stats_list, vbr_rc_info->q_index_list, - vbr_rc_info->estimated_bitrate_byframe); + if (cpi->oxcf.rc_cfg.mode == AOM_Q) { + vbr_rc_info->base_q_index = cpi->oxcf.rc_cfg.cq_level; + av1_vbr_rc_compute_q_indices( + vbr_rc_info->base_q_index, vbr_rc_info->total_frame_count, + vbr_rc_info->qstep_ratio_list, cm->seq_params->bit_depth, + vbr_rc_info->q_index_list); + } else { + vbr_rc_info->base_q_index = av1_vbr_rc_info_estimate_base_q( + vbr_rc_info->total_bit_budget, cm->seq_params->bit_depth, + vbr_rc_info->scale_factors, vbr_rc_info->total_frame_count, + vbr_rc_info->update_type_list, vbr_rc_info->qstep_ratio_list, + vbr_rc_info->txfm_stats_list, vbr_rc_info->q_index_list, NULL); + } vbr_rc_info->ready = 1; +#if CONFIG_RATECTRL_LOG + rc_log_record_chunk_info(&cpi->rc_log, vbr_rc_info->base_q_index, + vbr_rc_info->total_frame_count); +#endif // CONFIG_RATECTRL_LOG } #endif // CONFIG_BITRATE_ACCURACY && CONFIG_THREE_PASS
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 039dc80..b7c87dc 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -1541,6 +1541,11 @@ void av1_remove_compressor(AV1_COMP *cpi) { if (!cpi) return; +#if CONFIG_RATECTRL_LOG + if (cpi->oxcf.pass == 3) { + rc_log_show(&cpi->rc_log); + } +#endif // CONFIG_RATECTRL_LOG AV1_COMMON *cm = &cpi->common; if (cm->current_frame.frame_number > 0) { @@ -2694,23 +2699,18 @@ #endif // CONFIG_THREE_PASS #endif // CONFIG_BITRATE_ACCURACY -#if CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS +#if CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY // TODO(angiebird): Move this into a function. if (oxcf->pass == AOM_RC_THIRD_PASS) { -#if CONFIG_BITRATE_ACCURACY int frame_coding_idx = av1_vbr_rc_frame_coding_idx(&cpi->vbr_rc_info, cpi->gf_frame_index); double qstep_ratio = cpi->vbr_rc_info.qstep_ratio_list[frame_coding_idx]; -#else - double qstep_ratio = - av1_tpl_get_qstep_ratio(&cpi->ppi->tpl_data, cpi->gf_frame_index); -#endif // CONFIG_BITRATE_ACCURACY - printf("gf_frame_index %d update_type %d q %d qstep_ratio %f\n", - cpi->gf_frame_index, - cpi->ppi->gf_group.update_type[cpi->gf_frame_index], q, - qstep_ratio); + FRAME_UPDATE_TYPE update_type = + cpi->vbr_rc_info.update_type_list[frame_coding_idx]; + rc_log_frame_encode_param(&cpi->rc_log, frame_coding_idx, qstep_ratio, q, + update_type); } -#endif // CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS +#endif // CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY av1_set_quantizer(cm, q_cfg->qm_minlevel, q_cfg->qm_maxlevel, q, q_cfg->enable_chroma_deltaq, q_cfg->enable_hdr_deltaq); @@ -2817,11 +2817,6 @@ return AOM_CODEC_ERROR; } -#if CONFIG_BITRATE_ACCURACY - cpi->vbr_rc_info.actual_coeff_bitrate_byframe[cpi->gf_frame_index] = - rc->coefficient_size; -#endif - // bits used for this frame rc->projected_frame_size = (int)(*size) << 3; #if CONFIG_RD_COMMAND @@ -2835,18 +2830,14 @@ } #endif // CONFIG_RD_COMMAND -#if CONFIG_BITRATE_ACCURACY - cpi->vbr_rc_info.actual_bitrate_byframe[cpi->gf_frame_index] = - rc->projected_frame_size; - cpi->vbr_rc_info.actual_mv_bitrate_byframe[cpi->gf_frame_index] = - rc->projected_frame_size - - cpi->vbr_rc_info.actual_coeff_bitrate_byframe[cpi->gf_frame_index]; -#if 0 - vbr_rc_info_log(&cpi->vbr_rc_info, cpi->gf_frame_index, - cpi->ppi->gf_group.size, cpi->ppi->gf_group.update_type); -#endif - -#endif +#if CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY + if (oxcf->pass == AOM_RC_THIRD_PASS) { + int frame_coding_idx = + av1_vbr_rc_frame_coding_idx(&cpi->vbr_rc_info, cpi->gf_frame_index); + rc_log_frame_entropy(&cpi->rc_log, frame_coding_idx, + rc->projected_frame_size, rc->coefficient_size); + } +#endif // CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY } #if CONFIG_TUNE_VMAF @@ -3384,6 +3375,16 @@ } if (encode_show_existing_frame(cm)) { +#if CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY + // TODO(angiebird): Move this into a function. + if (oxcf->pass == AOM_RC_THIRD_PASS) { + int frame_coding_idx = + av1_vbr_rc_frame_coding_idx(&cpi->vbr_rc_info, cpi->gf_frame_index); + rc_log_frame_encode_param( + &cpi->rc_log, frame_coding_idx, 1, 255, + cpi->ppi->gf_group.update_type[cpi->gf_frame_index]); + } +#endif av1_finalize_encoded_frame(cpi); // Build the bitstream int largest_tile_id = 0; // Output from bitstream: unused here
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index 3d9d479..57782a9 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h
@@ -3312,6 +3312,13 @@ VBR_RATECTRL_INFO vbr_rc_info; #endif +#if CONFIG_RATECTRL_LOG + /*! + * Structure stores information of rate control decisions. + */ + RATECTRL_LOG rc_log; +#endif // CONFIG_RATECTRL_LOG + /*! * Frame level twopass status and control data */
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c index 8bbd1d7..9e086ee 100644 --- a/av1/encoder/pass2_strategy.c +++ b/av1/encoder/pass2_strategy.c
@@ -3919,6 +3919,10 @@ (int)round(stats->count)); #endif +#if CONFIG_RATECTRL_LOG + rc_log_init(&cpi->rc_log); +#endif + // This variable monitors how far behind the second ref update is lagging. twopass->sr_update_lag = 1;
diff --git a/av1/encoder/thirdpass.c b/av1/encoder/thirdpass.c index 68944d7..d526554 100644 --- a/av1/encoder/thirdpass.c +++ b/av1/encoder/thirdpass.c
@@ -732,6 +732,7 @@ for (int i = 0; i < tpl_info->gf_length; ++i) { tpl_info->txfm_stats_list[i] = tpl_data->txfm_stats_list[i]; tpl_info->qstep_ratio_ls[i] = av1_tpl_get_qstep_ratio(tpl_data, i); + tpl_info->update_type_list[i] = gf_group->update_type[i]; } } } @@ -750,6 +751,9 @@ fwrite_and_check(&tpl_info->qstep_ratio_ls, sizeof(tpl_info->qstep_ratio_ls[0]), tpl_info->gf_length, log_stream, error); + fwrite_and_check(&tpl_info->update_type_list, + sizeof(tpl_info->update_type_list[0]), tpl_info->gf_length, + log_stream, error); } } @@ -768,6 +772,9 @@ fread_and_check(&tpl_info->qstep_ratio_ls, sizeof(tpl_info->qstep_ratio_ls[0]), tpl_info->gf_length, log_stream, error); + fread_and_check(&tpl_info->update_type_list, + sizeof(tpl_info->update_type_list[0]), tpl_info->gf_length, + log_stream, error); } } #endif // CONFIG_BITRATE_ACCURACY
diff --git a/av1/encoder/thirdpass.h b/av1/encoder/thirdpass.h index 4117532..8080c06 100644 --- a/av1/encoder/thirdpass.h +++ b/av1/encoder/thirdpass.h
@@ -41,6 +41,7 @@ int tpl_ready; TplTxfmStats txfm_stats_list[MAX_LENGTH_TPL_FRAME_STATS]; double qstep_ratio_ls[MAX_LENGTH_TPL_FRAME_STATS]; + FRAME_UPDATE_TYPE update_type_list[MAX_LENGTH_TPL_FRAME_STATS]; } TPL_INFO; #endif // CONFIG_BITRATE_ACCURACY
diff --git a/av1/encoder/tpl_model.c b/av1/encoder/tpl_model.c index 764de09..79d313b 100644 --- a/av1/encoder/tpl_model.c +++ b/av1/encoder/tpl_model.c
@@ -1502,12 +1502,16 @@ gf_group->update_type[gf_index] = LF_UPDATE; #if CONFIG_BITRATE_ACCURACY && CONFIG_THREE_PASS - // TODO(angiebird): Find a more adaptive method to decide pframe_qindex - // override the pframe_qindex in the second pass when bitrate accuracy is - // on. We found that setting this pframe_qindex make the tpl stats more - // stable. if (cpi->oxcf.pass == AOM_RC_SECOND_PASS) { - *pframe_qindex = 128; + if (cpi->oxcf.rc_cfg.mode == AOM_Q) { + *pframe_qindex = cpi->oxcf.rc_cfg.cq_level; + } else if (cpi->oxcf.rc_cfg.mode == AOM_VBR) { + // TODO(angiebird): Find a more adaptive method to decide pframe_qindex + // override the pframe_qindex in the second pass when bitrate accuracy + // is on. We found that setting this pframe_qindex make the tpl stats + // more stable. + *pframe_qindex = 128; + } } #endif // CONFIG_BITRATE_ACCURACY && CONFIG_THREE_PASS gf_group->q_val[gf_index] = *pframe_qindex; @@ -1698,6 +1702,14 @@ } av1_tpl_txfm_stats_update_abs_coeff_mean(&cpi->td.tpl_txfm_stats); av1_tpl_store_txfm_stats(tpl_data, &cpi->td.tpl_txfm_stats, frame_idx); +#if CONFIG_RATECTRL_LOG && CONFIG_THREE_PASS && CONFIG_BITRATE_ACCURACY + if (cpi->oxcf.pass == AOM_RC_THIRD_PASS) { + int frame_coding_idx = + av1_vbr_rc_frame_coding_idx(&cpi->vbr_rc_info, frame_idx); + rc_log_frame_stats(&cpi->rc_log, frame_coding_idx, + &cpi->td.tpl_txfm_stats); + } +#endif // CONFIG_RATECTRL_LOG aom_extend_frame_borders(tpl_data->tpl_frame[frame_idx].rec_picture, av1_num_planes(cm)); @@ -2059,22 +2071,12 @@ tpl_info->txfm_stats_list[i]; vbr_rc_info->qstep_ratio_list[gop_start_idx + i] = tpl_info->qstep_ratio_ls[i]; - // TODO(angiebird): This is a temporary solution. We currently apply same - // scale factor for each update_type, therefore setting everything to - // ARF_UPDATE is temporarily okay. Properly set the update_type later. - vbr_rc_info->update_type_list[gop_start_idx + i] = ARF_UPDATE; + vbr_rc_info->update_type_list[gop_start_idx + i] = + tpl_info->update_type_list[i]; } vbr_rc_info->total_frame_count += tpl_info->gf_length; vbr_rc_info->gop_count++; } - -#if CONFIG_RATECTRL_LOG -void av1_rc_frame_log(int gf_frame_index, FRAME_UPDATE_TYPE update_type, int q, - double qstep_ratio) { - printf("gf_frame_index %d update_type %d q %d qstep_ratio %f\n", - gf_frame_index, update_type, q, qstep_ratio); -} -#endif // CONFIG_RATECTRL_LOG #endif // CONFIG_THREE_PASS void av1_vbr_rc_set_gop_bit_budget(VBR_RATECTRL_INFO *vbr_rc_info, @@ -2085,10 +2087,10 @@ vbr_rc_info->show_frame_count; } -static INLINE void compute_q_indices(int base_q_index, int frame_count, - const double *qstep_ratio_list, - aom_bit_depth_t bit_depth, - int *q_index_list) { +void av1_vbr_rc_compute_q_indices(int base_q_index, int frame_count, + const double *qstep_ratio_list, + aom_bit_depth_t bit_depth, + int *q_index_list) { for (int i = 0; i < frame_count; ++i) { q_index_list[i] = av1_get_q_index_from_qstep_ratio( base_q_index, qstep_ratio_list[i], bit_depth); @@ -2101,26 +2103,25 @@ const FRAME_UPDATE_TYPE *update_type_list, const double *qstep_ratio_list, const TplTxfmStats *stats_list, int *q_index_list, double *estimated_bitrate_byframe) { - compute_q_indices(base_q_index, frame_count, qstep_ratio_list, bit_depth, - q_index_list); + av1_vbr_rc_compute_q_indices(base_q_index, frame_count, qstep_ratio_list, + bit_depth, q_index_list); + double estimated_gop_bitrate = 0; for (int frame_index = 0; frame_index < frame_count; frame_index++) { const TplTxfmStats *frame_stats = &stats_list[frame_index]; + double frame_bitrate = 0; if (frame_stats->ready) { int q_index = q_index_list[frame_index]; - double frame_bitrate = av1_laplace_estimate_frame_rate( + frame_bitrate = av1_laplace_estimate_frame_rate( q_index, frame_stats->txfm_block_count, frame_stats->abs_coeff_mean, frame_stats->coeff_num); - estimated_bitrate_byframe[frame_index] = frame_bitrate; - } else { - estimated_bitrate_byframe[frame_index] = 0; } - } - double estimated_gop_bitrate = 0; - for (int i = 0; i < frame_count; ++i) { - FRAME_UPDATE_TYPE update_type = update_type_list[i]; + FRAME_UPDATE_TYPE update_type = update_type_list[frame_index]; estimated_gop_bitrate += - estimated_bitrate_byframe[i] * update_type_scale_factors[update_type]; + frame_bitrate * update_type_scale_factors[update_type]; + if (estimated_bitrate_byframe != NULL) { + estimated_bitrate_byframe[frame_index] = frame_bitrate; + } } return estimated_gop_bitrate; } @@ -2180,7 +2181,17 @@ vbr_rc_info->qstep_ratio_list[i] = av1_tpl_get_qstep_ratio(tpl_data, i); } - double mv_bits = av1_tpl_compute_mv_bits(tpl_data, gf_group, vbr_rc_info); + double mv_bits = 0; + for (int i = 0; i < gf_group->size; i++) { + double frame_mv_bits = 0; + if (av1_tpl_stats_ready(tpl_data, i)) { + TplDepFrame *tpl_frame = &tpl_data->tpl_frame[i]; + frame_mv_bits = av1_tpl_compute_frame_mv_entropy( + tpl_frame, tpl_data->tpl_stats_block_mis_log2); + FRAME_UPDATE_TYPE updae_type = gf_group->update_type[i]; + mv_bits += frame_mv_bits * vbr_rc_info->mv_scale_factors[updae_type]; + } + } mv_bits = AOMMIN(mv_bits, 0.6 * gop_bit_budget); gop_bit_budget -= mv_bits; @@ -2188,34 +2199,9 @@ vbr_rc_info->base_q_index = av1_vbr_rc_info_estimate_base_q( gop_bit_budget, bit_depth, vbr_rc_info->scale_factors, gf_group->size, gf_group->update_type, vbr_rc_info->qstep_ratio_list, - tpl_data->txfm_stats_list, vbr_rc_info->q_index_list, - vbr_rc_info->estimated_bitrate_byframe); + tpl_data->txfm_stats_list, vbr_rc_info->q_index_list, NULL); } -/* For a GOP, calculate the bits used by motion vectors. */ -double av1_tpl_compute_mv_bits(const TplParams *tpl_data, - const GF_GROUP *gf_group, - VBR_RATECTRL_INFO *vbr_rc_info) { - double total_mv_bits = 0; - - // Loop through each frame. - for (int i = 0; i < gf_group->size; i++) { - if (av1_tpl_stats_ready(tpl_data, i)) { - TplDepFrame *tpl_frame = &tpl_data->tpl_frame[i]; - double frame_mv_bits = av1_tpl_compute_frame_mv_entropy( - tpl_frame, tpl_data->tpl_stats_block_mis_log2); - vbr_rc_info->estimated_mv_bitrate_byframe[i] = frame_mv_bits; - FRAME_UPDATE_TYPE updae_type = gf_group->update_type[i]; - total_mv_bits += - frame_mv_bits * vbr_rc_info->mv_scale_factors[updae_type]; - } else { - vbr_rc_info->estimated_mv_bitrate_byframe[i] = 0; - } - } - - // Scale the final result by the scale factor. - return total_mv_bits; -} #endif // CONFIG_BITRATE_ACCURACY // Use upper and left neighbor block as the reference MVs.
diff --git a/av1/encoder/tpl_model.h b/av1/encoder/tpl_model.h index a974f98..b77a19f 100644 --- a/av1/encoder/tpl_model.h +++ b/av1/encoder/tpl_model.h
@@ -225,13 +225,11 @@ } TplParams; -#if CONFIG_BITRATE_ACCURACY - -#if CONFIG_THREE_PASS +#if CONFIG_BITRATE_ACCURACY || CONFIG_RATECTRL_LOG #define VBR_RC_INFO_MAX_FRAMES 500 -#else // CONFIG_THREE_PASS -#define VBR_RC_INFO_MAX_FRAMES MAX_LENGTH_TPL_FRAME_STATS -#endif // CONFIG_THREE_PASS +#endif // CONFIG_BITRATE_ACCURACY || CONFIG_RATECTRL_LOG + +#if CONFIG_BITRATE_ACCURACY /*! * \brief This structure stores information needed for bitrate accuracy @@ -254,12 +252,6 @@ int q_index_list_ready; int q_index_list[VBR_RC_INFO_MAX_FRAMES]; // q indices for the current // GOP - // Arrays to store frame level bitrate accuracy data. - double estimated_bitrate_byframe[VBR_RC_INFO_MAX_FRAMES]; - double estimated_mv_bitrate_byframe[VBR_RC_INFO_MAX_FRAMES]; - int actual_bitrate_byframe[VBR_RC_INFO_MAX_FRAMES]; - int actual_mv_bitrate_byframe[VBR_RC_INFO_MAX_FRAMES]; - int actual_coeff_bitrate_byframe[VBR_RC_INFO_MAX_FRAMES]; // Array to store qstep_ratio for each frame in a GOP double qstep_ratio_list[VBR_RC_INFO_MAX_FRAMES]; @@ -278,11 +270,6 @@ static INLINE void vbr_rc_reset_gop_data(VBR_RATECTRL_INFO *vbr_rc_info) { vbr_rc_info->q_index_list_ready = 0; av1_zero(vbr_rc_info->q_index_list); - av1_zero(vbr_rc_info->estimated_bitrate_byframe); - av1_zero(vbr_rc_info->estimated_mv_bitrate_byframe); - av1_zero(vbr_rc_info->actual_bitrate_byframe); - av1_zero(vbr_rc_info->actual_mv_bitrate_byframe); - av1_zero(vbr_rc_info->actual_coeff_bitrate_byframe); } void av1_vbr_rc_init(VBR_RATECTRL_INFO *vbr_rc_info, double total_bit_budget, @@ -293,28 +280,13 @@ void av1_vbr_rc_append_tpl_info(VBR_RATECTRL_INFO *vbr_rc_info, const struct TPL_INFO *tpl_info); + void av1_vbr_rc_set_gop_bit_budget(VBR_RATECTRL_INFO *vbr_rc_info, int gop_showframe_count); -static INLINE void vbr_rc_info_log(const VBR_RATECTRL_INFO *vbr_rc_info, - int gf_frame_index, int gf_group_size, - FRAME_UPDATE_TYPE *update_type) { - // Add +2 here because this is the last frame this method is called at. - if (gf_frame_index + 2 >= gf_group_size) { - printf( - "\ni, \test_bitrate, \test_mv_bitrate, \tact_bitrate, " - "\tact_mv_bitrate, \tact_coeff_bitrate, \tq, \tupdate_type\n"); - for (int i = 0; i < gf_group_size; i++) { - printf("%d, \t%f, \t%f, \t%d, \t%d, \t%d, \t%d, \t%d\n", i, - vbr_rc_info->estimated_bitrate_byframe[i], - vbr_rc_info->estimated_mv_bitrate_byframe[i], - vbr_rc_info->actual_bitrate_byframe[i], - vbr_rc_info->actual_mv_bitrate_byframe[i], - vbr_rc_info->actual_coeff_bitrate_byframe[i], - vbr_rc_info->q_index_list[i], update_type[i]); - } - } -} +void av1_vbr_rc_compute_q_indices(int base_q_index, int frame_count, + const double *qstep_ratio_list, + aom_bit_depth_t bit_depth, int *q_index_list); /*!\brief Update q_index_list in vbr_rc_info based on tpl stats * @@ -331,18 +303,21 @@ /* *!\brief Compute the number of bits needed to encode a GOP * - * \param[in] base_q_index base layer q_index - * \param[in] bit_depth bit depth + * \param[in] base_q_index base layer q_index + * \param[in] bit_depth bit depth * \param[in] update_type_scale_factors array of scale factors for each - * update_type - * \param[in] frame_count size of update_type_list, qstep_ratio_list - * stats_list, q_index_list and - * estimated_bitrate_byframe - * \param[in] update_type_list array of update_type, one per frame - * \param[in] qstep_ratio_list array of qstep_ratio, one per frame - * \param[in] stats_list array of transform stats, one per frame - * \param[out] q_index_list array of q_index, one per frame - * \param[out] estimated_bitrate_byframe Array to keep track of frame bitrate + * update_type + * \param[in] frame_count size of update_type_list, + * qstep_ratio_list stats_list, + * q_index_list and + * estimated_bitrate_byframe + * \param[in] update_type_list array of update_type, one per frame + * \param[in] qstep_ratio_list array of qstep_ratio, one per frame + * \param[in] stats_list array of transform stats, one per + * frame + * \param[out] q_index_list array of q_index, one per frame + * \param[out] estimated_bitrate_byframe array to keep track of frame + * bitrate * * \return The estimated GOP bitrate. * @@ -370,7 +345,8 @@ * \param[in] qstep_ratio_list array of qstep_ratio, one per frame * \param[in] stats_list array of transform stats, one per frame * \param[out] q_index_list array of q_index, one per frame - * \param[out] estimated_bitrate_byframe Array to keep track of frame bitrate + * \param[out] estimated_bitrate_byframe Array to keep track of frame + * bitrate * * \return Returns the optimal base q index to use. */ @@ -381,17 +357,6 @@ const TplTxfmStats *stats_list, int *q_index_list, double *estimated_bitrate_byframe); -/*!\brief For a GOP, calculate the bits used by motion vectors. - * - * \param[in] tpl_data TPL struct - * \param[in] gf_group GOP struct - * \param[in] vbr_rc_info Rate control info struct - * - * \return Bits used by the motion vectors for the GOP. - */ -double av1_tpl_compute_mv_bits(const TplParams *tpl_data, - const GF_GROUP *gf_group, - VBR_RATECTRL_INFO *vbr_rc_info); #endif // CONFIG_BITRATE_ACCURACY #if CONFIG_RD_COMMAND @@ -520,8 +485,8 @@ *!\brief Accumulate TplTxfmStats * * \param[in] sub_stats a structure for storing sub transform stats - * \param[out] accumulated_stats a structure for storing accumulated transform - *stats + * \param[out] accumulated_stats a structure for storing accumulated + *transform stats * */ void av1_accumulate_tpl_txfm_stats(const TplTxfmStats *sub_stats, @@ -552,13 +517,13 @@ * *\ingroup tpl_modelling * - * This function is equivalent to -log2(laplace_prob()), where laplace_prob() is - * defined in tpl_model_test.cc + * This function is equivalent to -log2(laplace_prob()), where laplace_prob() + *is defined in tpl_model_test.cc * * \param[in] q_step quantizer step size without any scaling - * \param[in] b mean absolute deviation of Laplace distribution - * \param[in] zero_bin_ratio zero bin's size is zero_bin_ratio * q_step - * \param[in] qcoeff quantized coefficient + * \param[in] b mean absolute deviation of Laplace + *distribution \param[in] zero_bin_ratio zero bin's size is zero_bin_ratio + ** q_step \param[in] qcoeff quantized coefficient * * \return estimated coefficient entropy * @@ -626,8 +591,8 @@ double av1_tpl_get_frame_importance(const TplParams *tpl_data, int gf_frame_index); -/*!\brief Compute the ratio between arf q step and the leaf q step based on TPL - * stats +/*!\brief Compute the ratio between arf q step and the leaf q step based on + * TPL stats * * \param[in] tpl_data TPL struct * \param[in] gf_frame_index current frame index in the GOP @@ -641,16 +606,16 @@ /*!\brief Find a q index whose step size is near qstep_ratio * leaf_qstep * * \param[in] leaf_qindex q index of leaf frame - * \param[in] qstep_ratio step ratio between target q index and leaf - * q index - * \param[in] bit_depth bit depth + * \param[in] qstep_ratio step ratio between target q index and + * leaf q index \param[in] bit_depth bit depth * * \return q_index */ int av1_get_q_index_from_qstep_ratio(int leaf_qindex, double qstep_ratio, aom_bit_depth_t bit_depth); -/*!\brief Improve the motion vector estimation by taking neighbors into account. +/*!\brief Improve the motion vector estimation by taking neighbors into + * account. * * Use the upper and left neighbor block as the reference MVs. * Compute the minimum difference between current MV and reference MV. @@ -660,7 +625,8 @@ * \param[in] col Current column * \param[in] step Step parameter for av1_tpl_ptr_pos * \param[in] tpl_stride Stride parameter for av1_tpl_ptr_pos - * \param[in] right_shift Right shift parameter for av1_tpl_ptr_pos + * \param[in] right_shift Right shift parameter for + * av1_tpl_ptr_pos */ int_mv av1_compute_mv_difference(const TplDepFrame *tpl_frame, int row, int col, int step, int tpl_stride, int right_shift); @@ -675,6 +641,83 @@ double av1_tpl_compute_frame_mv_entropy(const TplDepFrame *tpl_frame, uint8_t right_shift); +#if CONFIG_RATECTRL_LOG +typedef struct { + int coding_frame_count; + int base_q_index; + + // Encode decision + int q_index_list[VBR_RC_INFO_MAX_FRAMES]; + double qstep_ratio_list[VBR_RC_INFO_MAX_FRAMES]; + FRAME_UPDATE_TYPE update_type_list[VBR_RC_INFO_MAX_FRAMES]; + + // Frame stats + TplTxfmStats txfm_stats_list[VBR_RC_INFO_MAX_FRAMES]; + + // Estimated encode results + double est_coeff_rate_list[VBR_RC_INFO_MAX_FRAMES]; + + // Actual encode results + double act_rate_list[VBR_RC_INFO_MAX_FRAMES]; + double act_coeff_rate_list[VBR_RC_INFO_MAX_FRAMES]; +} RATECTRL_LOG; + +static INLINE void rc_log_init(RATECTRL_LOG *rc_log) { av1_zero(*rc_log); } + +static INLINE void rc_log_frame_stats(RATECTRL_LOG *rc_log, int coding_index, + const TplTxfmStats *txfm_stats) { + rc_log->txfm_stats_list[coding_index] = *txfm_stats; +} + +static INLINE void rc_log_frame_encode_param(RATECTRL_LOG *rc_log, + int coding_index, + double qstep_ratio, int q_index, + FRAME_UPDATE_TYPE update_type) { + rc_log->qstep_ratio_list[coding_index] = qstep_ratio; + rc_log->q_index_list[coding_index] = q_index; + rc_log->update_type_list[coding_index] = update_type; + const TplTxfmStats *txfm_stats = &rc_log->txfm_stats_list[coding_index]; + rc_log->est_coeff_rate_list[coding_index] = 0; + if (txfm_stats->ready) { + rc_log->est_coeff_rate_list[coding_index] = av1_laplace_estimate_frame_rate( + q_index, txfm_stats->txfm_block_count, txfm_stats->abs_coeff_mean, + txfm_stats->coeff_num); + } +} + +static INLINE void rc_log_frame_entropy(RATECTRL_LOG *rc_log, int coding_index, + double act_rate, + double act_coeff_rate) { + rc_log->act_rate_list[coding_index] = act_rate; + rc_log->act_coeff_rate_list[coding_index] = act_coeff_rate; +} + +static INLINE void rc_log_record_chunk_info(RATECTRL_LOG *rc_log, + int base_q_index, + int coding_frame_count) { + rc_log->base_q_index = base_q_index; + rc_log->coding_frame_count = coding_frame_count; +} + +static INLINE void rc_log_show(const RATECTRL_LOG *rc_log) { + printf("= chunk 1\n"); + printf("coding_frame_count %d base_q_index %d\n", rc_log->coding_frame_count, + rc_log->base_q_index); + printf("= frame %d\n", rc_log->coding_frame_count); + for (int coding_idx = 0; coding_idx < rc_log->coding_frame_count; + coding_idx++) { + printf( + "coding_idx %d update_type %d q %d qstep_ratio %f est_coeff_rate %f " + "act_coeff_rate %f act_rate %f\n", + coding_idx, rc_log->update_type_list[coding_idx], + rc_log->q_index_list[coding_idx], rc_log->qstep_ratio_list[coding_idx], + rc_log->est_coeff_rate_list[coding_idx], + rc_log->act_coeff_rate_list[coding_idx], + rc_log->act_rate_list[coding_idx]); + } +} +#endif // CONFIG_RATECTRL_LOG + /*!\endcond */ #ifdef __cplusplus } // extern "C"
diff --git a/test/tpl_model_test.cc b/test/tpl_model_test.cc index a875ed6..ed2f593 100644 --- a/test/tpl_model_test.cc +++ b/test/tpl_model_test.cc
@@ -436,31 +436,32 @@ std::vector<TplTxfmStats> stats_list(gf_group.size); init_toy_tpl_txfm_stats(&stats_list); + + std::vector<double> est_bitrate_list(gf_group.size); + init_toy_tpl_txfm_stats(&stats_list); const aom_bit_depth_t bit_depth = AOM_BITS_8; const int q = 125; // Case1: all scale factors are 0 double scale_factors[FRAME_UPDATE_TYPES] = { 0 }; - memcpy(vbr_rc_info.scale_factors, scale_factors, sizeof(scale_factors)); double estimate = av1_vbr_rc_info_estimate_gop_bitrate( - q, bit_depth, vbr_rc_info.scale_factors, gf_group.size, - gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(), - vbr_rc_info.q_index_list, vbr_rc_info.estimated_bitrate_byframe); + q, bit_depth, scale_factors, gf_group.size, gf_group.update_type, + vbr_rc_info.qstep_ratio_list, stats_list.data(), vbr_rc_info.q_index_list, + est_bitrate_list.data()); EXPECT_NEAR(estimate, 0, epsilon); // Case2: all scale factors are 1 for (int i = 0; i < FRAME_UPDATE_TYPES; i++) { scale_factors[i] = 1; } - memcpy(vbr_rc_info.scale_factors, scale_factors, sizeof(scale_factors)); estimate = av1_vbr_rc_info_estimate_gop_bitrate( - q, bit_depth, vbr_rc_info.scale_factors, gf_group.size, - gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(), - vbr_rc_info.q_index_list, vbr_rc_info.estimated_bitrate_byframe); + q, bit_depth, scale_factors, gf_group.size, gf_group.update_type, + vbr_rc_info.qstep_ratio_list, stats_list.data(), vbr_rc_info.q_index_list, + est_bitrate_list.data()); double ref_estimate = 0; for (int i = 0; i < gf_group.size; i++) { - ref_estimate += vbr_rc_info.estimated_bitrate_byframe[i]; + ref_estimate += est_bitrate_list[i]; } EXPECT_NEAR(estimate, ref_estimate, epsilon); @@ -472,15 +473,14 @@ scale_factors[i] = 1; } } - memcpy(vbr_rc_info.scale_factors, scale_factors, sizeof(scale_factors)); estimate = av1_vbr_rc_info_estimate_gop_bitrate( - q, bit_depth, vbr_rc_info.scale_factors, gf_group.size, - gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(), - vbr_rc_info.q_index_list, vbr_rc_info.estimated_bitrate_byframe); + q, bit_depth, scale_factors, gf_group.size, gf_group.update_type, + vbr_rc_info.qstep_ratio_list, stats_list.data(), vbr_rc_info.q_index_list, + est_bitrate_list.data()); ref_estimate = 0; for (int i = 0; i < gf_group.size; i++) { if (gf_group.update_type[i] != KF_UPDATE) { - ref_estimate += vbr_rc_info.estimated_bitrate_byframe[i]; + ref_estimate += est_bitrate_list[i]; } } EXPECT_NEAR(estimate, ref_estimate, epsilon); @@ -493,9 +493,6 @@ VBR_RATECTRL_INFO vbr_rc_info; init_toy_vbr_rc_info(&vbr_rc_info, gf_group.size); - VBR_RATECTRL_INFO ref_vbr_rc_info; - init_toy_vbr_rc_info(&ref_vbr_rc_info, gf_group.size); - std::vector<TplTxfmStats> stats_list(gf_group.size); init_toy_tpl_txfm_stats(&stats_list); const aom_bit_depth_t bit_depth = AOM_BITS_8; @@ -509,11 +506,11 @@ const int base_q = av1_vbr_rc_info_estimate_base_q( bit_budget, bit_depth, vbr_rc_info.scale_factors, gf_group.size, gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(), - vbr_rc_info.q_index_list, vbr_rc_info.estimated_bitrate_byframe); + vbr_rc_info.q_index_list, NULL); const int ref_base_q = find_gop_q_iterative( bit_budget, bit_depth, vbr_rc_info.scale_factors, gf_group.size, gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(), - vbr_rc_info.q_index_list, vbr_rc_info.estimated_bitrate_byframe); + vbr_rc_info.q_index_list, NULL); if (bit_budget == 0) { EXPECT_EQ(base_q, 255); } else if (bit_budget == DBL_MAX) {