Commit 7166f22a authored by Debargha Mukherjee's avatar Debargha Mukherjee

Add a q index based frame superres mode

Refactors and adds superres-mode 3 and associated
paramters --superres-qthresh and --superres-kf-qthresh
that are used to trigger superres mode when the qindex
for any frame exceeds the thresholds provided for non-key
and key-frames respenctively. The superres scale factor
numerator is progressively reduced from 16 starting from
that q threshold following a fixed slope.

Change-Id: If1c782993667a6fbaaa01bbde77c4924008c0d28
parent 34e1201a
......@@ -395,7 +395,7 @@ typedef struct aom_codec_enc_cfg {
* using restoration filters should allow it to outperform normal resizing.
*
* Mode 0 is SUPERRES_NONE, mode 1 is SUPERRES_FIXED, and mode 2 is
* SUPERRES_DYNAMIC.
* SUPERRES_RANDOM.
*/
unsigned int rc_superres_mode;
......@@ -407,7 +407,7 @@ typedef struct aom_codec_enc_cfg {
*
* Valid numerators are 8 to 16.
*
* Ignored by SUPERRES_DYNAMIC.
* Used only by SUPERRES_FIXED.
*/
unsigned int rc_superres_numerator;
......@@ -421,6 +421,24 @@ typedef struct aom_codec_enc_cfg {
*/
unsigned int rc_superres_kf_numerator;
/*!\brief Frame super-resolution q threshold.
*
* The q level threshold after which superres is used.
* Valid values are 1 to 63.
*
* Used only by SUPERRES_QTHRESH
*/
unsigned int rc_superres_qthresh;
/*!\brief Keyframe super-resolution q threshold.
*
* The q level threshold after which superres is used for key frames.
* Valid values are 1 to 63.
*
* Used only by SUPERRES_QTHRESH
*/
unsigned int rc_superres_kf_qthresh;
/*!\brief Rate control algorithm to use.
*
* Indicates whether the end usage of this stream is to be streamed over
......
......@@ -302,6 +302,11 @@ static const arg_def_t superres_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_qthresh = ARG_DEF(
NULL, "superres-qthresh", 1, "Frame super-resolution qindex threshold");
static const arg_def_t superres_kf_qthresh =
ARG_DEF(NULL, "superres-kf-qthresh", 1,
"Frame super-resolution keyframe qindex threshold");
#endif // CONFIG_FRAME_SUPERRES
static const struct arg_enum_list end_usage_enum[] = { { "vbr", AOM_VBR },
{ "cbr", AOM_CBR },
......@@ -334,6 +339,8 @@ static const arg_def_t *rc_args[] = { &dropframe_thresh,
&superres_mode,
&superres_numerator,
&superres_kf_numerator,
&superres_qthresh,
&superres_kf_qthresh,
#endif // CONFIG_FRAME_SUPERRES
&end_usage,
&target_bitrate,
......@@ -1055,6 +1062,10 @@ static int parse_stream_params(struct AvxEncoderConfig *global,
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_qthresh, argi)) {
config->cfg.rc_superres_qthresh = arg_parse_uint(&arg);
} else if (arg_match(&arg, &superres_kf_qthresh, argi)) {
config->cfg.rc_superres_kf_qthresh = arg_parse_uint(&arg);
#endif // CONFIG_FRAME_SUPERRES
} else if (arg_match(&arg, &end_usage, argi)) {
config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
......@@ -1267,6 +1278,8 @@ static void show_stream_config(struct stream_state *stream,
SHOW(rc_superres_mode);
SHOW(rc_superres_numerator);
SHOW(rc_superres_kf_numerator);
SHOW(rc_superres_qthresh);
SHOW(rc_superres_kf_qthresh);
#endif // CONFIG_FRAME_SUPERRES
SHOW(rc_end_usage);
SHOW(rc_target_bitrate);
......
......@@ -8,7 +8,6 @@
* Media Patent License 1.0 was not distributed with this source code in the
* PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
#include <stdlib.h>
#include <string.h>
......@@ -251,17 +250,19 @@ static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx,
(MAX_LAG_BUFFERS - 1));
}
RANGE_CHECK_HI(cfg, rc_resize_mode, RESIZE_DYNAMIC);
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);
#if CONFIG_FRAME_SUPERRES
RANGE_CHECK_HI(cfg, rc_superres_mode, SUPERRES_DYNAMIC);
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_qthresh, 1, 63);
RANGE_CHECK(cfg, rc_superres_kf_qthresh, 1, 63);
#endif // CONFIG_FRAME_SUPERRES
// AV1 does not support a lower bound on the keyframe interval in
......@@ -513,10 +514,20 @@ static aom_codec_err_t set_encoder_config(
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_qthresh =
extra_cfg->lossless ? 255
: av1_quantizer_to_qindex(cfg->rc_superres_qthresh);
oxcf->superres_kf_qthresh =
extra_cfg->lossless
? 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_mode = SUPERRES_NONE;
if (oxcf->superres_mode == SUPERRES_QTHRESH &&
oxcf->superres_qthresh == 255 && oxcf->superres_kf_qthresh == 255)
oxcf->superres_mode = SUPERRES_NONE;
#endif // CONFIG_FRAME_SUPERRES
oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
......@@ -1617,6 +1628,8 @@ static aom_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
0, // rc_superres_mode
SCALE_DENOMINATOR, // rc_superres_numerator
SCALE_DENOMINATOR, // rc_superres_kf_numerator
63, // rc_superres_qthresh
63, // rc_superres_kf_qthresh
AOM_VBR, // rc_end_usage
{ NULL, 0 }, // rc_twopass_stats_in
......
......@@ -19,6 +19,22 @@
#include "av1/common/entropymv.h"
#include "av1/common/onyxc_int.h"
int av1_get_MBs(int width, int height) {
const int aligned_width = ALIGN_POWER_OF_TWO(width, 3);
const int aligned_height = ALIGN_POWER_OF_TWO(height, 3);
const int mi_cols = aligned_width >> MI_SIZE_LOG2;
const int mi_rows = aligned_height >> MI_SIZE_LOG2;
#if CONFIG_CB4X4
const int mb_cols = (mi_cols + 2) >> 2;
const int mb_rows = (mi_rows + 2) >> 2;
#else
const int mb_cols = (mi_cols + 1) >> 1;
const int mb_rows = (mi_rows + 1) >> 1;
#endif
return mb_rows * mb_cols;
}
void av1_set_mb_mi(AV1_COMMON *cm, int width, int height) {
// Ensure that the decoded width and height are both multiples of
// 8 luma pixels (note: this may only be a multiple of 4 chroma pixels if
......
......@@ -37,6 +37,7 @@ int av1_alloc_state_buffers(struct AV1Common *cm, int width, int height);
void av1_free_state_buffers(struct AV1Common *cm);
void av1_set_mb_mi(struct AV1Common *cm, int width, int height);
int av1_get_MBs(int width, int height);
void av1_swap_current_and_last_seg_map(struct AV1Common *cm);
......
......@@ -56,6 +56,7 @@
#if CONFIG_LOOP_RESTORATION
#include "av1/encoder/pickrst.h"
#endif // CONFIG_LOOP_RESTORATION
#include "av1/encoder/random.h"
#include "av1/encoder/ratectrl.h"
#include "av1/encoder/rd.h"
#include "av1/encoder/segmentation.h"
......@@ -848,7 +849,7 @@ void av1_new_framerate(AV1_COMP *cpi, double framerate) {
cpi->od_rc.framerate = cpi->framerate;
od_enc_rc_resize(&cpi->od_rc);
#else
av1_rc_update_framerate(cpi);
av1_rc_update_framerate(cpi, cpi->common.width, cpi->common.height);
#endif
}
......@@ -3934,7 +3935,8 @@ static void set_size_dependent_vars(AV1_COMP *cpi, int *q, int *bottom_index,
&cpi->od_rc, cpi->refresh_golden_frame, cpi->refresh_alt_ref_frame,
frame_type, bottom_index, top_index);
#else
*q = av1_rc_pick_q_and_bounds(cpi, bottom_index, top_index);
*q = av1_rc_pick_q_and_bounds(cpi, cm->width, cm->height, bottom_index,
top_index);
#endif
if (!frame_is_intra_only(cm)) {
......@@ -4076,7 +4078,7 @@ static void set_frame_size(AV1_COMP *cpi, int width, int height) {
#if !CONFIG_XIPHRC
if (cpi->oxcf.pass == 2) {
av1_set_target_rate(cpi);
av1_set_target_rate(cpi, cm->width, cm->height);
}
#endif
......@@ -4164,26 +4166,132 @@ static void set_frame_size(AV1_COMP *cpi, int width, int height) {
set_ref_ptrs(cm, xd, LAST_FRAME, LAST_FRAME);
}
static void setup_frame_size(AV1_COMP *cpi) {
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;
switch (oxcf->resize_mode) {
case RESIZE_NONE: new_num = SCALE_DENOMINATOR; break;
case RESIZE_FIXED:
if (cpi->common.frame_type == KEY_FRAME)
new_num = oxcf->resize_kf_scale_numerator;
else
new_num = oxcf->resize_scale_numerator;
break;
case RESIZE_RANDOM: new_num = lcg_rand16(&seed) % 9 + 8; break;
default: assert(0);
}
return new_num;
}
#if CONFIG_FRAME_SUPERRES
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;
int bottom_index, top_index, q, qthresh;
switch (oxcf->superres_mode) {
case SUPERRES_NONE: new_num = SCALE_DENOMINATOR; break;
case SUPERRES_FIXED:
if (cpi->common.frame_type == KEY_FRAME)
new_num = oxcf->superres_kf_scale_numerator;
else
new_num = oxcf->superres_scale_numerator;
break;
case SUPERRES_RANDOM: new_num = lcg_rand16(&seed) % 9 + 8; break;
case SUPERRES_QTHRESH:
qthresh = (cpi->common.frame_type == KEY_FRAME ? oxcf->superres_kf_qthresh
: oxcf->superres_qthresh);
av1_set_target_rate(cpi, cpi->oxcf.width, cpi->oxcf.height);
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;
} 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);
}
break;
default: assert(0);
}
return new_num;
}
static int validate_size_scales(RESIZE_MODE resize_mode,
SUPERRES_MODE superres_mode,
size_params_type *rsz) {
if (rsz->resize_num * rsz->superres_num * 2 >
SCALE_DENOMINATOR * SCALE_DENOMINATOR)
return 1;
if (resize_mode != RESIZE_RANDOM && superres_mode == SUPERRES_RANDOM) {
rsz->superres_num =
(SCALE_DENOMINATOR * SCALE_DENOMINATOR + 2 * rsz->resize_num - 1) /
(2 * rsz->resize_num);
} else if (resize_mode == RESIZE_RANDOM && superres_mode != SUPERRES_RANDOM) {
rsz->resize_num =
(SCALE_DENOMINATOR * SCALE_DENOMINATOR + 2 * rsz->superres_num - 1) /
(2 * rsz->superres_num);
} else if (resize_mode == RESIZE_RANDOM && superres_mode == SUPERRES_RANDOM) {
do {
if (rsz->resize_num < rsz->superres_num)
++rsz->resize_num;
else
++rsz->superres_num;
} while (rsz->resize_num * rsz->superres_num * 2 <=
SCALE_DENOMINATOR * SCALE_DENOMINATOR);
} else {
return 0;
}
return 1;
}
#endif // CONFIG_FRAME_SUPERRES
size_params_type av1_calculate_next_size_params(AV1_COMP *cpi) {
const AV1EncoderConfig *oxcf = &cpi->oxcf;
size_params_type rsz = {
SCALE_DENOMINATOR,
#if CONFIG_FRAME_SUPERRES
SCALE_DENOMINATOR
#endif // CONFIG_FRAME_SUPERRES
};
if (oxcf->pass == 1) return rsz;
rsz.resize_num = calculate_next_resize_scale(cpi);
#if CONFIG_FRAME_SUPERRES
rsz.superres_num = calculate_next_superres_scale(cpi);
if (!validate_size_scales(oxcf->resize_mode, oxcf->superres_mode, &rsz))
assert(0 && "Invalid scale parameters");
#endif // CONFIG_FRAME_SUPERRES
return rsz;
}
static void setup_frame_size_from_params(AV1_COMP *cpi, size_params_type *rsz) {
int encode_width = cpi->oxcf.width;
int encode_height = cpi->oxcf.height;
uint8_t resize_num = av1_calculate_next_resize_scale(cpi);
av1_calculate_scaled_size(&encode_width, &encode_height, resize_num);
av1_calculate_scaled_size(&encode_width, &encode_height, rsz->resize_num);
#if CONFIG_FRAME_SUPERRES
AV1_COMMON *cm = &cpi->common;
cm->superres_upscaled_width = encode_width;
cm->superres_upscaled_height = encode_height;
cm->superres_scale_numerator =
av1_calculate_next_superres_scale(cpi, encode_width, encode_height);
av1_calculate_scaled_size(&encode_width, &encode_height,
cm->superres_scale_numerator);
cm->superres_scale_numerator = rsz->superres_num;
av1_calculate_scaled_size(&encode_width, &encode_height, rsz->superres_num);
#endif // CONFIG_FRAME_SUPERRES
set_frame_size(cpi, encode_width, encode_height);
}
static void setup_frame_size(AV1_COMP *cpi) {
size_params_type rsz;
rsz = av1_calculate_next_size_params(cpi);
setup_frame_size_from_params(cpi, &rsz);
}
#if CONFIG_FRAME_SUPERRES
static void superres_post_encode(AV1_COMP *cpi) {
AV1_COMMON *cm = &cpi->common;
......@@ -4326,7 +4434,9 @@ static void encode_without_recode_loop(AV1_COMP *cpi) {
aom_clear_system_state();
set_size_independent_vars(cpi);
setup_frame_size(cpi);
assert(cm->width == cpi->scaled_source.y_crop_width);
assert(cm->height == cpi->scaled_source.y_crop_height);
......@@ -4397,14 +4507,14 @@ static void encode_with_recode_loop(AV1_COMP *cpi, size_t *size,
cpi->source->buf_8bit_valid = 0;
#endif
aom_clear_system_state();
setup_frame_size(cpi);
set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
do {
aom_clear_system_state();
setup_frame_size(cpi);
if (loop_count == 0) {
set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
// TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed.
set_mv_search_params(cpi);
......@@ -4572,20 +4682,22 @@ static void encode_with_recode_loop(AV1_COMP *cpi, size_t *size,
if (undershoot_seen || loop_at_this_size > 1) {
// Update rate_correction_factor unless
av1_rc_update_rate_correction_factors(cpi);
av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
q = (q_high + q_low + 1) / 2;
} else {
// Update rate_correction_factor unless
av1_rc_update_rate_correction_factors(cpi);
av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
q = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
AOMMAX(q_high, top_index));
AOMMAX(q_high, top_index), cm->width,
cm->height);
while (q < q_low && retries < 10) {
av1_rc_update_rate_correction_factors(cpi);
av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
q = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
AOMMAX(q_high, top_index));
AOMMAX(q_high, top_index), cm->width,
cm->height);
retries++;
}
}
......@@ -4596,12 +4708,12 @@ static void encode_with_recode_loop(AV1_COMP *cpi, size_t *size,
q_high = q > q_low ? q - 1 : q_low;
if (overshoot_seen || loop_at_this_size > 1) {
av1_rc_update_rate_correction_factors(cpi);
av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
q = (q_high + q_low) / 2;
} else {
av1_rc_update_rate_correction_factors(cpi);
av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
q = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
top_index);
top_index, cm->width, cm->height);
// 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
......@@ -4611,9 +4723,9 @@ static void encode_with_recode_loop(AV1_COMP *cpi, size_t *size,
}
while (q > q_high && retries < 10) {
av1_rc_update_rate_correction_factors(cpi);
av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
q = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
top_index);
top_index, cm->width, cm->height);
retries++;
}
}
......@@ -5004,7 +5116,7 @@ static void encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size,
// Since we allocate a spot for the OVERLAY frame in the gf group, we need
// to do post-encoding update accordingly.
if (cpi->rc.is_src_frame_alt_ref) {
av1_set_target_rate(cpi);
av1_set_target_rate(cpi, cm->width, cm->height);
#if CONFIG_XIPHRC
frame_type = cm->frame_type == INTER_FRAME ? OD_P_FRAME : OD_I_FRAME;
drop_this_frame = od_enc_rc_update_state(
......
......@@ -134,14 +134,20 @@ typedef enum {
#endif
typedef enum {
RESIZE_NONE = 0, // No frame resizing allowed.
RESIZE_FIXED = 1, // All frames are coded at the specified dimension.
RESIZE_DYNAMIC = 2 // Coded size of each frame is determined by the codec.
RESIZE_FIXED = 1, // All frames are coded at the specified scale.
RESIZE_RANDOM = 2, // All frames are coded at a random scale.
RESIZE_MODES
} RESIZE_MODE;
#if CONFIG_FRAME_SUPERRES
typedef enum {
SUPERRES_NONE = 0,
SUPERRES_FIXED = 1,
SUPERRES_DYNAMIC = 2
SUPERRES_NONE = 0, // No frame superres allowed
SUPERRES_FIXED = 1, // All frames are coded at the specified scale,
// and super-resolved.
SUPERRES_RANDOM = 2, // All frames are coded at a random scale,
// and super-resolved.
SUPERRES_QTHRESH = 3, // Superres scale for a frame is determined based on
// q_index
SUPERRES_MODES
} SUPERRES_MODE;
#endif // CONFIG_FRAME_SUPERRES
......@@ -224,6 +230,8 @@ typedef struct AV1EncoderConfig {
SUPERRES_MODE superres_mode;
uint8_t superres_scale_numerator;
uint8_t superres_kf_scale_numerator;
int superres_qthresh;
int superres_kf_qthresh;
#endif // CONFIG_FRAME_SUPERRES
// Enable feature to reduce the frame quantization every x frames.
......
......@@ -94,9 +94,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->oxcf.width * cpi->oxcf.height) /
(cpi->common.width * cpi->common.height);
// How many times less pixels there are to encode given the current scaling.
// Temporary replacement for rcf_mult and rate_thresh_mult.
static double resize_rate_factor(const AV1_COMP *cpi, int width, int height) {
(void)cpi;
return (double)(cpi->oxcf.width * cpi->oxcf.height) / (width * height);
}
// Functions to compute the active minq lookup table entries based on a
......@@ -372,7 +374,8 @@ int av1_rc_drop_frame(AV1_COMP *cpi) {
}
}
static double get_rate_correction_factor(const AV1_COMP *cpi) {
static double get_rate_correction_factor(const AV1_COMP *cpi, int width,
int height) {
const RATE_CONTROL *const rc = &cpi->rc;
double rcf;
......@@ -390,15 +393,16 @@ static double get_rate_correction_factor(const AV1_COMP *cpi) {
else
rcf = rc->rate_correction_factors[INTER_NORMAL];
}
rcf *= av1_resize_rate_factor(cpi);
rcf *= resize_rate_factor(cpi, width, height);
return fclamp(rcf, MIN_BPB_FACTOR, MAX_BPB_FACTOR);
}
static void set_rate_correction_factor(AV1_COMP *cpi, double factor) {
static void set_rate_correction_factor(AV1_COMP *cpi, double factor, int width,
int height) {
RATE_CONTROL *const rc = &cpi->rc;
// Normalize RCF to account for the size-dependent scaling factor.
factor /= av1_resize_rate_factor(cpi);
factor /= resize_rate_factor(cpi, width, height);
factor = fclamp(factor, MIN_BPB_FACTOR, MAX_BPB_FACTOR);
......@@ -418,11 +422,14 @@ static void set_rate_correction_factor(AV1_COMP *cpi, double factor) {
}
}
void av1_rc_update_rate_correction_factors(AV1_COMP *cpi) {
void av1_rc_update_rate_correction_factors(AV1_COMP *cpi, int width,
int height) {
const AV1_COMMON *const cm = &cpi->common;
int correction_factor = 100;
double rate_correction_factor = get_rate_correction_factor(cpi);
double rate_correction_factor =
get_rate_correction_factor(cpi, width, height);
double adjustment_limit;
const int MBs = av1_get_MBs(width, height);
int projected_size_based_on_q = 0;
......@@ -440,7 +447,7 @@ void av1_rc_update_rate_correction_factors(AV1_COMP *cpi) {
av1_cyclic_refresh_estimate_bits_at_q(cpi, rate_correction_factor);
} else {
projected_size_based_on_q =
av1_estimate_bits_at_q(cpi->common.frame_type, cm->base_qindex, cm->MBs,
av1_estimate_bits_at_q(cpi->common.frame_type, cm->base_qindex, MBs,
rate_correction_factor, cm->bit_depth);
}
// Work out a size correction factor.
......@@ -486,21 +493,24 @@ void av1_rc_update_rate_correction_factors(AV1_COMP *cpi) {
rate_correction_factor = MIN_BPB_FACTOR;
}
set_rate_correction_factor(cpi, rate_correction_factor);
set_rate_correction_factor(cpi, rate_correction_factor, width, height);
}
int av1_rc_regulate_q(const AV1_COMP *cpi, int target_bits_per_frame,
int active_best_quality, int active_worst_quality) {
int active_best_quality, int active_worst_quality,
int width, int height) {
const AV1_COMMON *const cm = &cpi->common;
int q = active_worst_quality;
int last_error = INT_MAX;
int i, target_bits_per_mb, bits_per_mb_at_this_q;
const double correction_factor = get_rate_correction_factor(cpi);
const int MBs = av1_get_MBs(width, height);
const double correction_factor =
get_rate_correction_factor(cpi, width, height);
// Calculate required scaling factor based on target frame size and size of
// frame produced using previous Q.
target_bits_per_mb =
(int)((uint64_t)target_bits_per_frame << BPER_MB_NORMBITS) / cm->MBs;
(int)((uint64_t)(target_bits_per_frame) << BPER_MB_NORMBITS) / MBs;
i = active_best_quality;
......@@ -651,8 +661,8 @@ static int calc_active_worst_quality_one_pass_cbr(const AV1_COMP *cpi) {
return active_worst_quality;
}
static int rc_pick_q_and_bounds_one_pass_cbr(const AV1_COMP *cpi,
int *bottom_index,
static int rc_pick_q_and_bounds_one_pass_cbr(const AV1_COMP *cpi, int width,
int height, int *bottom_index,
int *top_index) {
const AV1_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
......@@ -682,7 +692,7 @@ static int rc_pick_q_and_bounds_one_pass_cbr(const AV1_COMP *cpi,
rc, rc->avg_frame_qindex[KEY_FRAME], cm->bit_depth);
// Allow somewhat lower kf minq with small image formats.
if ((cm->width * cm->height) <= (352 * 288)) {
if ((width * height) <= (352 * 288)) {
q_adj_factor -= 0.25;
}
......@@ -744,7 +754,7 @@ static int rc_pick_q_and_bounds_one_pass_cbr(const AV1_COMP *cpi,
q = rc->last_boosted_qindex;
} else {
q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality,
active_worst_quality);
active_worst_quality, width, height);
if (q > *top_index) {
// Special case when we are targeting the max allowed rate
if (rc->this_frame_target >= rc->max_frame_bandwidth)
......@@ -774,8 +784,8 @@ static int get_active_cq_level(const RATE_CONTROL *rc,
return active_cq_level;
}
static int rc_pick_q_and_bounds_one_pass_vbr(const AV1_COMP *cpi,
int *bottom_index,
static int rc_pick_q_and_bounds_one_pass_vbr(const AV1_COMP *cpi, int width,
int height, int *bottom_index,
int *top_index) {
const AV1_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
......@@ -808,7 +818,7 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const AV1_COMP *cpi,
rc, rc->avg_frame_qindex[KEY_FRAME], cm->bit_depth);
// Allow somewhat lower kf minq with small image formats.
if ((cm->width * cm->height) <= (352 * 288)) {
if ((width * height) <= (352 * 288)) {
q_adj_factor -= 0.25;
}
......@@ -903,7 +913,7 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const AV1_COMP *cpi,
q = rc->last_boosted_qindex;
} else {
q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality,
active_worst_quality);
active_worst_quality, width, height);
if (q > *top_index) {
// Special case when we are targeting the max allowed rate
if (rc->this_frame_target >= rc->max_frame_bandwidth)
......@@ -949,7 +959,8 @@ int av1_frame_type_qdelta(const AV1_COMP *cpi, int rf_level, int q) {
}
#define STATIC_MOTION_THRESH 95
static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int *bottom_index,
static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int width,
int height, int *bottom_index,
int *top_index) {
const AV1_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
......@@ -996,7 +1007,7 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int *bottom_index,
get_kf_active_quality(rc, active_worst_quality, cm->bit_depth);
// Allow somewhat lower kf minq with small image formats.
if ((cm->width * cm->height) <= (352 * 288)) {
if ((width * height) <= (352 * 288)) {
q_adj_factor -= 0.25;
}
......@@ -1119,7 +1130,7 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int *bottom_index,
}
} else {
q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality,
active_worst_quality);
active_worst_quality, width, height);
if (q > active_worst_quality) {
// Special case when we are targeting the max allowed rate.
if (rc->this_frame_target >= rc->max_frame_bandwidth)
......@@ -1140,16 +1151,19 @@ static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int *bottom_index,
return q;
}
int av1_rc_pick_q_and_bounds(const AV1_COMP *cpi, int *bottom_index,
int *top_index) {
int av1_rc_pick_q_and_bounds(const AV1_COMP *cpi, int width, int height,
int *bottom_index, int *top_index) {
int q;
if (cpi->oxcf.pass == 0) {
if (cpi->oxcf.rc_mode == AOM_CBR)
q = rc_pick_q_and_bounds_one_pass_cbr(cpi, bottom_index, top_index);
q = rc_pick_q_and_bounds_one_pass_cbr(cpi, width, height, bottom_index,
top_index);
else
q = rc_pick_q_and_bounds_one_pass_vbr(cpi, bottom_index, top_index);
q = rc_pick_q_and_bounds_one_pass_vbr(cpi, width, height, bottom_index,
top_index);
} else {
q = rc_pick_q_and_bounds_two_pass(cpi, bottom_index, top_index);
q = rc_pick_q_and_bounds_two_pass(cpi, width, height, bottom_index,
top_index);