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

resize-refactor: Change resizing process with helpers

Adds three new helpers and changes one other. The intention of this is
to make the triggering and function of resizing simpler. The new process
is to resize to the next state and then update the current state to
match. The new helpers reflect this change and make the overall flow
simpler.

resize_pending is now a helper instead of a member, so it doesn't need
to be raised manually. A resize is pending when the numerator or
denominator of the next resize state is different from the current one.
resize_pending could be 1 (scale down), 0 (no change), or -1 (return to
original resolution if 1-pass CBR), but now it can only be 1 or 0. To
return to the original resolution just set the scale to 1:1. This
reduces complexity with no change in functionality.

resize_unscaled just returns 1 if the current numerator and denominator
are equal. This makes some if conditions cleaner.

resize_step makes the current scale equal to the next scale. This
signifies that a resize is complete and will cause resize_pending to be
false until the next state is changed. This is the end of the new
resizing procedure.

av1_calculate_coded_size has been changed to calculate the next size
instead of the current size. The current state can't be updated until
the resize is complete because if it were, the resize_pending state
would drop and the resize wouldn't finish. This just means the next
resolution is the target resolution until the resize is complete.

Change-Id: I5d5855cc83f532d3a8b1f8853ba70a0d43221fbf
parent e13a11f3
......@@ -353,8 +353,8 @@ void av1_cyclic_refresh_check_golden_update(AV1_COMP *const cpi) {
// frame because of the camera movement, set this frame as the golden frame.
// Use 70% and 5% as the thresholds for golden frame refreshing.
// Also, force this frame as a golden update frame if this frame will change
// the resolution (resize_pending != 0).
if (cpi->resize_pending != 0 ||
// the resolution (av1_resize_pending != 0).
if (av1_resize_pending(cpi) ||
(cnt1 * 10 > (70 * rows * cols) && cnt2 * 20 < cnt1)) {
av1_cyclic_refresh_set_golden_update(cpi);
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
......
......@@ -2159,7 +2159,6 @@ 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;
......@@ -3862,11 +3861,13 @@ static void set_frame_size(AV1_COMP *cpi) {
AV1EncoderConfig *const oxcf = &cpi->oxcf;
MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
// TODO(afergs): Allow fixed resizing in AOM_CBR mode?
if (oxcf->pass == 2 && oxcf->rc_mode == AOM_VBR &&
((oxcf->resize_mode == RESIZE_FIXED && cm->current_video_frame == 0) ||
(oxcf->resize_mode == RESIZE_DYNAMIC && cpi->resize_pending))) {
av1_calculate_coded_size(cpi, &oxcf->scaled_frame_width,
&oxcf->scaled_frame_height);
(oxcf->resize_mode == RESIZE_DYNAMIC && av1_resize_pending(cpi)))) {
av1_calculate_next_coded_size(cpi, &oxcf->scaled_frame_width,
&oxcf->scaled_frame_height);
// There has been a change in frame size.
av1_set_size_literal(cpi, oxcf->scaled_frame_width,
......@@ -3874,25 +3875,16 @@ static void set_frame_size(AV1_COMP *cpi) {
}
if (oxcf->pass == 0 && oxcf->rc_mode == AOM_CBR &&
oxcf->resize_mode == RESIZE_DYNAMIC) {
if (cpi->resize_pending == 1) {
oxcf->scaled_frame_width =
(cm->width * cpi->resize_scale_num) / cpi->resize_scale_den;
oxcf->scaled_frame_height =
(cm->height * cpi->resize_scale_num) / cpi->resize_scale_den;
} else if (cpi->resize_pending == -1) {
// Go back up to original size.
oxcf->scaled_frame_width = oxcf->width;
oxcf->scaled_frame_height = oxcf->height;
}
if (cpi->resize_pending != 0) {
// There has been a change in frame size.
av1_set_size_literal(cpi, oxcf->scaled_frame_width,
oxcf->scaled_frame_height);
oxcf->resize_mode == RESIZE_DYNAMIC && av1_resize_pending(cpi)) {
av1_calculate_next_coded_size(cpi, &oxcf->scaled_frame_width,
&oxcf->scaled_frame_height);
// TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed.
set_mv_search_params(cpi);
}
// There has been a change in frame size.
av1_set_size_literal(cpi, oxcf->scaled_frame_width,
oxcf->scaled_frame_height);
// TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed.
set_mv_search_params(cpi);
}
#if !CONFIG_XIPHRC
......@@ -3991,6 +3983,8 @@ static void encode_without_recode_loop(AV1_COMP *cpi) {
set_frame_size(cpi);
av1_resize_step(cpi);
// For 1 pass CBR under dynamic resize mode: use faster scaling for source.
// Only for 2x2 scaling for now.
if (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == AOM_CBR &&
......@@ -4079,7 +4073,7 @@ static void encode_with_recode_loop(AV1_COMP *cpi, size_t *size,
set_frame_size(cpi);
if (loop_count == 0 || cpi->resize_pending != 0) {
if (loop_count == 0 || av1_resize_pending(cpi)) {
set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
// cpi->sf.use_upsampled_references can be different from frame to frame.
......@@ -4100,8 +4094,8 @@ static void encode_with_recode_loop(AV1_COMP *cpi, size_t *size,
undershoot_seen = 0;
#endif
// Reconfiguration for change in frame size has concluded.
cpi->resize_pending = 0;
// Advance resize to next state now that updates are done
av1_resize_step(cpi);
q_low = bottom_index;
q_high = top_index;
......@@ -4240,7 +4234,7 @@ static void encode_with_recode_loop(AV1_COMP *cpi, size_t *size,
#if !CONFIG_XIPHRC
int retries = 0;
// TODO(afergs): Replace removed recode when resize_pending is true
// TODO(afergs): Replace removed recode when av1_resize_pending is true
// Frame size out of permitted range:
// Update correction factor & compute new Q to try...
......
......@@ -613,7 +613,6 @@ typedef struct AV1_COMP {
TileBufferEnc tile_buffers[MAX_TILE_ROWS][MAX_TILE_COLS];
int resize_pending;
int resize_state;
int resize_scale_num;
int resize_scale_den;
......@@ -860,6 +859,25 @@ static INLINE void uref_cnt_fb(EncRefCntBuffer *ubufs, int *uidx,
ubufs[new_uidx].ref_count++;
}
// Returns 1 if a resize is pending and 0 otherwise.
static INLINE int av1_resize_pending(const struct AV1_COMP *cpi) {
return cpi->resize_scale_num != cpi->resize_next_scale_num ||
cpi->resize_scale_den != cpi->resize_next_scale_den;
}
// Returns 1 if a frame is unscaled and 0 otherwise.
static INLINE int av1_resize_unscaled(const struct AV1_COMP *cpi) {
return cpi->resize_scale_num == cpi->resize_scale_den;
}
// Moves resizing to the next state. This is just setting the numerator and
// denominator to the next numerator and denominator, causing
// av1_resize_pending to subsequently return false.
static INLINE void av1_resize_step(struct AV1_COMP *cpi) {
cpi->resize_scale_num = cpi->resize_next_scale_num;
cpi->resize_scale_den = cpi->resize_next_scale_den;
}
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -1235,12 +1235,12 @@ static void setup_rf_level_maxq(AV1_COMP *cpi) {
}
}
void av1_calculate_coded_size(const AV1_COMP *cpi, int *scaled_frame_width,
int *scaled_frame_height) {
void av1_calculate_next_coded_size(const AV1_COMP *cpi, int *scaled_frame_width,
int *scaled_frame_height) {
*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;
cpi->oxcf.width * cpi->resize_next_scale_num / cpi->resize_next_scale_den;
*scaled_frame_height = cpi->oxcf.height * cpi->resize_next_scale_num /
cpi->resize_next_scale_den;
}
void av1_init_second_pass(AV1_COMP *cpi) {
......
......@@ -177,9 +177,9 @@ 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_calculate_coded_size(const struct AV1_COMP *cpi,
int *scaled_frame_width,
int *scaled_frame_height);
void av1_calculate_next_coded_size(const struct AV1_COMP *cpi,
int *scaled_frame_width,
int *scaled_frame_height);
#if CONFIG_EXT_REFS
static INLINE int get_number_of_extra_arfs(int interval, int arf_pending) {
......
......@@ -1081,8 +1081,7 @@ 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 (cpi->resize_scale_num != cpi->resize_scale_den &&
!frame_is_kf_gf_arf(cpi)) {
if (!av1_resize_unscaled(cpi) && !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 =
......@@ -1164,9 +1163,8 @@ void av1_rc_set_frame_target(AV1_COMP *cpi, int target) {
rc->this_frame_target = target;
// Modify frame size target when down-scaling.
if (cpi->oxcf.resize_mode == RESIZE_DYNAMIC &&
cpi->resize_scale_num != cpi->resize_scale_den)
// Modify frame size target when down-scaled.
if (cpi->oxcf.resize_mode == RESIZE_DYNAMIC && !av1_resize_unscaled(cpi))
rc->this_frame_target =
(int)(rc->this_frame_target * av1_resize_rate_factor(cpi));
......@@ -1231,7 +1229,6 @@ static void update_golden_frame_stats(AV1_COMP *cpi) {
void av1_rc_postencode_update(AV1_COMP *cpi, uint64_t bytes_used) {
const AV1_COMMON *const cm = &cpi->common;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
const int qindex = cm->base_qindex;
......@@ -1323,15 +1320,6 @@ void av1_rc_postencode_update(AV1_COMP *cpi, uint64_t bytes_used) {
rc->frames_since_key++;
rc->frames_to_key--;
}
// Trigger the resizing of the next frame if it is scaled.
if (oxcf->pass != 0) {
cpi->resize_pending =
(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;
}
}
void av1_rc_postencode_update_drop_frame(AV1_COMP *cpi) {
......
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