From 97f4fb7b5f1eb76d879601f469057f52a87b9f9c Mon Sep 17 00:00:00 2001 From: Deb Mukherjee Date: Tue, 1 Apr 2014 17:31:59 -0700 Subject: [PATCH] Rate ctrl changes to track target bitrates closer Turns off the DISABLE_RC_LONG_TERM_MEM macro and makes other changes in the way the bits are updated, to make 2-pass rate control track target bitrates closer. Change-Id: I5f3be4b11c2908e6a9a9a1dd4fcf4e65531c44d8 --- vp9/encoder/vp9_bitstream.c | 5 +++-- vp9/encoder/vp9_encodeframe.c | 1 + vp9/encoder/vp9_firstpass.c | 47 ++++++++++++++----------------------------- vp9/encoder/vp9_firstpass.h | 3 +-- vp9/encoder/vp9_onyx_if.c | 7 +++---- vp9/encoder/vp9_ratectrl.c | 5 ++--- vp9/encoder/vp9_ratectrl.h | 5 +++-- vp9/vp9_cx_iface.c | 4 ++-- 8 files changed, 30 insertions(+), 47 deletions(-) diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 544a27d..7c811e2 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -1186,7 +1186,7 @@ static size_t write_compressed_header(VP9_COMP *cpi, uint8_t *data) { void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, size_t *size) { uint8_t *data = dest; - size_t first_part_size; + size_t first_part_size, uncompressed_hdr_size; struct vp9_write_bit_buffer wb = {data, 0}; struct vp9_write_bit_buffer saved_wb; @@ -1194,7 +1194,8 @@ void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, size_t *size) { saved_wb = wb; vp9_wb_write_literal(&wb, 0, 16); // don't know in advance first part. size - data += vp9_rb_bytes_written(&wb); + uncompressed_hdr_size = vp9_rb_bytes_written(&wb); + data += uncompressed_hdr_size; vp9_compute_update_table(); diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index cdca93a..42e1ac8 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -2336,6 +2336,7 @@ static void encode_rd_sb_row(VP9_COMP *cpi, const TileInfo *const tile, if ((cpi->sf.partition_search_type == SEARCH_PARTITION && cpi->sf.use_lastframe_partitioning) || cpi->sf.partition_search_type == FIXED_PARTITION || + cpi->sf.partition_search_type == VAR_BASED_PARTITION || cpi->sf.partition_search_type == VAR_BASED_FIXED_PARTITION) { const int idx_str = cm->mi_stride * mi_row + mi_col; MODE_INFO **mi_8x8 = cm->mi_grid_visible + idx_str; diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index cf0f805..7ec5255 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -54,8 +54,6 @@ #define MIN_KF_BOOST 300 -#define DISABLE_RC_LONG_TERM_MEM 0 - #if CONFIG_MULTIPLE_ARF // Set MIN_GF_INTERVAL to 1 for the full decomposition. #define MIN_GF_INTERVAL 2 @@ -1736,10 +1734,6 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { { // Adjust KF group bits and error remaining. twopass->kf_group_error_left -= (int64_t)gf_group_err; - twopass->kf_group_bits -= twopass->gf_group_bits; - - if (twopass->kf_group_bits < 0) - twopass->kf_group_bits = 0; // If this is an arf update we want to remove the score for the overlay // frame at the end which will usually be very cheap to code. @@ -1756,11 +1750,6 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { twopass->gf_group_error_left = (int64_t)gf_group_err; } - twopass->gf_group_bits -= twopass->gf_bits; - - if (twopass->gf_group_bits < 0) - twopass->gf_group_bits = 0; - // This condition could fail if there are two kfs very close together // despite MIN_GF_INTERVAL and would cause a divide by 0 in the // calculation of alt_extra_bits. @@ -1769,8 +1758,9 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { if (boost >= 150) { const int pct_extra = MIN(20, (boost - 100) / 50); - const int alt_extra_bits = (int)((twopass->gf_group_bits * pct_extra) / - 100); + const int alt_extra_bits = (int)(( + MAX(twopass->gf_group_bits - twopass->gf_bits, 0) * + pct_extra) / 100); twopass->gf_group_bits -= alt_extra_bits; } } @@ -1823,10 +1813,6 @@ static void assign_std_frame_bits(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { // Adjust error and bits remaining. cpi->twopass.gf_group_error_left -= (int64_t)modified_err; - cpi->twopass.gf_group_bits -= target_frame_size; - - if (cpi->twopass.gf_group_bits < 0) - cpi->twopass.gf_group_bits = 0; // Per frame bit target for this frame. vp9_rc_set_frame_target(cpi, target_frame_size); @@ -2343,23 +2329,20 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { subtract_stats(&twopass->total_left_stats, &this_frame); } -void vp9_twopass_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) { -#ifdef DISABLE_RC_LONG_TERM_MEM - cpi->twopass.bits_left -= cpi->rc.this_frame_target; -#else - cpi->twopass.bits_left -= 8 * bytes_used; +void vp9_twopass_postencode_update(VP9_COMP *cpi) { + const uint64_t bits_used = cpi->rc.projected_frame_size; + cpi->twopass.bits_left -= bits_used; + cpi->twopass.bits_left = MAX(cpi->twopass.bits_left, 0); // Update bits left to the kf and gf groups to account for overshoot or // undershoot on these frames. - if (cm->frame_type == KEY_FRAME) { - cpi->twopass.kf_group_bits += cpi->rc.this_frame_target - - cpi->rc.projected_frame_size; - - cpi->twopass.kf_group_bits = MAX(cpi->twopass.kf_group_bits, 0); - } else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) { - cpi->twopass.gf_group_bits += cpi->rc.this_frame_target - - cpi->rc.projected_frame_size; - + if (cpi->common.frame_type == KEY_FRAME) { + // For key frames kf_group_bits already had the target bits subtracted out. + // So now update to the correct value based on the actual bits used. + cpi->twopass.kf_group_bits += cpi->rc.this_frame_target - bits_used; + } else { + cpi->twopass.kf_group_bits -= bits_used; + cpi->twopass.gf_group_bits -= bits_used; cpi->twopass.gf_group_bits = MAX(cpi->twopass.gf_group_bits, 0); } -#endif + cpi->twopass.kf_group_bits = MAX(cpi->twopass.kf_group_bits, 0); } diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h index 9268c38..7a16c8f 100644 --- a/vp9/encoder/vp9_firstpass.h +++ b/vp9/encoder/vp9_firstpass.h @@ -95,8 +95,7 @@ int vp9_twopass_worst_quality(struct VP9_COMP *cpi, FIRSTPASS_STATS *fpstats, int section_target_bandwitdh); // Post encode update of the rate control parameters for 2-pass -void vp9_twopass_postencode_update(struct VP9_COMP *cpi, - uint64_t bytes_used); +void vp9_twopass_postencode_update(struct VP9_COMP *cpi); #ifdef __cplusplus } // extern "C" #endif diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 1f83f6b..f8427cf 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -696,10 +696,9 @@ void vp9_new_framerate(VP9_COMP *cpi, double framerate) { oxcf->framerate = framerate < 0.1 ? 30 : framerate; cpi->output_framerate = cpi->oxcf.framerate; rc->av_per_frame_bandwidth = (int)(oxcf->target_bandwidth / - cpi->output_framerate); + cpi->output_framerate); rc->min_frame_bandwidth = (int)(rc->av_per_frame_bandwidth * - oxcf->two_pass_vbrmin_section / 100); - + oxcf->two_pass_vbrmin_section / 100); rc->min_frame_bandwidth = MAX(rc->min_frame_bandwidth, FRAME_OVERHEAD_BITS); @@ -2883,7 +2882,7 @@ static void Pass2Encode(VP9_COMP *cpi, size_t *size, vp9_rc_get_second_pass_params(cpi); encode_frame_to_data_rate(cpi, size, dest, frame_flags); - vp9_twopass_postencode_update(cpi, *size); + vp9_twopass_postencode_update(cpi); } static void check_initial_width(VP9_COMP *cpi, int subsampling_x, diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 9ee5818..0169014 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -1150,10 +1150,9 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) { // Actual bits spent rc->total_actual_bits += rc->projected_frame_size; + rc->total_target_bits += (cm->show_frame ? rc->av_per_frame_bandwidth : 0); - // Debug stats - rc->total_target_vs_actual += (rc->this_frame_target - - rc->projected_frame_size); + rc->total_target_vs_actual = rc->total_actual_bits - rc->total_target_bits; if (cpi->oxcf.play_alternate && cpi->refresh_alt_ref_frame && (cm->frame_type != KEY_FRAME)) diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index 87421af..f2d128c 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -58,7 +58,7 @@ typedef struct { int ni_av_qi; int ni_tot_qi; int ni_frames; - int avg_frame_qindex[3]; // 0 - KEY, 1 - INTER, 2 - ARF/GF + int avg_frame_qindex[3]; // 0 - KEY, 1 - INTER, 2 - ARF/GF double tot_q; double avg_q; @@ -75,7 +75,8 @@ typedef struct { int long_rolling_actual_bits; int64_t total_actual_bits; - int total_target_vs_actual; // debug stats + int64_t total_target_bits; + int64_t total_target_vs_actual; int worst_quality; int best_quality; diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index c39ccba..a9fd8c1 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -730,8 +730,8 @@ static vpx_codec_err_t vp9e_encode(vpx_codec_alg_priv_t *ctx, // Convert API flags to internal codec lib flags lib_flags = (flags & VPX_EFLAG_FORCE_KF) ? FRAMEFLAGS_KEY : 0; - // vp8 use 10,000,000 ticks/second as time stamp - dst_time_stamp = pts * 10000000 * ctx->cfg.g_timebase.num + /* vp9 use 10,000,000 ticks/second as time stamp */ + dst_time_stamp = (pts * 10000000 * ctx->cfg.g_timebase.num) / ctx->cfg.g_timebase.den; dst_end_time_stamp = (pts + duration) * 10000000 * ctx->cfg.g_timebase.num / ctx->cfg.g_timebase.den; -- 2.7.4