resize-refactor: Refactor 2-pass VBR resizing Replaces resizing's table and index approach to frame sizes with numerator and denominator integers in the AV1_COMP struct. This approach is more flexible and will be simpler going forward as it is much more similar to the 1-pass CBR approach that is also being refactored. The intention is to merge both approaches and this is the first step toward that. Change-Id: I5733c0687390f8a8e2790dcddfa09fb08ab88376
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 35f9f20..c623bdc 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -2189,9 +2189,15 @@ memset(cm->fc, 0, sizeof(*cm->fc)); memset(cm->frame_contexts, 0, FRAME_CONTEXTS * sizeof(*cm->frame_contexts)); + cpi->resize_pending = 0; cpi->resize_state = 0; cpi->resize_avg_qp = 0; cpi->resize_buffer_underflow = 0; + cpi->resize_scale_num = 16; + cpi->resize_scale_den = 16; + cpi->resize_next_scale_num = 16; + cpi->resize_next_scale_den = 16; + cpi->common.buffer_pool = pool; init_config(cpi, oxcf); @@ -3047,11 +3053,18 @@ int scale = 0; assert(frame_is_kf_gf_arf(cpi)); - if (rc->frame_size_selector == UNSCALED && + if (cpi->resize_scale_num == cpi->resize_scale_den && q >= rc->rf_level_maxq[gf_group->rf_level[gf_group->index]]) { + const int old_num = cpi->resize_scale_num; + --cpi->resize_scale_num; + if (cpi->resize_scale_num <= 0) { + cpi->resize_scale_num = old_num; + return 0; + } const int max_size_thresh = - (int)(rate_thresh_mult[SCALE_STEP1] * + (int)(av1_resize_rate_factor(cpi) * AOMMAX(rc->this_frame_target, rc->avg_frame_bandwidth)); + cpi->resize_scale_num = old_num; scale = rc->projected_frame_size > max_size_thresh ? 1 : 0; } return scale; @@ -4332,9 +4345,13 @@ if (cpi->resize_pending == 1) { // Change in frame size so go back around the recode loop. - cpi->rc.frame_size_selector = - SCALE_STEP1 - cpi->rc.frame_size_selector; - cpi->rc.next_frame_size_selector = cpi->rc.frame_size_selector; + // 11/16 is close to the old 2/3, then goes back to 16/16. + cpi->resize_scale_num -= 5; + if (cpi->resize_scale_num < 8 || cpi->resize_scale_num > 16) + cpi->resize_scale_num = 16; + cpi->resize_scale_den = 16; + cpi->resize_next_scale_num = cpi->resize_scale_num; + cpi->resize_next_scale_den = cpi->resize_scale_den; #if CONFIG_INTERNAL_STATS ++cpi->tot_recode_hits;
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index 4e7aef8..68808a7 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h
@@ -629,6 +629,8 @@ int resize_state; int resize_scale_num; int resize_scale_den; + int resize_next_scale_num; + int resize_next_scale_den; int resize_avg_qp; int resize_buffer_underflow; int resize_count;
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c index e35a54e..109de34 100644 --- a/av1/encoder/firstpass.c +++ b/av1/encoder/firstpass.c
@@ -1235,27 +1235,12 @@ } } -void av1_init_subsampling(AV1_COMP *cpi) { - const AV1_COMMON *const cm = &cpi->common; - RATE_CONTROL *const rc = &cpi->rc; - const int w = cm->width; - const int h = cm->height; - int i; - - for (i = 0; i < FRAME_SCALE_STEPS; ++i) { - // Note: Frames with odd-sized dimensions may result from this scaling. - rc->frame_width[i] = (w * 16) / frame_scale_factor[i]; - rc->frame_height[i] = (h * 16) / frame_scale_factor[i]; - } - - setup_rf_level_maxq(cpi); -} - -void av1_calculate_coded_size(AV1_COMP *cpi, int *scaled_frame_width, +void av1_calculate_coded_size(const AV1_COMP *cpi, int *scaled_frame_width, int *scaled_frame_height) { - RATE_CONTROL *const rc = &cpi->rc; - *scaled_frame_width = rc->frame_width[rc->frame_size_selector]; - *scaled_frame_height = rc->frame_height[rc->frame_size_selector]; + *scaled_frame_width = + cpi->oxcf.width * cpi->resize_scale_num / cpi->resize_scale_den; + *scaled_frame_height = + cpi->oxcf.height * cpi->resize_scale_num / cpi->resize_scale_den; } void av1_init_second_pass(AV1_COMP *cpi) { @@ -1316,7 +1301,7 @@ twopass->last_kfgroup_zeromotion_pct = 100; if (oxcf->resize_mode != RESIZE_NONE) { - av1_init_subsampling(cpi); + setup_rf_level_maxq(cpi); } } @@ -2300,7 +2285,8 @@ if (oxcf->resize_mode == RESIZE_DYNAMIC) { // Default to starting GF groups at normal frame size. - cpi->rc.next_frame_size_selector = UNSCALED; + // TODO(afergs): Make a function for this + cpi->resize_next_scale_num = cpi->resize_next_scale_den; } } @@ -2646,7 +2632,8 @@ if (oxcf->resize_mode == RESIZE_DYNAMIC) { // Default to normal-sized frame on keyframes. - cpi->rc.next_frame_size_selector = UNSCALED; + // TODO(afergs): Make a function for this + cpi->resize_next_scale_num = cpi->resize_next_scale_den; } }
diff --git a/av1/encoder/firstpass.h b/av1/encoder/firstpass.h index db459cc..cb893d4 100644 --- a/av1/encoder/firstpass.h +++ b/av1/encoder/firstpass.h
@@ -177,9 +177,8 @@ // Post encode update of the rate control parameters for 2-pass void av1_twopass_postencode_update(struct AV1_COMP *cpi); -void av1_init_subsampling(struct AV1_COMP *cpi); - -void av1_calculate_coded_size(struct AV1_COMP *cpi, int *scaled_frame_width, +void av1_calculate_coded_size(const struct AV1_COMP *cpi, + int *scaled_frame_width, int *scaled_frame_height); #if CONFIG_EXT_REFS
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c index 1f2ea36..8500b83 100644 --- a/av1/encoder/ratectrl.c +++ b/av1/encoder/ratectrl.c
@@ -93,6 +93,11 @@ static int kf_high = 5000; static int kf_low = 400; +double av1_resize_rate_factor(const AV1_COMP *cpi) { + return (double)(cpi->resize_scale_den * cpi->resize_scale_den) / + (cpi->resize_scale_num * cpi->resize_scale_num); +} + // Functions to compute the active minq lookup table entries based on a // formulaic approach to facilitate easier adjustment of the Q tables. // The formulae were derived from computing a 3rd order polynomial best @@ -384,7 +389,7 @@ else rcf = rc->rate_correction_factors[INTER_NORMAL]; } - rcf *= rcf_mult[rc->frame_size_selector]; + rcf *= av1_resize_rate_factor(cpi); return fclamp(rcf, MIN_BPB_FACTOR, MAX_BPB_FACTOR); } @@ -392,7 +397,7 @@ RATE_CONTROL *const rc = &cpi->rc; // Normalize RCF to account for the size-dependent scaling factor. - factor /= rcf_mult[cpi->rc.frame_size_selector]; + factor /= av1_resize_rate_factor(cpi); factor = fclamp(factor, MIN_BPB_FACTOR, MAX_BPB_FACTOR); @@ -1076,7 +1081,8 @@ } // Modify active_best_quality for downscaled normal frames. - if (rc->frame_size_selector != UNSCALED && !frame_is_kf_gf_arf(cpi)) { + if (cpi->resize_scale_num != cpi->resize_scale_den && + !frame_is_kf_gf_arf(cpi)) { int qdelta = av1_compute_qdelta_by_rate( rc, cm->frame_type, active_best_quality, 2.0, cm->bit_depth); active_best_quality = @@ -1160,9 +1166,9 @@ // Modify frame size target when down-scaling. if (cpi->oxcf.resize_mode == RESIZE_DYNAMIC && - rc->frame_size_selector != UNSCALED) - rc->this_frame_target = (int)(rc->this_frame_target * - rate_thresh_mult[rc->frame_size_selector]); + cpi->resize_scale_num != cpi->resize_scale_den) + rc->this_frame_target = + (int)(rc->this_frame_target * av1_resize_rate_factor(cpi)); // Target rate per SB64 (including partial SB64s. rc->sb64_target_rate = (int)((int64_t)rc->this_frame_target * 64 * 64) / @@ -1321,8 +1327,10 @@ // Trigger the resizing of the next frame if it is scaled. if (oxcf->pass != 0) { cpi->resize_pending = - rc->next_frame_size_selector != rc->frame_size_selector; - rc->frame_size_selector = rc->next_frame_size_selector; + (cpi->resize_next_scale_num != cpi->resize_scale_num || + cpi->resize_next_scale_den != cpi->resize_scale_den); + cpi->resize_scale_num = cpi->resize_next_scale_num; + cpi->resize_scale_den = cpi->resize_next_scale_den; } }
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h index 93a9b49..61bb0c2 100644 --- a/av1/encoder/ratectrl.h +++ b/av1/encoder/ratectrl.h
@@ -49,27 +49,6 @@ } RATE_FACTOR_LEVEL; #endif // CONFIG_EXT_REFS -// Internal frame scaling level. -typedef enum { - UNSCALED = 0, // Frame is unscaled. - SCALE_STEP1 = 1, // First-level down-scaling. - FRAME_SCALE_STEPS -} FRAME_SCALE_LEVEL; - -// Frame dimensions multiplier wrt the native frame size, in 1/16ths, -// specified for the scale-up case. -// e.g. 24 => 16/24 = 2/3 of native size. The restriction to 1/16th is -// intended to match the capabilities of the normative scaling filters, -// giving precedence to the up-scaling accuracy. -static const int frame_scale_factor[FRAME_SCALE_STEPS] = { 16, 24 }; - -// Multiplier of the target rate to be used as threshold for triggering scaling. -static const double rate_thresh_mult[FRAME_SCALE_STEPS] = { 1.0, 2.0 }; - -// Scale dependent Rate Correction Factor multipliers. Compensates for the -// greater number of bits per pixel generated in down-scaled frames. -static const double rcf_mult[FRAME_SCALE_STEPS] = { 1.0, 2.0 }; - typedef struct { // Rate targetting variables int base_frame_target; // A baseline frame target before adjustment @@ -162,10 +141,6 @@ int q_2_frame; // Auto frame-scaling variables. - FRAME_SCALE_LEVEL frame_size_selector; - FRAME_SCALE_LEVEL next_frame_size_selector; - int frame_width[FRAME_SCALE_STEPS]; - int frame_height[FRAME_SCALE_STEPS]; int rf_level_maxq[RATE_FACTOR_LEVELS]; } RATE_CONTROL; @@ -214,6 +189,10 @@ void av1_rc_get_one_pass_vbr_params(struct AV1_COMP *cpi); void av1_rc_get_one_pass_cbr_params(struct AV1_COMP *cpi); +// How many times less pixels there are to encode given the current scaling. +// Temporary replacement for rcf_mult and rate_thresh_mult. +double av1_resize_rate_factor(const struct AV1_COMP *cpi); + // Post encode update of the rate control parameters based // on bytes used void av1_rc_postencode_update(struct AV1_COMP *cpi, uint64_t bytes_used);