Index: source/libvpx/vp9/encoder/vp9_firstpass.c |
diff --git a/source/libvpx/vp9/encoder/vp9_firstpass.c b/source/libvpx/vp9/encoder/vp9_firstpass.c |
index 3f28e0ff346b5728e91e1457274b9a2cd535d232..9752668b15df0bba9cb9c6b08b524dcef71a1ec4 100644 |
--- a/source/libvpx/vp9/encoder/vp9_firstpass.c |
+++ b/source/libvpx/vp9/encoder/vp9_firstpass.c |
@@ -38,7 +38,7 @@ |
#define OUTPUT_FPF 0 |
#define ARF_STATS_OUTPUT 0 |
-#define GROUP_ADAPTIVE_MAXQ 0 |
+#define GROUP_ADAPTIVE_MAXQ 1 |
#define BOOST_BREAKOUT 12.5 |
#define BOOST_FACTOR 12.5 |
@@ -51,7 +51,6 @@ |
#define KF_MAX_BOOST 128.0 |
#define MIN_ARF_GF_BOOST 240 |
#define MIN_DECAY_FACTOR 0.01 |
-#define MIN_GF_INTERVAL 4 |
#define MIN_KF_BOOST 300 |
#define NEW_MV_MODE_PENALTY 32 |
#define SVC_FACTOR_PT_LOW 0.45 |
@@ -61,12 +60,9 @@ |
#define RC_FACTOR_MAX 1.75 |
-#define INTRA_WEIGHT_EXPERIMENT 0 |
-#if INTRA_WEIGHT_EXPERIMENT |
#define NCOUNT_INTRA_THRESH 8192 |
#define NCOUNT_INTRA_FACTOR 3 |
#define NCOUNT_FRAME_II_THRESH 5.0 |
-#endif |
#define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x) - 0.000001 : (x) + 0.000001) |
@@ -361,7 +357,7 @@ static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x, |
MV tmp_mv = {0, 0}; |
MV ref_mv_full = {ref_mv->row >> 3, ref_mv->col >> 3}; |
int num00, tmp_err, n; |
- const BLOCK_SIZE bsize = xd->mi[0].src_mi->mbmi.sb_type; |
+ const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type; |
vp9_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[bsize]; |
const int new_mv_mode_penalty = NEW_MV_MODE_PENALTY; |
@@ -570,8 +566,8 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { |
vp9_setup_pre_planes(xd, 0, first_ref_buf, 0, 0, NULL); |
} |
- xd->mi = cm->mi; |
- xd->mi[0].src_mi = &xd->mi[0]; |
+ xd->mi = cm->mi_grid_visible; |
+ xd->mi[0] = cm->mi; |
vp9_frame_init_quantizer(cpi); |
@@ -624,8 +620,8 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { |
xd->plane[1].dst.buf = new_yv12->u_buffer + recon_uvoffset; |
xd->plane[2].dst.buf = new_yv12->v_buffer + recon_uvoffset; |
xd->left_available = (mb_col != 0); |
- xd->mi[0].src_mi->mbmi.sb_type = bsize; |
- xd->mi[0].src_mi->mbmi.ref_frame[0] = INTRA_FRAME; |
+ xd->mi[0]->mbmi.sb_type = bsize; |
+ xd->mi[0]->mbmi.ref_frame[0] = INTRA_FRAME; |
set_mi_row_col(xd, &tile, |
mb_row << 1, num_8x8_blocks_high_lookup[bsize], |
mb_col << 1, num_8x8_blocks_wide_lookup[bsize], |
@@ -633,8 +629,8 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { |
// Do intra 16x16 prediction. |
x->skip_encode = 0; |
- xd->mi[0].src_mi->mbmi.mode = DC_PRED; |
- xd->mi[0].src_mi->mbmi.tx_size = use_dc_pred ? |
+ xd->mi[0]->mbmi.mode = DC_PRED; |
+ xd->mi[0]->mbmi.tx_size = use_dc_pred ? |
(bsize >= BLOCK_16X16 ? TX_16X16 : TX_8X8) : TX_4X4; |
vp9_encode_intra_block_plane(x, bsize, 0); |
this_error = vp9_get_mb_ss(x->plane[0].src_diff); |
@@ -832,7 +828,6 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { |
// Keep a count of cases where the inter and intra were very close |
// and very low. This helps with scene cut detection for example in |
// cropped clips with black bars at the sides or top and bottom. |
-#if INTRA_WEIGHT_EXPERIMENT |
if (((this_error - intrapenalty) * 9 <= motion_error * 10) && |
(this_error < (2 * intrapenalty))) { |
neutral_count += 1.0; |
@@ -843,21 +838,15 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { |
neutral_count += (double)motion_error / |
DOUBLE_DIVIDE_CHECK((double)this_error); |
} |
-#else |
- if (((this_error - intrapenalty) * 9 <= motion_error * 10) && |
- (this_error < (2 * intrapenalty))) { |
- neutral_count += 1.0; |
- } |
-#endif |
mv.row *= 8; |
mv.col *= 8; |
this_error = motion_error; |
- xd->mi[0].src_mi->mbmi.mode = NEWMV; |
- xd->mi[0].src_mi->mbmi.mv[0].as_mv = mv; |
- xd->mi[0].src_mi->mbmi.tx_size = TX_4X4; |
- xd->mi[0].src_mi->mbmi.ref_frame[0] = LAST_FRAME; |
- xd->mi[0].src_mi->mbmi.ref_frame[1] = NONE; |
+ xd->mi[0]->mbmi.mode = NEWMV; |
+ xd->mi[0]->mbmi.mv[0].as_mv = mv; |
+ xd->mi[0]->mbmi.tx_size = TX_4X4; |
+ xd->mi[0]->mbmi.ref_frame[0] = LAST_FRAME; |
+ xd->mi[0]->mbmi.ref_frame[1] = NONE; |
vp9_build_inter_predictors_sby(xd, mb_row << 1, mb_col << 1, bsize); |
vp9_encode_sby_pass1(x, bsize); |
sum_mvr += mv.row; |
@@ -1291,11 +1280,10 @@ static double get_sr_decay_rate(const VP9_COMP *cpi, |
frame->pcnt_motion * ((frame->mvc_abs + frame->mvr_abs) / 2); |
modified_pct_inter = frame->pcnt_inter; |
-#if INTRA_WEIGHT_EXPERIMENT |
if ((frame->intra_error / DOUBLE_DIVIDE_CHECK(frame->coded_error)) < |
- (double)NCOUNT_FRAME_II_THRESH) |
+ (double)NCOUNT_FRAME_II_THRESH) { |
modified_pct_inter = frame->pcnt_inter - frame->pcnt_neutral; |
-#endif |
+ } |
modified_pcnt_intra = 100 * (1.0 - modified_pct_inter); |
@@ -1334,14 +1322,17 @@ static double get_prediction_decay_rate(const VP9_COMP *cpi, |
// Function to test for a condition where a complex transition is followed |
// by a static section. For example in slide shows where there is a fade |
// between slides. This is to help with more optimal kf and gf positioning. |
-static int detect_transition_to_still(const TWO_PASS *twopass, |
+static int detect_transition_to_still(VP9_COMP *cpi, |
int frame_interval, int still_interval, |
double loop_decay_rate, |
double last_decay_rate) { |
+ TWO_PASS *const twopass = &cpi->twopass; |
+ RATE_CONTROL *const rc = &cpi->rc; |
+ |
// Break clause to detect very still sections after motion |
// For example a static image after a fade or other transition |
// instead of a clean scene cut. |
- if (frame_interval > MIN_GF_INTERVAL && |
+ if (frame_interval > rc->min_gf_interval && |
loop_decay_rate >= 0.999 && |
last_decay_rate < 0.9) { |
int j; |
@@ -1849,7 +1840,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { |
int int_lbq = |
(int)(vp9_convert_qindex_to_q(rc->last_boosted_qindex, |
cpi->common.bit_depth)); |
- active_min_gf_interval = MIN_GF_INTERVAL + MIN(2, int_max_q / 200); |
+ active_min_gf_interval = rc->min_gf_interval + MIN(2, int_max_q / 200); |
if (active_min_gf_interval > rc->max_gf_interval) |
active_min_gf_interval = rc->max_gf_interval; |
@@ -1863,6 +1854,8 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { |
active_max_gf_interval = 12 + MIN(4, (int_lbq / 6)); |
if (active_max_gf_interval > rc->max_gf_interval) |
active_max_gf_interval = rc->max_gf_interval; |
+ if (active_max_gf_interval < active_min_gf_interval) |
+ active_max_gf_interval = active_min_gf_interval; |
} |
} |
@@ -1903,7 +1896,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { |
// Break clause to detect very still sections after motion. For example, |
// a static image after a fade or other transition. |
- if (detect_transition_to_still(twopass, i, 5, loop_decay_rate, |
+ if (detect_transition_to_still(cpi, i, 5, loop_decay_rate, |
last_loop_decay_rate)) { |
allow_alt_ref = 0; |
break; |
@@ -1969,7 +1962,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { |
// Should we use the alternate reference frame. |
if (allow_alt_ref && |
(i < cpi->oxcf.lag_in_frames) && |
- (i >= MIN_GF_INTERVAL)) { |
+ (i >= rc->min_gf_interval)) { |
// Calculate the boost for alt ref. |
rc->gfu_boost = calc_arf_boost(cpi, 0, (i - 1), (i - 1), &f_boost, |
&b_boost); |
@@ -2058,29 +2051,61 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { |
} |
} |
-// TODO(PGW) Re-examine the use of II ration in this code in the light of# |
-// changes elsewhere |
+// Threshold for use of the lagging second reference frame. High second ref |
+// usage may point to a transient event like a flash or occlusion rather than |
+// a real scene cut. |
+#define SECOND_REF_USEAGE_THRESH 0.1 |
+// Minimum % intra coding observed in first pass (1.0 = 100%) |
+#define MIN_INTRA_LEVEL 0.25 |
+// Minimum ratio between the % of intra coding and inter coding in the first |
+// pass after discounting neutral blocks (discounting neutral blocks in this |
+// way helps catch scene cuts in clips with very flat areas or letter box |
+// format clips with image padding. |
+#define INTRA_VS_INTER_THRESH 2.0 |
+// Hard threshold where the first pass chooses intra for almost all blocks. |
+// In such a case even if the frame is not a scene cut coding a key frame |
+// may be a good option. |
+#define VERY_LOW_INTER_THRESH 0.05 |
+// Maximum threshold for the relative ratio of intra error score vs best |
+// inter error score. |
+#define KF_II_ERR_THRESHOLD 2.5 |
+// In real scene cuts there is almost always a sharp change in the intra |
+// or inter error score. |
+#define ERR_CHANGE_THRESHOLD 0.4 |
+// For real scene cuts we expect an improvment in the intra inter error |
+// ratio in the next frame. |
+#define II_IMPROVEMENT_THRESHOLD 3.5 |
#define KF_II_MAX 128.0 |
+ |
static int test_candidate_kf(TWO_PASS *twopass, |
const FIRSTPASS_STATS *last_frame, |
const FIRSTPASS_STATS *this_frame, |
const FIRSTPASS_STATS *next_frame) { |
int is_viable_kf = 0; |
+ double pcnt_intra = 1.0 - this_frame->pcnt_inter; |
+ double modified_pcnt_inter = |
+ this_frame->pcnt_inter - this_frame->pcnt_neutral; |
// Does the frame satisfy the primary criteria of a key frame? |
+ // See above for an explanation of the test criteria. |
// If so, then examine how well it predicts subsequent frames. |
- if ((this_frame->pcnt_second_ref < 0.10) && |
- (next_frame->pcnt_second_ref < 0.10) && |
- ((this_frame->pcnt_inter < 0.05) || |
- (((this_frame->pcnt_inter - this_frame->pcnt_neutral) < 0.35) && |
+ if ((this_frame->pcnt_second_ref < SECOND_REF_USEAGE_THRESH) && |
+ (next_frame->pcnt_second_ref < SECOND_REF_USEAGE_THRESH) && |
+ ((this_frame->pcnt_inter < VERY_LOW_INTER_THRESH) || |
+ ((pcnt_intra > MIN_INTRA_LEVEL) && |
+ (pcnt_intra > (INTRA_VS_INTER_THRESH * modified_pcnt_inter)) && |
((this_frame->intra_error / |
- DOUBLE_DIVIDE_CHECK(this_frame->coded_error)) < 2.5) && |
+ DOUBLE_DIVIDE_CHECK(this_frame->coded_error)) < |
+ KF_II_ERR_THRESHOLD) && |
((fabs(last_frame->coded_error - this_frame->coded_error) / |
- DOUBLE_DIVIDE_CHECK(this_frame->coded_error) > 0.40) || |
+ DOUBLE_DIVIDE_CHECK(this_frame->coded_error) > |
+ ERR_CHANGE_THRESHOLD) || |
(fabs(last_frame->intra_error - this_frame->intra_error) / |
- DOUBLE_DIVIDE_CHECK(this_frame->intra_error) > 0.40) || |
+ DOUBLE_DIVIDE_CHECK(this_frame->intra_error) > |
+ ERR_CHANGE_THRESHOLD) || |
((next_frame->intra_error / |
- DOUBLE_DIVIDE_CHECK(next_frame->coded_error)) > 3.5))))) { |
+ DOUBLE_DIVIDE_CHECK(next_frame->coded_error)) > |
+ II_IMPROVEMENT_THRESHOLD))))) { |
int i; |
const FIRSTPASS_STATS *start_pos = twopass->stats_in; |
FIRSTPASS_STATS local_next_frame = *next_frame; |
@@ -2216,7 +2241,7 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { |
// Special check for transition or high motion followed by a |
// static scene. |
- if (detect_transition_to_still(twopass, i, cpi->oxcf.key_freq - i, |
+ if (detect_transition_to_still(cpi, i, cpi->oxcf.key_freq - i, |
loop_decay_rate, decay_accumulator)) |
break; |
@@ -2623,6 +2648,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { |
} |
#define MINQ_ADJ_LIMIT 48 |
+#define MINQ_ADJ_LIMIT_CQ 20 |
void vp9_twopass_postencode_update(VP9_COMP *cpi) { |
TWO_PASS *const twopass = &cpi->twopass; |
RATE_CONTROL *const rc = &cpi->rc; |
@@ -2662,7 +2688,7 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) { |
const int maxq_adj_limit = |
rc->worst_quality - twopass->active_worst_quality; |
const int minq_adj_limit = |
- (cpi->oxcf.rc_mode == VPX_CQ) ? 0 : MINQ_ADJ_LIMIT; |
+ (cpi->oxcf.rc_mode == VPX_CQ ? MINQ_ADJ_LIMIT_CQ : MINQ_ADJ_LIMIT); |
// Undershoot. |
if (rc->rate_error_estimate > cpi->oxcf.under_shoot_pct) { |