summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
authorDeb Mukherjee <debargha@google.com>2013-12-03 17:05:19 -0800
committerDeb Mukherjee <debargha@google.com>2013-12-05 16:31:04 -0800
commit52d273674beab6efa96d36c4da672ee23813c7b4 (patch)
treeb31982bf15a1ea044328c90aa97a65b6a7ba0fff /vp9
parente7922a5b70964dff3841fffec21550bb4e931891 (diff)
downloadlibvpx-52d273674beab6efa96d36c4da672ee23813c7b4.tar
libvpx-52d273674beab6efa96d36c4da672ee23813c7b4.tar.gz
libvpx-52d273674beab6efa96d36c4da672ee23813c7b4.tar.bz2
libvpx-52d273674beab6efa96d36c4da672ee23813c7b4.zip
Further rate control cleanups
Includes various cleanups. Streamlines the interfaces so that all rate control state updates happen in the vp9_rc_postencode_update() function. This will hopefully make it easier to support multiple rate control schemes. Removes some unnecessary code, which in rare cases can casue a difference in the constrained quality mode output, but other than that there is no bitstream change yet. Change-Id: I3198cc37249932feea1e3691c0b2650e7b0c22fc
Diffstat (limited to 'vp9')
-rw-r--r--vp9/encoder/vp9_firstpass.c15
-rw-r--r--vp9/encoder/vp9_onyx_if.c163
-rw-r--r--vp9/encoder/vp9_onyx_int.h4
-rw-r--r--vp9/encoder/vp9_ratectrl.c204
-rw-r--r--vp9/encoder/vp9_ratectrl.h20
5 files changed, 184 insertions, 222 deletions
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index 50d803680..5ec0b765a 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -2170,21 +2170,6 @@ void vp9_second_pass(VP9_COMP *cpi) {
(int)(cpi->twopass.bits_left / frames_left);
cpi->twopass.est_max_qcorrection_factor = 1.0;
- // Set a cq_level in constrained quality mode.
- // Commenting this code out for now since it does not seem to be
- // working well.
- /*
- if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
- int est_cq = estimate_cq(cpi, &cpi->twopass.total_left_stats,
- section_target_bandwidth);
-
- if (est_cq > cpi->cq_target_quality)
- cpi->cq_target_quality = est_cq;
- else
- cpi->cq_target_quality = cpi->oxcf.cq_level;
- }
- */
-
// guess at maxq needed in 2nd pass
cpi->twopass.maxq_max_limit = cpi->rc.worst_quality;
cpi->twopass.maxq_min_limit = cpi->rc.best_quality;
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 968cbfbce..e724ecaa6 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -143,8 +143,9 @@ static INLINE void Scale2Ratio(int mode, int *hr, int *hs) {
}
}
-static void set_mvcost(VP9_COMP *cpi) {
+static void set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv) {
MACROBLOCK *const mb = &cpi->mb;
+ cpi->common.allow_high_precision_mv = allow_high_precision_mv;
if (cpi->common.allow_high_precision_mv) {
mb->mvcost = mb->nmvcost_hp;
mb->mvsadcost = mb->nmvsadcost_hp;
@@ -234,7 +235,7 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
// Computes a q delta (in "q index" terms) to get from a starting q value
// to a target value
// target q value
-int vp9_compute_qdelta(VP9_COMP *cpi, double qstart, double qtarget) {
+int vp9_compute_qdelta(const VP9_COMP *cpi, double qstart, double qtarget) {
int i;
int start_index = cpi->rc.worst_quality;
int target_index = cpi->rc.worst_quality;
@@ -1115,8 +1116,8 @@ static void init_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
vp9_change_config(ptr, oxcf);
// Initialize active best and worst q and average q values.
- cpi->rc.active_worst_quality = cpi->oxcf.worst_allowed_q;
- cpi->rc.active_best_quality = cpi->oxcf.best_allowed_q;
+ cpi->rc.active_worst_quality = cpi->oxcf.worst_allowed_q;
+
cpi->rc.avg_frame_qindex = cpi->oxcf.worst_allowed_q;
// Initialise the starting buffer levels
@@ -1205,8 +1206,7 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
cm->reset_frame_context = 0;
setup_features(cm);
- cpi->common.allow_high_precision_mv = 0; // Default mv precision
- set_mvcost(cpi);
+ set_high_precision_mv(cpi, 0);
{
int i;
@@ -1253,12 +1253,8 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
// active values should only be modified if out of new range
cpi->rc.active_worst_quality = clamp(cpi->rc.active_worst_quality,
- cpi->oxcf.best_allowed_q,
- cpi->oxcf.worst_allowed_q);
-
- cpi->rc.active_best_quality = clamp(cpi->rc.active_best_quality,
- cpi->oxcf.best_allowed_q,
- cpi->oxcf.worst_allowed_q);
+ cpi->rc.best_quality,
+ cpi->rc.worst_quality);
cpi->cq_target_quality = cpi->oxcf.cq_level;
@@ -2369,16 +2365,6 @@ static int find_fp_qindex() {
return i;
}
-static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest,
- unsigned int *frame_flags) {
- (void) size;
- (void) dest;
- (void) frame_flags;
-
- vp9_set_quantizer(cpi, find_fp_qindex());
- vp9_first_pass(cpi);
-}
-
#define WRITE_RECON_BUFFER 0
#if WRITE_RECON_BUFFER
void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) {
@@ -2470,16 +2456,9 @@ static int recode_loop_test(VP9_COMP *cpi,
cpi->rc.projected_frame_size <
((cpi->rc.this_frame_target * 7) >> 3)) {
force_recode = 1;
- } else if (q > cpi->oxcf.cq_level &&
- cpi->rc.projected_frame_size < cpi->rc.min_frame_bandwidth &&
- cpi->rc.active_best_quality > cpi->oxcf.cq_level) {
- // Severe undershoot and between auto and user cq level
- force_recode = 1;
- cpi->rc.active_best_quality = cpi->oxcf.cq_level;
}
}
}
-
return force_recode;
}
@@ -2639,7 +2618,7 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) {
if (cpi->twopass.total_left_stats.coded_error != 0.0)
fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %10d"
- "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"
+ "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"
"%6d %6d %5d %5d %5d %8.2f %10d %10.3f"
"%10.3f %8d %10d %10d %10d\n",
cpi->common.current_video_frame, cpi->rc.this_frame_target,
@@ -2650,7 +2629,6 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) {
(int)cpi->rc.total_actual_bits, cm->base_qindex,
vp9_convert_qindex_to_q(cm->base_qindex),
(double)vp9_dc_quant(cm->base_qindex, 0) / 4.0,
- vp9_convert_qindex_to_q(cpi->rc.active_best_quality),
vp9_convert_qindex_to_q(cpi->rc.active_worst_quality), cpi->rc.avg_q,
vp9_convert_qindex_to_q(cpi->rc.ni_av_qi),
vp9_convert_qindex_to_q(cpi->cq_target_quality),
@@ -2699,6 +2677,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
int overshoot_seen = 0;
int undershoot_seen = 0;
int q_low = bottom_index, q_high = top_index;
+
do {
vp9_clear_system_state(); // __asm emms;
@@ -2816,11 +2795,13 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
// Update rate_correction_factor unless
vp9_rc_update_rate_correction_factors(cpi, 0);
- *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target);
+ *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+ bottom_index, top_index);
while (*q < q_low && retries < 10) {
vp9_rc_update_rate_correction_factors(cpi, 0);
- *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target);
+ *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+ bottom_index, top_index);
retries++;
}
}
@@ -2831,18 +2812,12 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
q_high = *q > q_low ? *q - 1 : q_low;
if (overshoot_seen || loop_count > 1) {
- // Update rate_correction_factor unless
- // cpi->rc.active_worst_quality has changed.
vp9_rc_update_rate_correction_factors(cpi, 1);
-
*q = (q_high + q_low) / 2;
} else {
- // Update rate_correction_factor unless
- // cpi->rc.active_worst_quality has changed.
vp9_rc_update_rate_correction_factors(cpi, 0);
-
- *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target);
-
+ *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+ bottom_index, top_index);
// 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
@@ -2854,7 +2829,8 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
while (*q > q_high && retries < 10) {
vp9_rc_update_rate_correction_factors(cpi, 0);
- *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target);
+ *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+ bottom_index, top_index);
retries++;
}
}
@@ -2893,8 +2869,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
int q;
int frame_over_shoot_limit;
int frame_under_shoot_limit;
-
int top_index;
+ int top_index_prop;
int bottom_index;
SPEED_FEATURES *const sf = &cpi->sf;
@@ -3008,45 +2984,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
vp9_clear_system_state();
- // Decide how big to make the frame.
- vp9_rc_pick_frame_size_and_bounds(cpi,
- &frame_under_shoot_limit,
- &frame_over_shoot_limit);
-
- q = vp9_rc_pick_q_and_adjust_q_bounds(cpi,
- &bottom_index,
- &top_index);
-
-#if CONFIG_MULTIPLE_ARF
- // Force the quantizer determined by the coding order pattern.
- if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
- cpi->oxcf.end_usage != USAGE_CONSTANT_QUALITY) {
- double new_q;
- double current_q = vp9_convert_qindex_to_q(cpi->rc.active_worst_quality);
- int level = cpi->this_frame_weight;
- assert(level >= 0);
-
- // Set quantizer steps at 10% increments.
- new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level)));
- q = cpi->rc.active_worst_quality +
- vp9_compute_qdelta(cpi, current_q, new_q);
-
- bottom_index = q;
- top_index = q;
-
- printf("frame:%d q:%d\n", cm->current_video_frame, q);
- }
-#endif
-
vp9_zero(cpi->rd_tx_select_threshes);
- if (!frame_is_intra_only(cm)) {
- cm->mcomp_filter_type = DEFAULT_INTERP_FILTER;
- /* TODO: Decide this more intelligently */
- cm->allow_high_precision_mv = q < HIGH_PRECISION_MV_QTHRESH;
- set_mvcost(cpi);
- }
-
#if CONFIG_VP9_POSTPROC
if (cpi->oxcf.noise_sensitivity > 0) {
int l = 0;
@@ -3076,6 +3015,26 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
vp9_write_yuv_frame(cpi->Source);
#endif
+ // Decide how big to make the frame.
+ vp9_rc_pick_frame_size_target(cpi);
+
+ // Decide frame size bounds
+ vp9_rc_compute_frame_size_bounds(cpi, cpi->rc.this_frame_target,
+ &frame_under_shoot_limit,
+ &frame_over_shoot_limit);
+
+ // Decide q and q bounds
+ q = vp9_rc_pick_q_and_adjust_q_bounds(cpi,
+ &bottom_index,
+ &top_index,
+ &top_index_prop);
+
+ if (!frame_is_intra_only(cm)) {
+ cm->mcomp_filter_type = DEFAULT_INTERP_FILTER;
+ /* TODO: Decide this more intelligently */
+ set_high_precision_mv(cpi, (q < HIGH_PRECISION_MV_QTHRESH));
+ }
+
encode_with_recode_loop(cpi,
size,
dest,
@@ -3161,7 +3120,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
* needed in motion search besides loopfilter */
cm->last_frame_type = cm->frame_type;
- vp9_rc_postencode_update(cpi, *size, q);
+ vp9_rc_postencode_update(cpi, *size, top_index_prop);
#if 0
output_frame_level_debug_stats(cpi);
@@ -3282,6 +3241,21 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1;
}
+static void Pass0Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest,
+ unsigned int *frame_flags) {
+ encode_frame_to_data_rate(cpi, size, dest, frame_flags);
+}
+
+static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest,
+ unsigned int *frame_flags) {
+ (void) size;
+ (void) dest;
+ (void) frame_flags;
+
+ vp9_set_quantizer(cpi, find_fp_qindex());
+ vp9_first_pass(cpi);
+}
+
static void Pass2Encode(VP9_COMP *cpi, unsigned long *size,
unsigned char *dest, unsigned int *frame_flags) {
cpi->enable_encode_breakout = 1;
@@ -3293,27 +3267,6 @@ static void Pass2Encode(VP9_COMP *cpi, unsigned long *size,
// vp9_print_modes_and_motion_vectors(&cpi->common, "encode.stt");
vp9_twopass_postencode_update(cpi, *size);
-
- /*
-#ifdef DISABLE_RC_LONG_TERM_MEM
- cpi->twopass.bits_left -= cpi->rc.this_frame_target;
-#else
- cpi->twopass.bits_left -= 8 * *size;
-#endif
-
- if (!cpi->refresh_alt_ref_frame) {
- double lower_bounds_min_rate = FRAME_OVERHEAD_BITS * cpi->oxcf.framerate;
- double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth
- * cpi->oxcf.two_pass_vbrmin_section
- / 100);
-
- if (two_pass_min_rate < lower_bounds_min_rate)
- two_pass_min_rate = lower_bounds_min_rate;
-
- cpi->twopass.bits_left += (int64_t)(two_pass_min_rate
- / cpi->oxcf.framerate);
- }
- */
}
static void check_initial_width(VP9_COMP *cpi, YV12_BUFFER_CONFIG *sd) {
@@ -3386,8 +3339,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
cpi->source = NULL;
- cpi->common.allow_high_precision_mv = ALTREF_HIGH_PRECISION_MV;
- set_mvcost(cpi);
+ set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
// Should we code an alternate reference frame.
if (cpi->oxcf.play_alternate && cpi->source_alt_ref_pending) {
@@ -3627,7 +3579,8 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
} else if (cpi->pass == 2) {
Pass2Encode(cpi, size, dest, frame_flags);
} else {
- encode_frame_to_data_rate(cpi, size, dest, frame_flags);
+ // One pass encode
+ Pass0Encode(cpi, size, dest, frame_flags);
}
if (cm->refresh_frame_context)
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index b8602e094..c6315653e 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -338,7 +338,7 @@ typedef struct {
int worst_quality;
int active_worst_quality;
int best_quality;
- int active_best_quality;
+ // int active_best_quality;
} RATE_CONTROL;
typedef struct VP9_COMP {
@@ -695,7 +695,7 @@ int vp9_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest);
void vp9_alloc_compressor_data(VP9_COMP *cpi);
-int vp9_compute_qdelta(VP9_COMP *cpi, double qstart, double qtarget);
+int vp9_compute_qdelta(const VP9_COMP *cpi, double qstart, double qtarget);
static int get_token_alloc(int mb_rows, int mb_cols) {
return mb_rows * mb_cols * (48 * 16 + 4);
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index bf1fc4f31..d631b3145 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -45,6 +45,10 @@ static int gf_high_motion_minq[QINDEX_RANGE];
static int inter_minq[QINDEX_RANGE];
static int afq_low_motion_minq[QINDEX_RANGE];
static int afq_high_motion_minq[QINDEX_RANGE];
+static int gf_high = 2000;
+static int gf_low = 400;
+static int kf_high = 5000;
+static int kf_low = 400;
// Functions to compute the active minq lookup table entries based on a
// formulaic approach to facilitate easier adjustment of the Q tables.
@@ -84,7 +88,7 @@ void vp9_rc_init_minq_luts(void) {
kf_high_motion_minq[i] = calculate_minq_index(maxq,
0.000002,
-0.0012,
- 0.5,
+ 0.50,
0.0);
gf_low_motion_minq[i] = calculate_minq_index(maxq,
@@ -97,11 +101,6 @@ void vp9_rc_init_minq_luts(void) {
-0.00125,
0.50,
0.0);
- inter_minq[i] = calculate_minq_index(maxq,
- 0.00000271,
- -0.00113,
- 0.75,
- 0.0);
afq_low_motion_minq[i] = calculate_minq_index(maxq,
0.0000015,
-0.0009,
@@ -112,6 +111,11 @@ void vp9_rc_init_minq_luts(void) {
-0.00125,
0.55,
0.0);
+ inter_minq[i] = calculate_minq_index(maxq,
+ 0.00000271,
+ -0.00113,
+ 0.75,
+ 0.0);
}
}
@@ -285,7 +289,6 @@ static void calc_pframe_target_size(VP9_COMP *cpi) {
}
}
-
void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) {
const int q = cpi->common.base_qindex;
int correction_factor = 100;
@@ -333,7 +336,6 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) {
break;
}
- // if ( (correction_factor > 102) && (Q < cpi->rc.active_worst_quality) )
if (correction_factor > 102) {
// We are not already at the worst allowable quality
correction_factor =
@@ -367,8 +369,9 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) {
}
-int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) {
- int q = cpi->rc.active_worst_quality;
+int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
+ int active_best_quality, int active_worst_quality) {
+ int q = active_worst_quality;
int i;
int last_error = INT_MAX;
@@ -396,7 +399,7 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) {
target_bits_per_mb =
(target_bits_per_frame << BPER_MB_NORMBITS) / cpi->common.MBs;
- i = cpi->rc.active_best_quality;
+ i = active_best_quality;
do {
bits_per_mb_at_this_q = (int)vp9_rc_bits_per_mb(cpi->common.frame_type, i,
@@ -412,7 +415,7 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) {
} else {
last_error = bits_per_mb_at_this_q - target_bits_per_mb;
}
- } while (++i <= cpi->rc.active_worst_quality);
+ } while (++i <= active_worst_quality);
return q;
}
@@ -438,14 +441,17 @@ static int get_active_quality(int q,
return active_best_quality;
}
-int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
+int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
int *bottom_index,
- int *top_index) {
- // Set an active best quality and if necessary active worst quality
- int q = cpi->rc.active_worst_quality;
- VP9_COMMON *const cm = &cpi->common;
+ int *top_index,
+ int *top_index_prop) {
+ const VP9_COMMON *const cm = &cpi->common;
+ int active_best_quality;
+ int active_worst_quality = cpi->rc.active_worst_quality;
+ int q;
if (frame_is_intra_only(cm)) {
+ active_best_quality = cpi->rc.best_quality;
#if !CONFIG_MULTIPLE_ARF
// Handle the special case for key frames forced when we have75 reached
// the maximum key frame interval. Here force the Q to a range
@@ -457,25 +463,19 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
delta_qindex = vp9_compute_qdelta(cpi, last_boosted_q,
(last_boosted_q * 0.75));
-
- cpi->rc.active_best_quality = MAX(qindex + delta_qindex,
- cpi->rc.best_quality);
- } else if (cpi->pass == 0 && cpi->common.current_video_frame == 0) {
- // If this is the first (key) frame in 1-pass, active best/worst is
- // the user best/worst-allowed, and leave the top_index to active_worst.
- cpi->rc.active_best_quality = cpi->oxcf.best_allowed_q;
- cpi->rc.active_worst_quality = cpi->oxcf.worst_allowed_q;
- } else {
- int high = 5000;
- int low = 400;
+ active_best_quality = MAX(qindex + delta_qindex,
+ cpi->rc.best_quality);
+ } else if (!(cpi->pass == 0 && cpi->common.current_video_frame == 0)) {
+ // not first frame of one pass
double q_adj_factor = 1.0;
double q_val;
// Baseline value derived from cpi->active_worst_quality and kf boost
- cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.kf_boost,
- low, high,
- kf_low_motion_minq,
- kf_high_motion_minq);
+ active_best_quality = get_active_quality(active_worst_quality,
+ cpi->rc.kf_boost,
+ kf_low, kf_high,
+ kf_low_motion_minq,
+ kf_high_motion_minq);
// Allow somewhat lower kf minq with small image formats.
if ((cm->width * cm->height) <= (352 * 288)) {
@@ -487,124 +487,128 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
// Convert the adjustment factor to a qindex delta
// on active_best_quality.
- q_val = vp9_convert_qindex_to_q(cpi->rc.active_best_quality);
- cpi->rc.active_best_quality +=
+ q_val = vp9_convert_qindex_to_q(active_best_quality);
+ active_best_quality +=
vp9_compute_qdelta(cpi, q_val, (q_val * q_adj_factor));
}
#else
double current_q;
// Force the KF quantizer to be 30% of the active_worst_quality.
- current_q = vp9_convert_qindex_to_q(cpi->rc.active_worst_quality);
- cpi->rc.active_best_quality = cpi->rc.active_worst_quality
+ current_q = vp9_convert_qindex_to_q(active_worst_quality);
+ active_best_quality = active_worst_quality
+ vp9_compute_qdelta(cpi, current_q, current_q * 0.3);
#endif
} else if (!cpi->is_src_frame_alt_ref &&
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
- int high = 2000;
- int low = 400;
- // Use the lower of cpi->rc.active_worst_quality and recent
+ // Use the lower of active_worst_quality and recent
// average Q as basis for GF/ARF best Q limit unless last frame was
// a key frame.
if (cpi->frames_since_key > 1 &&
- cpi->rc.avg_frame_qindex < cpi->rc.active_worst_quality) {
+ cpi->rc.avg_frame_qindex < active_worst_quality) {
q = cpi->rc.avg_frame_qindex;
+ } else {
+ q = active_worst_quality;
}
// For constrained quality dont allow Q less than the cq level
if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
if (q < cpi->cq_target_quality)
q = cpi->cq_target_quality;
if (cpi->frames_since_key > 1) {
- cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
- low, high,
- afq_low_motion_minq,
- afq_high_motion_minq);
+ active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
+ gf_low, gf_high,
+ afq_low_motion_minq,
+ afq_high_motion_minq);
} else {
- cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
- low, high,
- gf_low_motion_minq,
- gf_high_motion_minq);
+ active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
+ gf_low, gf_high,
+ gf_low_motion_minq,
+ gf_high_motion_minq);
}
// Constrained quality use slightly lower active best.
- cpi->rc.active_best_quality = cpi->rc.active_best_quality * 15 / 16;
+ active_best_quality = active_best_quality * 15 / 16;
} else if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
if (!cpi->refresh_alt_ref_frame) {
- cpi->rc.active_best_quality = cpi->cq_target_quality;
+ active_best_quality = cpi->cq_target_quality;
} else {
if (cpi->frames_since_key > 1) {
- cpi->rc.active_best_quality = get_active_quality(
- q, cpi->rc.gfu_boost, low, high,
+ active_best_quality = get_active_quality(
+ q, cpi->rc.gfu_boost, gf_low, gf_high,
afq_low_motion_minq, afq_high_motion_minq);
} else {
- cpi->rc.active_best_quality = get_active_quality(
- q, cpi->rc.gfu_boost, low, high,
+ active_best_quality = get_active_quality(
+ q, cpi->rc.gfu_boost, gf_low, gf_high,
gf_low_motion_minq, gf_high_motion_minq);
}
}
} else {
- cpi->rc.active_best_quality = get_active_quality(
- q, cpi->rc.gfu_boost, low, high,
- gf_low_motion_minq, gf_high_motion_minq);
+ active_best_quality = get_active_quality(
+ q, cpi->rc.gfu_boost, gf_low, gf_high,
+ gf_low_motion_minq, gf_high_motion_minq);
}
} else {
if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
- cpi->rc.active_best_quality = cpi->cq_target_quality;
+ active_best_quality = cpi->cq_target_quality;
} else {
- cpi->rc.active_best_quality = inter_minq[q];
- // 1-pass: for now, use the average Q for the active_best, if its lower
- // than active_worst.
- if (cpi->pass == 0 && (cpi->rc.avg_frame_qindex < q))
- cpi->rc.active_best_quality = inter_minq[cpi->rc.avg_frame_qindex];
+ if (cpi->pass == 0 &&
+ cpi->rc.avg_frame_qindex < active_worst_quality)
+ // 1-pass: for now, use the average Q for the active_best, if its lower
+ // than active_worst.
+ active_best_quality = inter_minq[cpi->rc.avg_frame_qindex];
+ else
+ active_best_quality = inter_minq[active_worst_quality];
// For the constrained quality mode we don't want
// q to fall below the cq level.
if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
- (cpi->rc.active_best_quality < cpi->cq_target_quality)) {
+ (active_best_quality < cpi->cq_target_quality)) {
// If we are strongly undershooting the target rate in the last
// frames then use the user passed in cq value not the auto
// cq value.
if (cpi->rc.rolling_actual_bits < cpi->rc.min_frame_bandwidth)
- cpi->rc.active_best_quality = cpi->oxcf.cq_level;
+ active_best_quality = cpi->oxcf.cq_level;
else
- cpi->rc.active_best_quality = cpi->cq_target_quality;
+ active_best_quality = cpi->cq_target_quality;
}
}
}
// Clip the active best and worst quality values to limits
- if (cpi->rc.active_worst_quality > cpi->rc.worst_quality)
- cpi->rc.active_worst_quality = cpi->rc.worst_quality;
+ if (active_worst_quality > cpi->rc.worst_quality)
+ active_worst_quality = cpi->rc.worst_quality;
- if (cpi->rc.active_best_quality < cpi->rc.best_quality)
- cpi->rc.active_best_quality = cpi->rc.best_quality;
+ if (active_best_quality < cpi->rc.best_quality)
+ active_best_quality = cpi->rc.best_quality;
- if (cpi->rc.active_best_quality > cpi->rc.worst_quality)
- cpi->rc.active_best_quality = cpi->rc.worst_quality;
+ if (active_best_quality > cpi->rc.worst_quality)
+ active_best_quality = cpi->rc.worst_quality;
- if (cpi->rc.active_worst_quality < cpi->rc.active_best_quality)
- cpi->rc.active_worst_quality = cpi->rc.active_best_quality;
+ if (active_worst_quality < active_best_quality)
+ active_worst_quality = active_best_quality;
- *top_index = cpi->rc.active_worst_quality;
- *bottom_index = cpi->rc.active_best_quality;
+ *top_index_prop = active_worst_quality;
+ *top_index = active_worst_quality;
+ *bottom_index = active_best_quality;
#if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
// Limit Q range for the adaptive loop.
if (cm->frame_type == KEY_FRAME && !cpi->this_key_frame_forced) {
if (!(cpi->pass == 0 && cpi->common.current_video_frame == 0)) {
+ *top_index = active_worst_quality;
*top_index =
- (cpi->rc.active_worst_quality + cpi->rc.active_best_quality * 3) / 4;
+ (active_worst_quality + active_best_quality * 3) / 4;
}
} else if (!cpi->is_src_frame_alt_ref &&
(cpi->oxcf.end_usage != USAGE_STREAM_FROM_SERVER) &&
(cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
*top_index =
- (cpi->rc.active_worst_quality + cpi->rc.active_best_quality) / 2;
+ (active_worst_quality + active_best_quality) / 2;
}
#endif
if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
- q = cpi->rc.active_best_quality;
+ q = active_best_quality;
// Special case code to try and match quality with forced key frames
} else if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
q = cpi->rc.last_boosted_qindex;
@@ -614,17 +618,35 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
// 1-pass: for now, use per-frame-bw for target size of frame, scaled
// by |x| for key frame.
int scale = (cm->frame_type == KEY_FRAME) ? 5 : 1;
- q = vp9_rc_regulate_q(cpi, scale * cpi->rc.av_per_frame_bandwidth);
+ q = vp9_rc_regulate_q(cpi, scale * cpi->rc.av_per_frame_bandwidth,
+ active_best_quality, active_worst_quality);
} else {
- q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target);
+ q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+ active_best_quality, active_worst_quality);
}
if (q > *top_index)
q = *top_index;
}
+#if CONFIG_MULTIPLE_ARF
+ // Force the quantizer determined by the coding order pattern.
+ if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
+ cpi->oxcf.end_usage != USAGE_CONSTANT_QUALITY) {
+ double new_q;
+ double current_q = vp9_convert_qindex_to_q(active_worst_quality);
+ int level = cpi->this_frame_weight;
+ assert(level >= 0);
+ new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level)));
+ q = active_worst_quality +
+ vp9_compute_qdelta(cpi, current_q, new_q);
+
+ *bottom_index = q;
+ *top_index = q;
+ printf("frame:%d q:%d\n", cm->current_video_frame, q);
+ }
+#endif
return q;
}
-
static int estimate_keyframe_frequency(VP9_COMP *cpi) {
int i;
@@ -680,8 +702,7 @@ static void adjust_key_frame_context(VP9_COMP *cpi) {
cpi->rc.key_frame_count++;
}
-
-static void compute_frame_size_bounds(const VP9_COMP *cpi,
+void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi,
int this_frame_target,
int *frame_under_shoot_limit,
int *frame_over_shoot_limit) {
@@ -720,9 +741,7 @@ static void compute_frame_size_bounds(const VP9_COMP *cpi,
}
// return of 0 means drop frame
-int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi,
- int *frame_under_shoot_limit,
- int *frame_over_shoot_limit) {
+int vp9_rc_pick_frame_size_target(VP9_COMP *cpi) {
VP9_COMMON *cm = &cpi->common;
if (cm->frame_type == KEY_FRAME)
@@ -733,13 +752,11 @@ int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi,
// Target rate per SB64 (including partial SB64s.
cpi->rc.sb64_target_rate = ((int64_t)cpi->rc.this_frame_target * 64 * 64) /
(cpi->common.width * cpi->common.height);
- compute_frame_size_bounds(cpi, cpi->rc.this_frame_target,
- frame_under_shoot_limit, frame_over_shoot_limit);
-
return 1;
}
-void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) {
+void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used,
+ int worst_q) {
VP9_COMMON *const cm = &cpi->common;
// Update rate control heuristics
cpi->rc.projected_frame_size = (bytes_used << 3);
@@ -750,6 +767,7 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) {
cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) ? 2 : 0);
cpi->rc.last_q[cm->frame_type] = cm->base_qindex;
+ cpi->rc.active_worst_quality = worst_q;
// Keep record of last boosted (KF/KF/ARF) Q value.
// If the current frame is coded at a lower Q then we also update it.
@@ -777,11 +795,11 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) {
if (cm->frame_type != KEY_FRAME &&
!cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
cpi->rc.ni_frames++;
- cpi->rc.tot_q += vp9_convert_qindex_to_q(q);
+ cpi->rc.tot_q += vp9_convert_qindex_to_q(cm->base_qindex);
cpi->rc.avg_q = cpi->rc.tot_q / (double)cpi->rc.ni_frames;
// Calculate the average Q for normal inter frames (not key or GFU frames).
- cpi->rc.ni_tot_qi += q;
+ cpi->rc.ni_tot_qi += cm->base_qindex;
cpi->rc.ni_av_qi = cpi->rc.ni_tot_qi / cpi->rc.ni_frames;
}
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index f01d18672..063ac8f6a 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -31,23 +31,29 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var);
void vp9_rc_init_minq_luts(void);
// return of 0 means drop frame
-// Changes rc.this_frame_target and rc.sb64_rate_target
-int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi,
+// Changes only rc.this_frame_target and rc.sb64_rate_target
+int vp9_rc_pick_frame_size_target(VP9_COMP *cpi);
+
+void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi,
+ int this_frame_target,
int *frame_under_shoot_limit,
int *frame_over_shoot_limit);
+
// Picks q and q bounds given the target for bits
-int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
- int * bottom_index,
- int * top_index);
+int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
+ int *bottom_index,
+ int *top_index,
+ int *top_index_prop);
// Estimates q to achieve a target bits per frame
-int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame);
+int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
+ int active_best_quality, int active_worst_quality);
// Post encode update of the rate control parameters based
// on bytes used and q used for the frame
void vp9_rc_postencode_update(VP9_COMP *cpi,
uint64_t bytes_used,
- int q_used);
+ int worst_q);
// estimates bits per mb for a given qindex and correction factor
int vp9_rc_bits_per_mb(FRAME_TYPE frame_type, int qindex,