From de71d1429f9135006a5c1500a74ec2e3059bfd24 Mon Sep 17 00:00:00 2001 From: Urvang Joshi <urvang@google.com> Date: Thu, 5 Oct 2017 12:12:15 -0700 Subject: [PATCH] FRAME_SUPERRES: Rework to use scale factor of 8/D Earlier, the superres scale was in the form of: N/16, where N ranged from 8 to 16. We change this to the form: 8/D, where D ranges from 8 to 16. This helps on the decoder side, by making it possible to work on 8x8 blocks at a time. Change-Id: I6c72d4b3e8d1c830e61d4bb8d7f6337a100c3064 --- aom/aom_encoder.h | 32 ++++----- aomenc.c | 50 +++++++------- av1/av1_cx_iface.c | 51 +++++++------- av1/common/enums.h | 2 +- av1/common/onyxc_int.h | 4 +- av1/common/resize.c | 18 +++-- av1/common/resize.h | 10 +-- av1/common/restoration.c | 4 +- av1/common/scale.h | 2 +- av1/decoder/decodeframe.c | 8 +-- av1/encoder/bitstream.c | 4 +- av1/encoder/encoder.c | 136 +++++++++++++++++++++----------------- av1/encoder/encoder.h | 8 +-- av1/encoder/pickrst.c | 4 +- av1/encoder/ratectrl.h | 2 +- 15 files changed, 173 insertions(+), 162 deletions(-) diff --git a/aom/aom_encoder.h b/aom/aom_encoder.h index c8fe99654c..208ba011fa 100644 --- a/aom/aom_encoder.h +++ b/aom/aom_encoder.h @@ -372,21 +372,21 @@ typedef struct aom_codec_enc_cfg { */ unsigned int rc_resize_mode; - /*!\brief Frame resize numerator. + /*!\brief Frame resize denominator. * - * The numerator for resize to use, assuming 16 as the denominator. + * The denominator for resize to use, assuming 8 as the numerator. * - * Valid numerators are 8 - 16 for now. + * Valid denominators are 8 - 16 for now. */ - unsigned int rc_resize_numerator; + unsigned int rc_resize_denominator; - /*!\brief Keyframe resize numerator. + /*!\brief Keyframe resize denominator. * - * The numerator for resize to use, assuming 16 as the denominator. + * The denominator for resize to use, assuming 8 as the numerator. * - * Valid numerators are 8 - 16 for now. + * Valid denominators are 8 - 16 for now. */ - unsigned int rc_resize_kf_numerator; + unsigned int rc_resize_kf_denominator; /*!\brief Frame super-resolution scaling mode. * @@ -399,27 +399,27 @@ typedef struct aom_codec_enc_cfg { */ unsigned int rc_superres_mode; - /*!\brief Frame super-resolution numerator. + /*!\brief Frame super-resolution denominator. * - * The numerator for superres to use. If fixed it will only change if the + * The denominator for superres to use. If fixed it will only change if the * cumulative scale change over resizing and superres is greater than 1/2; * this forces superres to reduce scaling. * - * Valid numerators are 8 to 16. + * Valid denominators are 8 to 16. * * Used only by SUPERRES_FIXED. */ - unsigned int rc_superres_numerator; + unsigned int rc_superres_denominator; - /*!\brief Keyframe super-resolution numerator. + /*!\brief Keyframe super-resolution denominator. * - * The numerator for superres to use. If fixed it will only change if the + * The denominator for superres to use. If fixed it will only change if the * cumulative scale change over resizing and superres is greater than 1/2; * this forces superres to reduce scaling. * - * Valid numerators are 8 - 16 for now. + * Valid denominators are 8 - 16 for now. */ - unsigned int rc_superres_kf_numerator; + unsigned int rc_superres_kf_denominator; /*!\brief Frame super-resolution q threshold. * diff --git a/aomenc.c b/aomenc.c index 99463a3e37..43ad4bf039 100644 --- a/aomenc.c +++ b/aomenc.c @@ -290,18 +290,18 @@ static const arg_def_t dropframe_thresh = ARG_DEF(NULL, "drop-frame", 1, "Temporal resampling threshold (buf %)"); static const arg_def_t resize_mode = ARG_DEF(NULL, "resize-mode", 1, "Frame resize mode"); -static const arg_def_t resize_numerator = - ARG_DEF(NULL, "resize-numerator", 1, "Frame resize numerator"); -static const arg_def_t resize_kf_numerator = - ARG_DEF(NULL, "resize-kf-numerator", 1, "Frame resize keyframe numerator"); +static const arg_def_t resize_denominator = + ARG_DEF(NULL, "resize-denominator", 1, "Frame resize denominator"); +static const arg_def_t resize_kf_denominator = ARG_DEF( + NULL, "resize-kf-denominator", 1, "Frame resize keyframe denominator"); #if CONFIG_FRAME_SUPERRES static const arg_def_t superres_mode = ARG_DEF(NULL, "superres-mode", 1, "Frame super-resolution mode"); -static const arg_def_t superres_numerator = - ARG_DEF(NULL, "superres-numerator", 1, "Frame super-resolution numerator"); -static const arg_def_t superres_kf_numerator = - ARG_DEF(NULL, "superres-kf-numerator", 1, - "Frame super-resolution keyframe numerator"); +static const arg_def_t superres_denominator = ARG_DEF( + NULL, "superres-denominator", 1, "Frame super-resolution denominator"); +static const arg_def_t superres_kf_denominator = + ARG_DEF(NULL, "superres-kf-denominator", 1, + "Frame super-resolution keyframe denominator"); static const arg_def_t superres_qthresh = ARG_DEF( NULL, "superres-qthresh", 1, "Frame super-resolution qindex threshold"); static const arg_def_t superres_kf_qthresh = @@ -333,12 +333,12 @@ static const arg_def_t buf_optimal_sz = ARG_DEF(NULL, "buf-optimal-sz", 1, "Client optimal buffer size (ms)"); static const arg_def_t *rc_args[] = { &dropframe_thresh, &resize_mode, - &resize_numerator, - &resize_kf_numerator, + &resize_denominator, + &resize_kf_denominator, #if CONFIG_FRAME_SUPERRES &superres_mode, - &superres_numerator, - &superres_kf_numerator, + &superres_denominator, + &superres_kf_denominator, &superres_qthresh, &superres_kf_qthresh, #endif // CONFIG_FRAME_SUPERRES @@ -1057,17 +1057,17 @@ static int parse_stream_params(struct AvxEncoderConfig *global, config->cfg.rc_dropframe_thresh = arg_parse_uint(&arg); } else if (arg_match(&arg, &resize_mode, argi)) { config->cfg.rc_resize_mode = arg_parse_uint(&arg); - } else if (arg_match(&arg, &resize_numerator, argi)) { - config->cfg.rc_resize_numerator = arg_parse_uint(&arg); - } else if (arg_match(&arg, &resize_kf_numerator, argi)) { - config->cfg.rc_resize_kf_numerator = arg_parse_uint(&arg); + } else if (arg_match(&arg, &resize_denominator, argi)) { + config->cfg.rc_resize_denominator = arg_parse_uint(&arg); + } else if (arg_match(&arg, &resize_kf_denominator, argi)) { + config->cfg.rc_resize_kf_denominator = arg_parse_uint(&arg); #if CONFIG_FRAME_SUPERRES } else if (arg_match(&arg, &superres_mode, argi)) { config->cfg.rc_superres_mode = arg_parse_uint(&arg); - } else if (arg_match(&arg, &superres_numerator, argi)) { - config->cfg.rc_superres_numerator = arg_parse_uint(&arg); - } else if (arg_match(&arg, &superres_kf_numerator, argi)) { - config->cfg.rc_superres_kf_numerator = arg_parse_uint(&arg); + } else if (arg_match(&arg, &superres_denominator, argi)) { + config->cfg.rc_superres_denominator = arg_parse_uint(&arg); + } else if (arg_match(&arg, &superres_kf_denominator, argi)) { + config->cfg.rc_superres_kf_denominator = arg_parse_uint(&arg); } else if (arg_match(&arg, &superres_qthresh, argi)) { config->cfg.rc_superres_qthresh = arg_parse_uint(&arg); } else if (arg_match(&arg, &superres_kf_qthresh, argi)) { @@ -1286,12 +1286,12 @@ static void show_stream_config(struct stream_state *stream, #endif // CONFIG_EXT_TILE SHOW(rc_dropframe_thresh); SHOW(rc_resize_mode); - SHOW(rc_resize_numerator); - SHOW(rc_resize_kf_numerator); + SHOW(rc_resize_denominator); + SHOW(rc_resize_kf_denominator); #if CONFIG_FRAME_SUPERRES SHOW(rc_superres_mode); - SHOW(rc_superres_numerator); - SHOW(rc_superres_kf_numerator); + SHOW(rc_superres_denominator); + SHOW(rc_superres_kf_denominator); SHOW(rc_superres_qthresh); SHOW(rc_superres_kf_qthresh); #endif // CONFIG_FRAME_SUPERRES diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c index 457c32c191..2444d32271 100644 --- a/av1/av1_cx_iface.c +++ b/av1/av1_cx_iface.c @@ -251,16 +251,16 @@ static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx, } RANGE_CHECK_HI(cfg, rc_resize_mode, RESIZE_MODES - 1); - RANGE_CHECK(cfg, rc_resize_numerator, SCALE_DENOMINATOR / 2, - SCALE_DENOMINATOR); - RANGE_CHECK(cfg, rc_resize_kf_numerator, SCALE_DENOMINATOR / 2, - SCALE_DENOMINATOR); + RANGE_CHECK(cfg, rc_resize_denominator, SCALE_NUMERATOR, + SCALE_NUMERATOR << 1); + RANGE_CHECK(cfg, rc_resize_kf_denominator, SCALE_NUMERATOR, + SCALE_NUMERATOR << 1); #if CONFIG_FRAME_SUPERRES RANGE_CHECK_HI(cfg, rc_superres_mode, SUPERRES_MODES - 1); - RANGE_CHECK(cfg, rc_superres_numerator, SCALE_DENOMINATOR / 2, - SCALE_DENOMINATOR); - RANGE_CHECK(cfg, rc_superres_kf_numerator, SCALE_DENOMINATOR / 2, - SCALE_DENOMINATOR); + RANGE_CHECK(cfg, rc_superres_denominator, SCALE_NUMERATOR, + SCALE_NUMERATOR << 1); + RANGE_CHECK(cfg, rc_superres_kf_denominator, SCALE_NUMERATOR, + SCALE_NUMERATOR << 1); RANGE_CHECK(cfg, rc_superres_qthresh, 1, 63); RANGE_CHECK(cfg, rc_superres_kf_qthresh, 1, 63); #endif // CONFIG_FRAME_SUPERRES @@ -516,17 +516,18 @@ static aom_codec_err_t set_encoder_config( oxcf->over_shoot_pct = cfg->rc_overshoot_pct; oxcf->resize_mode = (RESIZE_MODE)cfg->rc_resize_mode; - oxcf->resize_scale_numerator = (uint8_t)cfg->rc_resize_numerator; - oxcf->resize_kf_scale_numerator = (uint8_t)cfg->rc_resize_kf_numerator; + oxcf->resize_scale_denominator = (uint8_t)cfg->rc_resize_denominator; + oxcf->resize_kf_scale_denominator = (uint8_t)cfg->rc_resize_kf_denominator; if (oxcf->resize_mode == RESIZE_FIXED && - oxcf->resize_scale_numerator == SCALE_DENOMINATOR && - oxcf->resize_kf_scale_numerator == SCALE_DENOMINATOR) + oxcf->resize_scale_denominator == SCALE_NUMERATOR && + oxcf->resize_kf_scale_denominator == SCALE_NUMERATOR) oxcf->resize_mode = RESIZE_NONE; #if CONFIG_FRAME_SUPERRES oxcf->superres_mode = (SUPERRES_MODE)cfg->rc_superres_mode; - oxcf->superres_scale_numerator = (uint8_t)cfg->rc_superres_numerator; - oxcf->superres_kf_scale_numerator = (uint8_t)cfg->rc_superres_kf_numerator; + oxcf->superres_scale_denominator = (uint8_t)cfg->rc_superres_denominator; + oxcf->superres_kf_scale_denominator = + (uint8_t)cfg->rc_superres_kf_denominator; oxcf->superres_qthresh = extra_cfg->lossless ? 255 : av1_quantizer_to_qindex(cfg->rc_superres_qthresh); @@ -535,8 +536,8 @@ static aom_codec_err_t set_encoder_config( ? 255 : av1_quantizer_to_qindex(cfg->rc_superres_kf_qthresh); if (oxcf->superres_mode == SUPERRES_FIXED && - oxcf->superres_scale_numerator == SCALE_DENOMINATOR && - oxcf->superres_kf_scale_numerator == SCALE_DENOMINATOR) + oxcf->superres_scale_denominator == SCALE_NUMERATOR && + oxcf->superres_kf_scale_denominator == SCALE_NUMERATOR) oxcf->superres_mode = SUPERRES_NONE; if (oxcf->superres_mode == SUPERRES_QTHRESH && oxcf->superres_qthresh == 255 && oxcf->superres_kf_qthresh == 255) @@ -1646,16 +1647,16 @@ static aom_codec_enc_cfg_map_t encoder_usage_cfg_map[] = { 25, // g_lag_in_frames - 0, // rc_dropframe_thresh - RESIZE_NONE, // rc_resize_mode - SCALE_DENOMINATOR, // rc_resize_numerator - SCALE_DENOMINATOR, // rc_resize_kf_numerator + 0, // rc_dropframe_thresh + RESIZE_NONE, // rc_resize_mode + SCALE_NUMERATOR, // rc_resize_denominator + SCALE_NUMERATOR, // rc_resize_kf_denominator - 0, // rc_superres_mode - SCALE_DENOMINATOR, // rc_superres_numerator - SCALE_DENOMINATOR, // rc_superres_kf_numerator - 63, // rc_superres_qthresh - 63, // rc_superres_kf_qthresh + 0, // rc_superres_mode + SCALE_NUMERATOR, // rc_superres_denominator + SCALE_NUMERATOR, // rc_superres_kf_denominator + 63, // rc_superres_qthresh + 63, // rc_superres_kf_qthresh AOM_VBR, // rc_end_usage { NULL, 0 }, // rc_twopass_stats_in diff --git a/av1/common/enums.h b/av1/common/enums.h index c1d084db1c..aeae71cf39 100644 --- a/av1/common/enums.h +++ b/av1/common/enums.h @@ -736,7 +736,7 @@ typedef enum { #if CONFIG_FRAME_SUPERRES #define SUPERRES_SCALE_BITS 3 -#define SUPERRES_SCALE_NUMERATOR_MIN 8 +#define SUPERRES_SCALE_DENOMINATOR_MIN 8 #endif // CONFIG_FRAME_SUPERRES #if CONFIG_LPF_DIRECT diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h index 7035825ecb..ec6c98aafa 100644 --- a/av1/common/onyxc_int.h +++ b/av1/common/onyxc_int.h @@ -368,8 +368,8 @@ typedef struct AV1Common { loop_filter_info_n lf_info; #if CONFIG_FRAME_SUPERRES - // The numerator of the superres scale; the denominator is fixed. - uint8_t superres_scale_numerator; + // The denominator of the superres scale; the numerator is fixed. + uint8_t superres_scale_denominator; int superres_upscaled_width; int superres_upscaled_height; #endif // CONFIG_FRAME_SUPERRES diff --git a/av1/common/resize.c b/av1/common/resize.c index 125f7556b2..fd66ad98f6 100644 --- a/av1/common/resize.c +++ b/av1/common/resize.c @@ -1168,24 +1168,22 @@ YV12_BUFFER_CONFIG *av1_scale_if_required(AV1_COMMON *cm, } } -void av1_calculate_scaled_size(int *width, int *height, int num) { - if (num != SCALE_DENOMINATOR) { - *width = *width * num / SCALE_DENOMINATOR; - *height = *height * num / SCALE_DENOMINATOR; +void av1_calculate_scaled_size(int *width, int *height, int denom) { + if (denom != SCALE_NUMERATOR) { + *width = *width * SCALE_NUMERATOR / denom; + *height = *height * SCALE_NUMERATOR / denom; // Make width and height even *width += *width & 1; *height += *height & 1; } } -// Inverse of av1_calculate_scaled_size() above: calculates the original size -// from the given scaled dimensions and the scale numerator. -void av1_calculate_unscaled_size(int *width, int *height, int num) { - if (num != SCALE_DENOMINATOR) { +void av1_calculate_unscaled_size(int *width, int *height, int denom) { + if (denom != SCALE_NUMERATOR) { // Note: av1_calculate_scaled_size() rounds *up* after division when the // resulting dimensions are odd. So here, we round *down*. - *width = *width * SCALE_DENOMINATOR / num; - *height = *height * SCALE_DENOMINATOR / num; + *width = *width * denom / SCALE_NUMERATOR; + *height = *height * denom / SCALE_NUMERATOR; } } diff --git a/av1/common/resize.h b/av1/common/resize.h index 47dbf21e78..7834dfa2e3 100644 --- a/av1/common/resize.h +++ b/av1/common/resize.h @@ -86,19 +86,19 @@ YV12_BUFFER_CONFIG *av1_scale_if_required(AV1_COMMON *cm, YV12_BUFFER_CONFIG *scaled); // Calculates the scaled size from the given original dimensions and the scale -// numerator. -void av1_calculate_scaled_size(int *width, int *height, int num); +// denominator. +void av1_calculate_scaled_size(int *width, int *height, int denom); // Inverse of av1_calculate_scaled_size() above: calculates the original size -// from the given scaled dimensions and the scale numerator. -void av1_calculate_unscaled_size(int *width, int *height, int num); +// from the given scaled dimensions and the scale denominator. +void av1_calculate_unscaled_size(int *width, int *height, int denom); #if CONFIG_FRAME_SUPERRES void av1_superres_upscale(AV1_COMMON *cm, BufferPool *const pool); // Returns 1 if a superres upscaled frame is unscaled and 0 otherwise. static INLINE int av1_superres_unscaled(const AV1_COMMON *cm) { - return (cm->superres_scale_numerator == SCALE_DENOMINATOR); + return (cm->superres_scale_denominator == SCALE_NUMERATOR); } #endif // CONFIG_FRAME_SUPERRES diff --git a/av1/common/restoration.c b/av1/common/restoration.c index 613ad8386f..fb47b66390 100644 --- a/av1/common/restoration.c +++ b/av1/common/restoration.c @@ -1782,8 +1782,8 @@ int av1_loop_restoration_corners_in_sb(const struct AV1Common *cm, int plane, #if CONFIG_FRAME_SUPERRES const int frame_w = cm->superres_upscaled_width; const int frame_h = cm->superres_upscaled_height; - const int mi_to_px = MI_SIZE * cm->superres_scale_numerator; - const int denom = SCALE_DENOMINATOR; + const int mi_to_px = MI_SIZE * SCALE_NUMERATOR; + const int denom = cm->superres_scale_denominator; #else const int frame_w = cm->width; const int frame_h = cm->height; diff --git a/av1/common/scale.h b/av1/common/scale.h index 3aa61eb34e..900e6bf472 100644 --- a/av1/common/scale.h +++ b/av1/common/scale.h @@ -19,7 +19,7 @@ extern "C" { #endif -#define SCALE_DENOMINATOR 16 +#define SCALE_NUMERATOR 8 #define REF_SCALE_SHIFT 14 #define REF_NO_SCALE (1 << REF_SCALE_SHIFT) diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index c2a48c43b4..e140847132 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c @@ -3038,15 +3038,15 @@ static void setup_superres(AV1_COMMON *const cm, struct aom_read_bit_buffer *rb, cm->superres_upscaled_width = *width; cm->superres_upscaled_height = *height; if (aom_rb_read_bit(rb)) { - cm->superres_scale_numerator = + cm->superres_scale_denominator = (uint8_t)aom_rb_read_literal(rb, SUPERRES_SCALE_BITS); - cm->superres_scale_numerator += SUPERRES_SCALE_NUMERATOR_MIN; + cm->superres_scale_denominator += SUPERRES_SCALE_DENOMINATOR_MIN; // Don't edit cm->width or cm->height directly, or the buffers won't get // resized correctly - av1_calculate_scaled_size(width, height, cm->superres_scale_numerator); + av1_calculate_scaled_size(width, height, cm->superres_scale_denominator); } else { // 1:1 scaling - ie. no scaling, scale not provided - cm->superres_scale_numerator = SCALE_DENOMINATOR; + cm->superres_scale_denominator = SCALE_NUMERATOR; } } #endif // CONFIG_FRAME_SUPERRES diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index 799ee81780..302b56cea3 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c @@ -4249,12 +4249,12 @@ static void write_render_size(const AV1_COMMON *cm, static void write_superres_scale(const AV1_COMMON *const cm, struct aom_write_bit_buffer *wb) { // First bit is whether to to scale or not - if (cm->superres_scale_numerator == SCALE_DENOMINATOR) { + if (cm->superres_scale_denominator == SCALE_NUMERATOR) { aom_wb_write_bit(wb, 0); // no scaling } else { aom_wb_write_bit(wb, 1); // scaling, write scale factor aom_wb_write_literal( - wb, cm->superres_scale_numerator - SUPERRES_SCALE_NUMERATOR_MIN, + wb, cm->superres_scale_denominator - SUPERRES_SCALE_DENOMINATOR_MIN, SUPERRES_SCALE_BITS); } } diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 2de36dea73..46cf2796bb 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c @@ -3088,7 +3088,7 @@ AV1_COMP *av1_create_compressor(AV1EncoderConfig *oxcf, av1_loop_filter_init(cm); #if CONFIG_FRAME_SUPERRES - cm->superres_scale_numerator = SCALE_DENOMINATOR; + cm->superres_scale_denominator = SCALE_NUMERATOR; cm->superres_upscaled_width = oxcf->width; cm->superres_upscaled_height = oxcf->height; #endif // CONFIG_FRAME_SUPERRES @@ -4429,21 +4429,21 @@ static uint8_t calculate_next_resize_scale(const AV1_COMP *cpi) { // Choose an arbitrary random number static unsigned int seed = 56789; const AV1EncoderConfig *oxcf = &cpi->oxcf; - if (oxcf->pass == 1) return SCALE_DENOMINATOR; - uint8_t new_num = SCALE_DENOMINATOR; + if (oxcf->pass == 1) return SCALE_NUMERATOR; + uint8_t new_denom = SCALE_NUMERATOR; switch (oxcf->resize_mode) { - case RESIZE_NONE: new_num = SCALE_DENOMINATOR; break; + case RESIZE_NONE: new_denom = SCALE_NUMERATOR; break; case RESIZE_FIXED: if (cpi->common.frame_type == KEY_FRAME) - new_num = oxcf->resize_kf_scale_numerator; + new_denom = oxcf->resize_kf_scale_denominator; else - new_num = oxcf->resize_scale_numerator; + new_denom = oxcf->resize_scale_denominator; break; - case RESIZE_RANDOM: new_num = lcg_rand16(&seed) % 9 + 8; break; + case RESIZE_RANDOM: new_denom = lcg_rand16(&seed) % 9 + 8; break; default: assert(0); } - return new_num; + return new_denom; } #if CONFIG_FRAME_SUPERRES @@ -4451,19 +4451,19 @@ static uint8_t calculate_next_superres_scale(AV1_COMP *cpi) { // Choose an arbitrary random number static unsigned int seed = 34567; const AV1EncoderConfig *oxcf = &cpi->oxcf; - if (oxcf->pass == 1) return SCALE_DENOMINATOR; - uint8_t new_num = SCALE_DENOMINATOR; + if (oxcf->pass == 1) return SCALE_NUMERATOR; + uint8_t new_denom = SCALE_NUMERATOR; int bottom_index, top_index, q, qthresh; switch (oxcf->superres_mode) { - case SUPERRES_NONE: new_num = SCALE_DENOMINATOR; break; + case SUPERRES_NONE: new_denom = SCALE_NUMERATOR; break; case SUPERRES_FIXED: if (cpi->common.frame_type == KEY_FRAME) - new_num = oxcf->superres_kf_scale_numerator; + new_denom = oxcf->superres_kf_scale_denominator; else - new_num = oxcf->superres_scale_numerator; + new_denom = oxcf->superres_scale_denominator; break; - case SUPERRES_RANDOM: new_num = lcg_rand16(&seed) % 9 + 8; break; + case SUPERRES_RANDOM: new_denom = lcg_rand16(&seed) % 9 + 8; break; case SUPERRES_QTHRESH: qthresh = (cpi->common.frame_type == KEY_FRAME ? oxcf->superres_kf_qthresh : oxcf->superres_qthresh); @@ -4471,74 +4471,86 @@ static uint8_t calculate_next_superres_scale(AV1_COMP *cpi) { q = av1_rc_pick_q_and_bounds(cpi, cpi->oxcf.width, cpi->oxcf.height, &bottom_index, &top_index); if (q < qthresh) { - new_num = SCALE_DENOMINATOR; + new_denom = SCALE_NUMERATOR; } else { - new_num = SCALE_DENOMINATOR - 1 - ((q - qthresh) >> 3); - new_num = AOMMAX(SCALE_DENOMINATOR / 2, new_num); - // printf("SUPERRES: q %d, qthresh %d: num %d\n", q, qthresh, new_num); + new_denom = SCALE_NUMERATOR + 1 + ((q - qthresh) >> 3); + new_denom = AOMMIN(SCALE_NUMERATOR << 1, new_denom); + // printf("SUPERRES: q %d, qthresh %d: denom %d\n", q, qthresh, + // new_denom); } break; default: assert(0); } - return new_num; + return new_denom; } +static int dimension_is_ok(int orig_dim, int resized_dim, int denom) { + return (resized_dim * SCALE_NUMERATOR >= orig_dim * denom / 2); +} + +static int dimensions_are_ok(int owidth, int oheight, size_params_type *rsz) { + return dimension_is_ok(owidth, rsz->resize_width, rsz->superres_denom) && + dimension_is_ok(oheight, rsz->resize_height, rsz->superres_denom); +} + +#define DIVIDE_AND_ROUND(x, y) (((x) + ((y) >> 1)) / (y)) + static int validate_size_scales(RESIZE_MODE resize_mode, SUPERRES_MODE superres_mode, int owidth, int oheight, size_params_type *rsz) { - if (rsz->resize_width * rsz->superres_num >= SCALE_DENOMINATOR * owidth / 2 && - rsz->resize_height * rsz->superres_num >= SCALE_DENOMINATOR * oheight / 2) + if (dimensions_are_ok(owidth, oheight, rsz)) { // Nothing to do. return 1; - int resize_num = AOMMIN(((rsz->resize_width * 16 + owidth / 2) / owidth), - ((rsz->resize_height * 16 + oheight / 2) / oheight)); + } + + // Calculate current resize scale. + int resize_denom = + AOMMAX(DIVIDE_AND_ROUND(owidth * SCALE_NUMERATOR, rsz->resize_width), + DIVIDE_AND_ROUND(oheight * SCALE_NUMERATOR, rsz->resize_height)); + if (resize_mode != RESIZE_RANDOM && superres_mode == SUPERRES_RANDOM) { - rsz->superres_num = - (SCALE_DENOMINATOR * SCALE_DENOMINATOR + 2 * resize_num - 1) / - (2 * resize_num); - if (rsz->resize_width * rsz->superres_num < - SCALE_DENOMINATOR * owidth / 2 || - rsz->resize_height * rsz->superres_num < - SCALE_DENOMINATOR * oheight / 2) { - if (rsz->superres_num < SCALE_DENOMINATOR) rsz->superres_num++; + // Alter superres scale as needed to enforce conformity. + rsz->superres_denom = + (2 * SCALE_NUMERATOR * SCALE_NUMERATOR) / resize_denom; + if (!dimensions_are_ok(owidth, oheight, rsz)) { + if (rsz->superres_denom > SCALE_NUMERATOR) --rsz->superres_denom; } } else if (resize_mode == RESIZE_RANDOM && superres_mode != SUPERRES_RANDOM) { - resize_num = - (SCALE_DENOMINATOR * SCALE_DENOMINATOR + 2 * rsz->superres_num - 1) / - (2 * rsz->superres_num); + // Alter resize scale as needed to enforce conformity. + resize_denom = + (2 * SCALE_NUMERATOR * SCALE_NUMERATOR) / rsz->superres_denom; rsz->resize_width = owidth; rsz->resize_height = oheight; av1_calculate_scaled_size(&rsz->resize_width, &rsz->resize_height, - resize_num); - if (rsz->resize_width * rsz->superres_num < - SCALE_DENOMINATOR * owidth / 2 || - rsz->resize_height * rsz->superres_num < - SCALE_DENOMINATOR * oheight / 2) { - if (resize_num < SCALE_DENOMINATOR) resize_num++; + resize_denom); + if (!dimensions_are_ok(owidth, oheight, rsz)) { + if (resize_denom > SCALE_NUMERATOR) { + --resize_denom; + rsz->resize_width = owidth; + rsz->resize_height = oheight; + av1_calculate_scaled_size(&rsz->resize_width, &rsz->resize_height, + resize_denom); + } } } else if (resize_mode == RESIZE_RANDOM && superres_mode == SUPERRES_RANDOM) { + // Alter both resize and superres scales as needed to enforce conformity. do { - if (resize_num < rsz->superres_num) - ++resize_num; + if (resize_denom > rsz->superres_denom) + --resize_denom; else - ++rsz->superres_num; + --rsz->superres_denom; rsz->resize_width = owidth; rsz->resize_height = oheight; av1_calculate_scaled_size(&rsz->resize_width, &rsz->resize_height, - resize_num); - } while ((rsz->resize_width * rsz->superres_num < - SCALE_DENOMINATOR * owidth / 2 || - rsz->resize_height * rsz->superres_num < - SCALE_DENOMINATOR * oheight / 2) && - (resize_num < SCALE_DENOMINATOR || - rsz->superres_num < SCALE_DENOMINATOR)); - } else { + resize_denom); + } while (!dimensions_are_ok(owidth, oheight, rsz) && + (resize_denom > SCALE_NUMERATOR || + rsz->superres_denom > SCALE_NUMERATOR)); + } else { // We are allowed to alter neither resize scale nor superres scale. return 0; } - if (rsz->resize_width * rsz->superres_num >= SCALE_DENOMINATOR * owidth / 2 && - rsz->resize_height * rsz->superres_num >= SCALE_DENOMINATOR * oheight / 2) - return 1; - return 0; + return dimensions_are_ok(owidth, oheight, rsz); } +#undef DIVIDE_AND_ROUND #endif // CONFIG_FRAME_SUPERRES // Calculates resize and superres params for next frame @@ -4548,24 +4560,24 @@ size_params_type av1_calculate_next_size_params(AV1_COMP *cpi) { oxcf->width, oxcf->height, #if CONFIG_FRAME_SUPERRES - SCALE_DENOMINATOR + SCALE_NUMERATOR #endif // CONFIG_FRAME_SUPERRES }; - int resize_num; + int resize_denom; if (oxcf->pass == 1) return rsz; if (cpi->resize_pending_width && cpi->resize_pending_height) { rsz.resize_width = cpi->resize_pending_width; rsz.resize_height = cpi->resize_pending_height; cpi->resize_pending_width = cpi->resize_pending_height = 0; } else { - resize_num = calculate_next_resize_scale(cpi); + resize_denom = calculate_next_resize_scale(cpi); rsz.resize_width = cpi->oxcf.width; rsz.resize_height = cpi->oxcf.height; av1_calculate_scaled_size(&rsz.resize_width, &rsz.resize_height, - resize_num); + resize_denom); } #if CONFIG_FRAME_SUPERRES - rsz.superres_num = calculate_next_superres_scale(cpi); + rsz.superres_denom = calculate_next_superres_scale(cpi); if (!validate_size_scales(oxcf->resize_mode, oxcf->superres_mode, oxcf->width, oxcf->height, &rsz)) assert(0 && "Invalid scale parameters"); @@ -4581,8 +4593,8 @@ static void setup_frame_size_from_params(AV1_COMP *cpi, size_params_type *rsz) { AV1_COMMON *cm = &cpi->common; cm->superres_upscaled_width = encode_width; cm->superres_upscaled_height = encode_height; - cm->superres_scale_numerator = rsz->superres_num; - av1_calculate_scaled_size(&encode_width, &encode_height, rsz->superres_num); + cm->superres_scale_denominator = rsz->superres_denom; + av1_calculate_scaled_size(&encode_width, &encode_height, rsz->superres_denom); #endif // CONFIG_FRAME_SUPERRES set_frame_size(cpi, encode_width, encode_height); } diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index 27f96b5210..eb779a3cd0 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h @@ -218,14 +218,14 @@ typedef struct AV1EncoderConfig { #endif // Internal frame size scaling. RESIZE_MODE resize_mode; - uint8_t resize_scale_numerator; - uint8_t resize_kf_scale_numerator; + uint8_t resize_scale_denominator; + uint8_t resize_kf_scale_denominator; #if CONFIG_FRAME_SUPERRES // Frame Super-Resolution size scaling. SUPERRES_MODE superres_mode; - uint8_t superres_scale_numerator; - uint8_t superres_kf_scale_numerator; + uint8_t superres_scale_denominator; + uint8_t superres_kf_scale_denominator; int superres_qthresh; int superres_kf_qthresh; #endif // CONFIG_FRAME_SUPERRES diff --git a/av1/encoder/pickrst.c b/av1/encoder/pickrst.c index 28f3a0cd2b..3da7789c79 100644 --- a/av1/encoder/pickrst.c +++ b/av1/encoder/pickrst.c @@ -546,9 +546,9 @@ static void foreach_rtile_in_tile(const struct rest_search_ctxt *ctxt, // top-left and bottom-right of the tile. if (!av1_superres_unscaled(cm)) { av1_calculate_unscaled_size(&tile_col_start, &tile_row_start, - cm->superres_scale_numerator); + cm->superres_scale_denominator); av1_calculate_unscaled_size(&tile_col_end, &tile_row_end, - cm->superres_scale_numerator); + cm->superres_scale_denominator); // Make sure we don't fall off the bottom-right of the frame. tile_col_end = AOMMIN(tile_col_end, ctxt->plane_width); tile_row_end = AOMMIN(tile_row_end, ctxt->plane_height); diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h index 9172ca77f0..8b410e7785 100644 --- a/av1/encoder/ratectrl.h +++ b/av1/encoder/ratectrl.h @@ -53,7 +53,7 @@ typedef struct { int resize_width; int resize_height; #if CONFIG_FRAME_SUPERRES - uint8_t superres_num; + uint8_t superres_denom; #endif // CONFIG_FRAME_SUPERRES } size_params_type; -- GitLab