Commit ddc846ea authored by Fergus Simpson's avatar Fergus Simpson
Browse files

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
parent 369ca7bc
......@@ -2189,9 +2189,15 @@ AV1_COMP *av1_create_compressor(AV1EncoderConfig *oxcf,
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 @@ static int scale_down(AV1_COMP *cpi, int q) {
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 @@ static void encode_with_recode_loop(AV1_COMP *cpi, size_t *size,
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;
......
......@@ -629,6 +629,8 @@ typedef struct AV1_COMP {
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;
......
......@@ -1235,27 +1235,12 @@ static void setup_rf_level_maxq(AV1_COMP *cpi) {
}
}
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 @@ void av1_init_second_pass(AV1_COMP *cpi) {
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 @@ static void define_gf_group(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) {
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 @@ static void find_next_key_frame(AV1_COMP *cpi, FIRSTPASS_STATS *this_frame) {
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;
}
}
......
......@@ -177,9 +177,8 @@ void av1_twopass_postencode_update(struct AV1_COMP *cpi);
// 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
......
......@@ -93,6 +93,11 @@ static int gf_low = 400;
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 @@ static double get_rate_correction_factor(const AV1_COMP *cpi) {
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 @@ static void set_rate_correction_factor(AV1_COMP *cpi, double factor) {
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 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int *bottom_index,
}
// 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 @@ void av1_rc_set_frame_target(AV1_COMP *cpi, int target) {
// 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 @@ void av1_rc_postencode_update(AV1_COMP *cpi, uint64_t bytes_used) {
// 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;
}
}
......
......@@ -49,27 +49,6 @@ typedef enum {
} 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 @@ typedef struct {
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 @@ int av1_rc_get_default_max_gf_interval(double framerate, int min_frame_rate);
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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment