From 52d273674beab6efa96d36c4da672ee23813c7b4 Mon Sep 17 00:00:00 2001 From: Deb Mukherjee Date: Tue, 3 Dec 2013 17:05:19 -0800 Subject: [PATCH] Further rate control cleanups Includes various cleanups. Streamlines the interfaces so that all rate control state updates happen in the vp9_rc_postencode_update() function. This will hopefully make it easier to support multiple rate control schemes. Removes some unnecessary code, which in rare cases can casue a difference in the constrained quality mode output, but other than that there is no bitstream change yet. Change-Id: I3198cc37249932feea1e3691c0b2650e7b0c22fc --- vp9/encoder/vp9_firstpass.c | 15 ---- vp9/encoder/vp9_onyx_if.c | 163 +++++++++++++---------------------- vp9/encoder/vp9_onyx_int.h | 4 +- vp9/encoder/vp9_ratectrl.c | 204 ++++++++++++++++++++++++-------------------- vp9/encoder/vp9_ratectrl.h | 20 +++-- 5 files changed, 184 insertions(+), 222 deletions(-) diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 50d8036..5ec0b76 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -2170,21 +2170,6 @@ void vp9_second_pass(VP9_COMP *cpi) { (int)(cpi->twopass.bits_left / frames_left); cpi->twopass.est_max_qcorrection_factor = 1.0; - // Set a cq_level in constrained quality mode. - // Commenting this code out for now since it does not seem to be - // working well. - /* - if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) { - int est_cq = estimate_cq(cpi, &cpi->twopass.total_left_stats, - section_target_bandwidth); - - if (est_cq > cpi->cq_target_quality) - cpi->cq_target_quality = est_cq; - else - cpi->cq_target_quality = cpi->oxcf.cq_level; - } - */ - // guess at maxq needed in 2nd pass cpi->twopass.maxq_max_limit = cpi->rc.worst_quality; cpi->twopass.maxq_min_limit = cpi->rc.best_quality; diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 968cbfb..e724eca 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -143,8 +143,9 @@ static INLINE void Scale2Ratio(int mode, int *hr, int *hs) { } } -static void set_mvcost(VP9_COMP *cpi) { +static void set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv) { MACROBLOCK *const mb = &cpi->mb; + cpi->common.allow_high_precision_mv = allow_high_precision_mv; if (cpi->common.allow_high_precision_mv) { mb->mvcost = mb->nmvcost_hp; mb->mvsadcost = mb->nmvsadcost_hp; @@ -234,7 +235,7 @@ static void dealloc_compressor_data(VP9_COMP *cpi) { // Computes a q delta (in "q index" terms) to get from a starting q value // to a target value // target q value -int vp9_compute_qdelta(VP9_COMP *cpi, double qstart, double qtarget) { +int vp9_compute_qdelta(const VP9_COMP *cpi, double qstart, double qtarget) { int i; int start_index = cpi->rc.worst_quality; int target_index = cpi->rc.worst_quality; @@ -1115,8 +1116,8 @@ static void init_config(VP9_PTR ptr, VP9_CONFIG *oxcf) { vp9_change_config(ptr, oxcf); // Initialize active best and worst q and average q values. - cpi->rc.active_worst_quality = cpi->oxcf.worst_allowed_q; - cpi->rc.active_best_quality = cpi->oxcf.best_allowed_q; + cpi->rc.active_worst_quality = cpi->oxcf.worst_allowed_q; + cpi->rc.avg_frame_qindex = cpi->oxcf.worst_allowed_q; // Initialise the starting buffer levels @@ -1205,8 +1206,7 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) { cm->reset_frame_context = 0; setup_features(cm); - cpi->common.allow_high_precision_mv = 0; // Default mv precision - set_mvcost(cpi); + set_high_precision_mv(cpi, 0); { int i; @@ -1253,12 +1253,8 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) { // active values should only be modified if out of new range cpi->rc.active_worst_quality = clamp(cpi->rc.active_worst_quality, - cpi->oxcf.best_allowed_q, - cpi->oxcf.worst_allowed_q); - - cpi->rc.active_best_quality = clamp(cpi->rc.active_best_quality, - cpi->oxcf.best_allowed_q, - cpi->oxcf.worst_allowed_q); + cpi->rc.best_quality, + cpi->rc.worst_quality); cpi->cq_target_quality = cpi->oxcf.cq_level; @@ -2369,16 +2365,6 @@ static int find_fp_qindex() { return i; } -static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest, - unsigned int *frame_flags) { - (void) size; - (void) dest; - (void) frame_flags; - - vp9_set_quantizer(cpi, find_fp_qindex()); - vp9_first_pass(cpi); -} - #define WRITE_RECON_BUFFER 0 #if WRITE_RECON_BUFFER void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) { @@ -2470,16 +2456,9 @@ static int recode_loop_test(VP9_COMP *cpi, cpi->rc.projected_frame_size < ((cpi->rc.this_frame_target * 7) >> 3)) { force_recode = 1; - } else if (q > cpi->oxcf.cq_level && - cpi->rc.projected_frame_size < cpi->rc.min_frame_bandwidth && - cpi->rc.active_best_quality > cpi->oxcf.cq_level) { - // Severe undershoot and between auto and user cq level - force_recode = 1; - cpi->rc.active_best_quality = cpi->oxcf.cq_level; } } } - return force_recode; } @@ -2639,7 +2618,7 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) { if (cpi->twopass.total_left_stats.coded_error != 0.0) fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %10d" - "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f" + "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f" "%6d %6d %5d %5d %5d %8.2f %10d %10.3f" "%10.3f %8d %10d %10d %10d\n", cpi->common.current_video_frame, cpi->rc.this_frame_target, @@ -2650,7 +2629,6 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) { (int)cpi->rc.total_actual_bits, cm->base_qindex, vp9_convert_qindex_to_q(cm->base_qindex), (double)vp9_dc_quant(cm->base_qindex, 0) / 4.0, - vp9_convert_qindex_to_q(cpi->rc.active_best_quality), vp9_convert_qindex_to_q(cpi->rc.active_worst_quality), cpi->rc.avg_q, vp9_convert_qindex_to_q(cpi->rc.ni_av_qi), vp9_convert_qindex_to_q(cpi->cq_target_quality), @@ -2699,6 +2677,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi, int overshoot_seen = 0; int undershoot_seen = 0; int q_low = bottom_index, q_high = top_index; + do { vp9_clear_system_state(); // __asm emms; @@ -2816,11 +2795,13 @@ static void encode_with_recode_loop(VP9_COMP *cpi, // Update rate_correction_factor unless vp9_rc_update_rate_correction_factors(cpi, 0); - *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target); + *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target, + bottom_index, top_index); while (*q < q_low && retries < 10) { vp9_rc_update_rate_correction_factors(cpi, 0); - *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target); + *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target, + bottom_index, top_index); retries++; } } @@ -2831,18 +2812,12 @@ static void encode_with_recode_loop(VP9_COMP *cpi, q_high = *q > q_low ? *q - 1 : q_low; if (overshoot_seen || loop_count > 1) { - // Update rate_correction_factor unless - // cpi->rc.active_worst_quality has changed. vp9_rc_update_rate_correction_factors(cpi, 1); - *q = (q_high + q_low) / 2; } else { - // Update rate_correction_factor unless - // cpi->rc.active_worst_quality has changed. vp9_rc_update_rate_correction_factors(cpi, 0); - - *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target); - + *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target, + bottom_index, top_index); // Special case reset for qlow for constrained quality. // This should only trigger where there is very substantial // undershoot on a frame and the auto cq level is above @@ -2854,7 +2829,8 @@ static void encode_with_recode_loop(VP9_COMP *cpi, while (*q > q_high && retries < 10) { vp9_rc_update_rate_correction_factors(cpi, 0); - *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target); + *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target, + bottom_index, top_index); retries++; } } @@ -2893,8 +2869,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, int q; int frame_over_shoot_limit; int frame_under_shoot_limit; - int top_index; + int top_index_prop; int bottom_index; SPEED_FEATURES *const sf = &cpi->sf; @@ -3008,45 +2984,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, vp9_clear_system_state(); - // Decide how big to make the frame. - vp9_rc_pick_frame_size_and_bounds(cpi, - &frame_under_shoot_limit, - &frame_over_shoot_limit); - - q = vp9_rc_pick_q_and_adjust_q_bounds(cpi, - &bottom_index, - &top_index); - -#if CONFIG_MULTIPLE_ARF - // Force the quantizer determined by the coding order pattern. - if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) && - cpi->oxcf.end_usage != USAGE_CONSTANT_QUALITY) { - double new_q; - double current_q = vp9_convert_qindex_to_q(cpi->rc.active_worst_quality); - int level = cpi->this_frame_weight; - assert(level >= 0); - - // Set quantizer steps at 10% increments. - new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level))); - q = cpi->rc.active_worst_quality + - vp9_compute_qdelta(cpi, current_q, new_q); - - bottom_index = q; - top_index = q; - - printf("frame:%d q:%d\n", cm->current_video_frame, q); - } -#endif - vp9_zero(cpi->rd_tx_select_threshes); - if (!frame_is_intra_only(cm)) { - cm->mcomp_filter_type = DEFAULT_INTERP_FILTER; - /* TODO: Decide this more intelligently */ - cm->allow_high_precision_mv = q < HIGH_PRECISION_MV_QTHRESH; - set_mvcost(cpi); - } - #if CONFIG_VP9_POSTPROC if (cpi->oxcf.noise_sensitivity > 0) { int l = 0; @@ -3076,6 +3015,26 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, vp9_write_yuv_frame(cpi->Source); #endif + // Decide how big to make the frame. + vp9_rc_pick_frame_size_target(cpi); + + // Decide frame size bounds + vp9_rc_compute_frame_size_bounds(cpi, cpi->rc.this_frame_target, + &frame_under_shoot_limit, + &frame_over_shoot_limit); + + // Decide q and q bounds + q = vp9_rc_pick_q_and_adjust_q_bounds(cpi, + &bottom_index, + &top_index, + &top_index_prop); + + if (!frame_is_intra_only(cm)) { + cm->mcomp_filter_type = DEFAULT_INTERP_FILTER; + /* TODO: Decide this more intelligently */ + set_high_precision_mv(cpi, (q < HIGH_PRECISION_MV_QTHRESH)); + } + encode_with_recode_loop(cpi, size, dest, @@ -3161,7 +3120,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, * needed in motion search besides loopfilter */ cm->last_frame_type = cm->frame_type; - vp9_rc_postencode_update(cpi, *size, q); + vp9_rc_postencode_update(cpi, *size, top_index_prop); #if 0 output_frame_level_debug_stats(cpi); @@ -3282,6 +3241,21 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1; } +static void Pass0Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest, + unsigned int *frame_flags) { + encode_frame_to_data_rate(cpi, size, dest, frame_flags); +} + +static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest, + unsigned int *frame_flags) { + (void) size; + (void) dest; + (void) frame_flags; + + vp9_set_quantizer(cpi, find_fp_qindex()); + vp9_first_pass(cpi); +} + static void Pass2Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags) { cpi->enable_encode_breakout = 1; @@ -3293,27 +3267,6 @@ static void Pass2Encode(VP9_COMP *cpi, unsigned long *size, // vp9_print_modes_and_motion_vectors(&cpi->common, "encode.stt"); vp9_twopass_postencode_update(cpi, *size); - - /* -#ifdef DISABLE_RC_LONG_TERM_MEM - cpi->twopass.bits_left -= cpi->rc.this_frame_target; -#else - cpi->twopass.bits_left -= 8 * *size; -#endif - - if (!cpi->refresh_alt_ref_frame) { - double lower_bounds_min_rate = FRAME_OVERHEAD_BITS * cpi->oxcf.framerate; - double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth - * cpi->oxcf.two_pass_vbrmin_section - / 100); - - if (two_pass_min_rate < lower_bounds_min_rate) - two_pass_min_rate = lower_bounds_min_rate; - - cpi->twopass.bits_left += (int64_t)(two_pass_min_rate - / cpi->oxcf.framerate); - } - */ } static void check_initial_width(VP9_COMP *cpi, YV12_BUFFER_CONFIG *sd) { @@ -3386,8 +3339,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, cpi->source = NULL; - cpi->common.allow_high_precision_mv = ALTREF_HIGH_PRECISION_MV; - set_mvcost(cpi); + set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV); // Should we code an alternate reference frame. if (cpi->oxcf.play_alternate && cpi->source_alt_ref_pending) { @@ -3627,7 +3579,8 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, } else if (cpi->pass == 2) { Pass2Encode(cpi, size, dest, frame_flags); } else { - encode_frame_to_data_rate(cpi, size, dest, frame_flags); + // One pass encode + Pass0Encode(cpi, size, dest, frame_flags); } if (cm->refresh_frame_context) diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index b8602e0..c631565 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -338,7 +338,7 @@ typedef struct { int worst_quality; int active_worst_quality; int best_quality; - int active_best_quality; + // int active_best_quality; } RATE_CONTROL; typedef struct VP9_COMP { @@ -695,7 +695,7 @@ int vp9_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest); void vp9_alloc_compressor_data(VP9_COMP *cpi); -int vp9_compute_qdelta(VP9_COMP *cpi, double qstart, double qtarget); +int vp9_compute_qdelta(const VP9_COMP *cpi, double qstart, double qtarget); static int get_token_alloc(int mb_rows, int mb_cols) { return mb_rows * mb_cols * (48 * 16 + 4); diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index bf1fc4f..d631b31 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -45,6 +45,10 @@ static int gf_high_motion_minq[QINDEX_RANGE]; static int inter_minq[QINDEX_RANGE]; static int afq_low_motion_minq[QINDEX_RANGE]; static int afq_high_motion_minq[QINDEX_RANGE]; +static int gf_high = 2000; +static int gf_low = 400; +static int kf_high = 5000; +static int kf_low = 400; // Functions to compute the active minq lookup table entries based on a // formulaic approach to facilitate easier adjustment of the Q tables. @@ -84,7 +88,7 @@ void vp9_rc_init_minq_luts(void) { kf_high_motion_minq[i] = calculate_minq_index(maxq, 0.000002, -0.0012, - 0.5, + 0.50, 0.0); gf_low_motion_minq[i] = calculate_minq_index(maxq, @@ -97,11 +101,6 @@ void vp9_rc_init_minq_luts(void) { -0.00125, 0.50, 0.0); - inter_minq[i] = calculate_minq_index(maxq, - 0.00000271, - -0.00113, - 0.75, - 0.0); afq_low_motion_minq[i] = calculate_minq_index(maxq, 0.0000015, -0.0009, @@ -112,6 +111,11 @@ void vp9_rc_init_minq_luts(void) { -0.00125, 0.55, 0.0); + inter_minq[i] = calculate_minq_index(maxq, + 0.00000271, + -0.00113, + 0.75, + 0.0); } } @@ -285,7 +289,6 @@ static void calc_pframe_target_size(VP9_COMP *cpi) { } } - void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) { const int q = cpi->common.base_qindex; int correction_factor = 100; @@ -333,7 +336,6 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) { break; } - // if ( (correction_factor > 102) && (Q < cpi->rc.active_worst_quality) ) if (correction_factor > 102) { // We are not already at the worst allowable quality correction_factor = @@ -367,8 +369,9 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) { } -int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) { - int q = cpi->rc.active_worst_quality; +int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame, + int active_best_quality, int active_worst_quality) { + int q = active_worst_quality; int i; int last_error = INT_MAX; @@ -396,7 +399,7 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) { target_bits_per_mb = (target_bits_per_frame << BPER_MB_NORMBITS) / cpi->common.MBs; - i = cpi->rc.active_best_quality; + i = active_best_quality; do { bits_per_mb_at_this_q = (int)vp9_rc_bits_per_mb(cpi->common.frame_type, i, @@ -412,7 +415,7 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) { } else { last_error = bits_per_mb_at_this_q - target_bits_per_mb; } - } while (++i <= cpi->rc.active_worst_quality); + } while (++i <= active_worst_quality); return q; } @@ -438,14 +441,17 @@ static int get_active_quality(int q, return active_best_quality; } -int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi, +int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi, int *bottom_index, - int *top_index) { - // Set an active best quality and if necessary active worst quality - int q = cpi->rc.active_worst_quality; - VP9_COMMON *const cm = &cpi->common; + int *top_index, + int *top_index_prop) { + const VP9_COMMON *const cm = &cpi->common; + int active_best_quality; + int active_worst_quality = cpi->rc.active_worst_quality; + int q; if (frame_is_intra_only(cm)) { + active_best_quality = cpi->rc.best_quality; #if !CONFIG_MULTIPLE_ARF // Handle the special case for key frames forced when we have75 reached // the maximum key frame interval. Here force the Q to a range @@ -457,25 +463,19 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi, delta_qindex = vp9_compute_qdelta(cpi, last_boosted_q, (last_boosted_q * 0.75)); - - cpi->rc.active_best_quality = MAX(qindex + delta_qindex, - cpi->rc.best_quality); - } else if (cpi->pass == 0 && cpi->common.current_video_frame == 0) { - // If this is the first (key) frame in 1-pass, active best/worst is - // the user best/worst-allowed, and leave the top_index to active_worst. - cpi->rc.active_best_quality = cpi->oxcf.best_allowed_q; - cpi->rc.active_worst_quality = cpi->oxcf.worst_allowed_q; - } else { - int high = 5000; - int low = 400; + active_best_quality = MAX(qindex + delta_qindex, + cpi->rc.best_quality); + } else if (!(cpi->pass == 0 && cpi->common.current_video_frame == 0)) { + // not first frame of one pass double q_adj_factor = 1.0; double q_val; // Baseline value derived from cpi->active_worst_quality and kf boost - cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.kf_boost, - low, high, - kf_low_motion_minq, - kf_high_motion_minq); + active_best_quality = get_active_quality(active_worst_quality, + cpi->rc.kf_boost, + kf_low, kf_high, + kf_low_motion_minq, + kf_high_motion_minq); // Allow somewhat lower kf minq with small image formats. if ((cm->width * cm->height) <= (352 * 288)) { @@ -487,124 +487,128 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi, // Convert the adjustment factor to a qindex delta // on active_best_quality. - q_val = vp9_convert_qindex_to_q(cpi->rc.active_best_quality); - cpi->rc.active_best_quality += + q_val = vp9_convert_qindex_to_q(active_best_quality); + active_best_quality += vp9_compute_qdelta(cpi, q_val, (q_val * q_adj_factor)); } #else double current_q; // Force the KF quantizer to be 30% of the active_worst_quality. - current_q = vp9_convert_qindex_to_q(cpi->rc.active_worst_quality); - cpi->rc.active_best_quality = cpi->rc.active_worst_quality + current_q = vp9_convert_qindex_to_q(active_worst_quality); + active_best_quality = active_worst_quality + vp9_compute_qdelta(cpi, current_q, current_q * 0.3); #endif } else if (!cpi->is_src_frame_alt_ref && (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) { - int high = 2000; - int low = 400; - // Use the lower of cpi->rc.active_worst_quality and recent + // Use the lower of active_worst_quality and recent // average Q as basis for GF/ARF best Q limit unless last frame was // a key frame. if (cpi->frames_since_key > 1 && - cpi->rc.avg_frame_qindex < cpi->rc.active_worst_quality) { + cpi->rc.avg_frame_qindex < active_worst_quality) { q = cpi->rc.avg_frame_qindex; + } else { + q = active_worst_quality; } // For constrained quality dont allow Q less than the cq level if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) { if (q < cpi->cq_target_quality) q = cpi->cq_target_quality; if (cpi->frames_since_key > 1) { - cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost, - low, high, - afq_low_motion_minq, - afq_high_motion_minq); + active_best_quality = get_active_quality(q, cpi->rc.gfu_boost, + gf_low, gf_high, + afq_low_motion_minq, + afq_high_motion_minq); } else { - cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost, - low, high, - gf_low_motion_minq, - gf_high_motion_minq); + active_best_quality = get_active_quality(q, cpi->rc.gfu_boost, + gf_low, gf_high, + gf_low_motion_minq, + gf_high_motion_minq); } // Constrained quality use slightly lower active best. - cpi->rc.active_best_quality = cpi->rc.active_best_quality * 15 / 16; + active_best_quality = active_best_quality * 15 / 16; } else if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) { if (!cpi->refresh_alt_ref_frame) { - cpi->rc.active_best_quality = cpi->cq_target_quality; + active_best_quality = cpi->cq_target_quality; } else { if (cpi->frames_since_key > 1) { - cpi->rc.active_best_quality = get_active_quality( - q, cpi->rc.gfu_boost, low, high, + active_best_quality = get_active_quality( + q, cpi->rc.gfu_boost, gf_low, gf_high, afq_low_motion_minq, afq_high_motion_minq); } else { - cpi->rc.active_best_quality = get_active_quality( - q, cpi->rc.gfu_boost, low, high, + active_best_quality = get_active_quality( + q, cpi->rc.gfu_boost, gf_low, gf_high, gf_low_motion_minq, gf_high_motion_minq); } } } else { - cpi->rc.active_best_quality = get_active_quality( - q, cpi->rc.gfu_boost, low, high, - gf_low_motion_minq, gf_high_motion_minq); + active_best_quality = get_active_quality( + q, cpi->rc.gfu_boost, gf_low, gf_high, + gf_low_motion_minq, gf_high_motion_minq); } } else { if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) { - cpi->rc.active_best_quality = cpi->cq_target_quality; + active_best_quality = cpi->cq_target_quality; } else { - cpi->rc.active_best_quality = inter_minq[q]; - // 1-pass: for now, use the average Q for the active_best, if its lower - // than active_worst. - if (cpi->pass == 0 && (cpi->rc.avg_frame_qindex < q)) - cpi->rc.active_best_quality = inter_minq[cpi->rc.avg_frame_qindex]; + if (cpi->pass == 0 && + cpi->rc.avg_frame_qindex < active_worst_quality) + // 1-pass: for now, use the average Q for the active_best, if its lower + // than active_worst. + active_best_quality = inter_minq[cpi->rc.avg_frame_qindex]; + else + active_best_quality = inter_minq[active_worst_quality]; // For the constrained quality mode we don't want // q to fall below the cq level. if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) && - (cpi->rc.active_best_quality < cpi->cq_target_quality)) { + (active_best_quality < cpi->cq_target_quality)) { // If we are strongly undershooting the target rate in the last // frames then use the user passed in cq value not the auto // cq value. if (cpi->rc.rolling_actual_bits < cpi->rc.min_frame_bandwidth) - cpi->rc.active_best_quality = cpi->oxcf.cq_level; + active_best_quality = cpi->oxcf.cq_level; else - cpi->rc.active_best_quality = cpi->cq_target_quality; + active_best_quality = cpi->cq_target_quality; } } } // Clip the active best and worst quality values to limits - if (cpi->rc.active_worst_quality > cpi->rc.worst_quality) - cpi->rc.active_worst_quality = cpi->rc.worst_quality; + if (active_worst_quality > cpi->rc.worst_quality) + active_worst_quality = cpi->rc.worst_quality; - if (cpi->rc.active_best_quality < cpi->rc.best_quality) - cpi->rc.active_best_quality = cpi->rc.best_quality; + if (active_best_quality < cpi->rc.best_quality) + active_best_quality = cpi->rc.best_quality; - if (cpi->rc.active_best_quality > cpi->rc.worst_quality) - cpi->rc.active_best_quality = cpi->rc.worst_quality; + if (active_best_quality > cpi->rc.worst_quality) + active_best_quality = cpi->rc.worst_quality; - if (cpi->rc.active_worst_quality < cpi->rc.active_best_quality) - cpi->rc.active_worst_quality = cpi->rc.active_best_quality; + if (active_worst_quality < active_best_quality) + active_worst_quality = active_best_quality; - *top_index = cpi->rc.active_worst_quality; - *bottom_index = cpi->rc.active_best_quality; + *top_index_prop = active_worst_quality; + *top_index = active_worst_quality; + *bottom_index = active_best_quality; #if LIMIT_QRANGE_FOR_ALTREF_AND_KEY // Limit Q range for the adaptive loop. if (cm->frame_type == KEY_FRAME && !cpi->this_key_frame_forced) { if (!(cpi->pass == 0 && cpi->common.current_video_frame == 0)) { + *top_index = active_worst_quality; *top_index = - (cpi->rc.active_worst_quality + cpi->rc.active_best_quality * 3) / 4; + (active_worst_quality + active_best_quality * 3) / 4; } } else if (!cpi->is_src_frame_alt_ref && (cpi->oxcf.end_usage != USAGE_STREAM_FROM_SERVER) && (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) { *top_index = - (cpi->rc.active_worst_quality + cpi->rc.active_best_quality) / 2; + (active_worst_quality + active_best_quality) / 2; } #endif if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) { - q = cpi->rc.active_best_quality; + q = active_best_quality; // Special case code to try and match quality with forced key frames } else if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) { q = cpi->rc.last_boosted_qindex; @@ -614,17 +618,35 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi, // 1-pass: for now, use per-frame-bw for target size of frame, scaled // by |x| for key frame. int scale = (cm->frame_type == KEY_FRAME) ? 5 : 1; - q = vp9_rc_regulate_q(cpi, scale * cpi->rc.av_per_frame_bandwidth); + q = vp9_rc_regulate_q(cpi, scale * cpi->rc.av_per_frame_bandwidth, + active_best_quality, active_worst_quality); } else { - q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target); + q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target, + active_best_quality, active_worst_quality); } if (q > *top_index) q = *top_index; } +#if CONFIG_MULTIPLE_ARF + // Force the quantizer determined by the coding order pattern. + if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) && + cpi->oxcf.end_usage != USAGE_CONSTANT_QUALITY) { + double new_q; + double current_q = vp9_convert_qindex_to_q(active_worst_quality); + int level = cpi->this_frame_weight; + assert(level >= 0); + new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level))); + q = active_worst_quality + + vp9_compute_qdelta(cpi, current_q, new_q); + + *bottom_index = q; + *top_index = q; + printf("frame:%d q:%d\n", cm->current_video_frame, q); + } +#endif return q; } - static int estimate_keyframe_frequency(VP9_COMP *cpi) { int i; @@ -680,8 +702,7 @@ static void adjust_key_frame_context(VP9_COMP *cpi) { cpi->rc.key_frame_count++; } - -static void compute_frame_size_bounds(const VP9_COMP *cpi, +void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi, int this_frame_target, int *frame_under_shoot_limit, int *frame_over_shoot_limit) { @@ -720,9 +741,7 @@ static void compute_frame_size_bounds(const VP9_COMP *cpi, } // return of 0 means drop frame -int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi, - int *frame_under_shoot_limit, - int *frame_over_shoot_limit) { +int vp9_rc_pick_frame_size_target(VP9_COMP *cpi) { VP9_COMMON *cm = &cpi->common; if (cm->frame_type == KEY_FRAME) @@ -733,13 +752,11 @@ int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi, // Target rate per SB64 (including partial SB64s. cpi->rc.sb64_target_rate = ((int64_t)cpi->rc.this_frame_target * 64 * 64) / (cpi->common.width * cpi->common.height); - compute_frame_size_bounds(cpi, cpi->rc.this_frame_target, - frame_under_shoot_limit, frame_over_shoot_limit); - return 1; } -void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) { +void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, + int worst_q) { VP9_COMMON *const cm = &cpi->common; // Update rate control heuristics cpi->rc.projected_frame_size = (bytes_used << 3); @@ -750,6 +767,7 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) { cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) ? 2 : 0); cpi->rc.last_q[cm->frame_type] = cm->base_qindex; + cpi->rc.active_worst_quality = worst_q; // Keep record of last boosted (KF/KF/ARF) Q value. // If the current frame is coded at a lower Q then we also update it. @@ -777,11 +795,11 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) { if (cm->frame_type != KEY_FRAME && !cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) { cpi->rc.ni_frames++; - cpi->rc.tot_q += vp9_convert_qindex_to_q(q); + cpi->rc.tot_q += vp9_convert_qindex_to_q(cm->base_qindex); cpi->rc.avg_q = cpi->rc.tot_q / (double)cpi->rc.ni_frames; // Calculate the average Q for normal inter frames (not key or GFU frames). - cpi->rc.ni_tot_qi += q; + cpi->rc.ni_tot_qi += cm->base_qindex; cpi->rc.ni_av_qi = cpi->rc.ni_tot_qi / cpi->rc.ni_frames; } diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index f01d186..063ac8f 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -31,23 +31,29 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var); void vp9_rc_init_minq_luts(void); // return of 0 means drop frame -// Changes rc.this_frame_target and rc.sb64_rate_target -int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi, +// Changes only rc.this_frame_target and rc.sb64_rate_target +int vp9_rc_pick_frame_size_target(VP9_COMP *cpi); + +void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi, + int this_frame_target, int *frame_under_shoot_limit, int *frame_over_shoot_limit); + // Picks q and q bounds given the target for bits -int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi, - int * bottom_index, - int * top_index); +int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi, + int *bottom_index, + int *top_index, + int *top_index_prop); // Estimates q to achieve a target bits per frame -int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame); +int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame, + int active_best_quality, int active_worst_quality); // Post encode update of the rate control parameters based // on bytes used and q used for the frame void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, - int q_used); + int worst_q); // estimates bits per mb for a given qindex and correction factor int vp9_rc_bits_per_mb(FRAME_TYPE frame_type, int qindex, -- 2.7.4