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
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index b92befb..a90cb88 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -94,9 +94,11 @@
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 @@
}
}
-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 @@
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 @@
}
}
-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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
#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 @@
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 @@
}
} 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 @@
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);
}
return q;
@@ -1171,7 +1185,8 @@
}
}
-void av1_rc_set_frame_target(AV1_COMP *cpi, int target) {
+static void rc_set_frame_target(AV1_COMP *cpi, int target, int width,
+ int height) {
const AV1_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
@@ -1180,11 +1195,11 @@
// Modify frame size target when down-scaled.
if (!av1_frame_unscaled(cm))
rc->this_frame_target =
- (int)(rc->this_frame_target * av1_resize_rate_factor(cpi));
+ (int)(rc->this_frame_target * resize_rate_factor(cpi, width, height));
// Target rate per SB64 (including partial SB64s.
- rc->sb64_target_rate = (int)((int64_t)rc->this_frame_target * 64 * 64) /
- (cm->width * cm->height);
+ rc->sb64_target_rate =
+ (int)((int64_t)rc->this_frame_target * 64 * 64) / (width * height);
}
static void update_alt_ref_frame_stats(AV1_COMP *cpi) {
@@ -1258,7 +1273,7 @@
rc->projected_frame_size = (int)(bytes_used << 3);
// Post encode loop adjustment of Q prediction.
- av1_rc_update_rate_correction_factors(cpi);
+ av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
// Keep a record of last Q and ambient average Q.
if (cm->frame_type == KEY_FRAME) {
@@ -1305,6 +1320,10 @@
// Rolling monitors of whether we are over or underspending used to help
// regulate min and Max Q in two pass.
+ if (!av1_frame_unscaled(cm))
+ rc->this_frame_target =
+ (int)(rc->this_frame_target /
+ resize_rate_factor(cpi, cm->width, cm->height));
if (cm->frame_type != KEY_FRAME) {
rc->rolling_target_bits = ROUND_POWER_OF_TWO(
rc->rolling_target_bits * 3 + rc->this_frame_target, 2);
@@ -1349,6 +1368,12 @@
rc->frames_since_key++;
rc->frames_to_key--;
}
+ // if (cm->current_video_frame == 1 && cm->show_frame)
+ /*
+ rc->this_frame_target =
+ (int)(rc->this_frame_target / resize_rate_factor(cpi, cm->width,
+ cm->height));
+ */
}
void av1_rc_postencode_update_drop_frame(AV1_COMP *cpi) {
@@ -1423,7 +1448,7 @@
target = calc_iframe_target_size_one_pass_vbr(cpi);
else
target = calc_pframe_target_size_one_pass_vbr(cpi);
- av1_rc_set_frame_target(cpi, target);
+ rc_set_frame_target(cpi, target, cm->width, cm->height);
}
static int calc_pframe_target_size_one_pass_cbr(const AV1_COMP *cpi) {
@@ -1525,7 +1550,7 @@
else
target = calc_pframe_target_size_one_pass_cbr(cpi);
- av1_rc_set_frame_target(cpi, target);
+ rc_set_frame_target(cpi, target, cm->width, cm->height);
// TODO(afergs): Decide whether to scale up, down, or not at all
}
@@ -1610,11 +1635,11 @@
}
}
-void av1_rc_update_framerate(AV1_COMP *cpi) {
- const AV1_COMMON *const cm = &cpi->common;
+void av1_rc_update_framerate(AV1_COMP *cpi, int width, int height) {
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
RATE_CONTROL *const rc = &cpi->rc;
int vbr_max_bits;
+ const int MBs = av1_get_MBs(width, height);
rc->avg_frame_bandwidth = (int)(oxcf->target_bandwidth / cpi->framerate);
rc->min_frame_bandwidth =
@@ -1634,7 +1659,7 @@
(int)(((int64_t)rc->avg_frame_bandwidth * oxcf->two_pass_vbrmax_section) /
100);
rc->max_frame_bandwidth =
- AOMMAX(AOMMAX((cm->MBs * MAX_MB_RATE), MAXRATE_1080P), vbr_max_bits);
+ AOMMAX(AOMMAX((MBs * MAX_MB_RATE), MAXRATE_1080P), vbr_max_bits);
av1_rc_set_gf_interval_range(cpi, rc);
}
@@ -1683,68 +1708,12 @@
}
}
-void av1_set_target_rate(AV1_COMP *cpi) {
+void av1_set_target_rate(AV1_COMP *cpi, int width, int height) {
RATE_CONTROL *const rc = &cpi->rc;
int target_rate = rc->base_frame_target;
// Correction to rate target based on prior over or under shoot.
if (cpi->oxcf.rc_mode == AOM_VBR || cpi->oxcf.rc_mode == AOM_CQ)
vbr_rate_correction(cpi, &target_rate);
- av1_rc_set_frame_target(cpi, target_rate);
+ rc_set_frame_target(cpi, target_rate, width, height);
}
-
-uint8_t av1_calculate_next_resize_scale(const AV1_COMP *cpi) {
- 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_DYNAMIC:
- // RESIZE_DYNAMIC: Just random for now.
- new_num = lcg_rand16(&seed) % 4 + 13;
- break;
- default: assert(0);
- }
- return new_num;
-}
-
-#if CONFIG_FRAME_SUPERRES
-// TODO(afergs): Rename av1_rc_update_superres_scale(...)?
-uint8_t av1_calculate_next_superres_scale(const AV1_COMP *cpi, int width,
- int height) {
- static unsigned int seed = 34567;
- const AV1EncoderConfig *oxcf = &cpi->oxcf;
- if (oxcf->pass == 1) return SCALE_DENOMINATOR;
- uint8_t new_num = SCALE_DENOMINATOR;
-
- 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_DYNAMIC:
- // SUPERRES_DYNAMIC: Just random for now.
- new_num = lcg_rand16(&seed) % 9 + 8;
- break;
- default: assert(0);
- }
-
- // Make sure overall reduction is no more than 1/2 of the source size.
- av1_calculate_scaled_size(&width, &height, new_num);
- if (width * 2 < oxcf->width || height * 2 < oxcf->height)
- new_num = SCALE_DENOMINATOR;
-
- return new_num;
-}
-#endif // CONFIG_FRAME_SUPERRES