diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h index 800e3ba4767f9e16a6ae470d1268189979fe0075..3e377cf6f62409b0f2920f57c0b938956fa312d6 100644 --- a/vp9/encoder/vp9_block.h +++ b/vp9/encoder/vp9_block.h @@ -102,6 +102,7 @@ struct macroblock { int mv_best_ref_index[MAX_REF_FRAMES]; unsigned int max_mv_context[MAX_REF_FRAMES]; + unsigned int source_variance; int nmvjointcost[MV_JOINTS]; int nmvcosts[2][MV_VALS]; diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index f4490aed936d1790a6c85dc991d31eb83c01c3d4..66eae41da47115a111291560da9b3e9300b4ce73 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -581,6 +581,8 @@ static void pick_sb_modes(VP9_COMP *cpi, int mi_row, int mi_col, set_offsets(cpi, mi_row, mi_col, bsize); xd->mode_info_context->mbmi.sb_type = bsize; + + x->source_variance = get_sb_variance(cpi, x, bsize); if (cpi->oxcf.tuning == VP8_TUNE_SSIM) vp9_activity_masking(cpi, x); @@ -1922,6 +1924,7 @@ static void encode_sb_row(VP9_COMP *cpi, int mi_row, TOKENEXTRA **tp, MODE_INFO *m = cm->mi + idx_str; MODE_INFO *p = cm->prev_mi + idx_str; + cpi->mb.source_variance = UINT_MAX; if (cpi->sf.use_one_partition_size_always) { set_offsets(cpi, mi_row, mi_col, BLOCK_SIZE_SB64X64); set_partitioning(cpi, m, cpi->sf.always_this_block_size); diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index f2fa552f271d385e81a3b45d522f488f4d22572f..db039959f61cbaddbe4b8691d2e6af60522350a6 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -790,7 +790,8 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->unused_mode_skip_lvl = BLOCK_32X32; sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH | FLAG_SKIP_INTRA_BESTINTER | - FLAG_SKIP_COMP_BESTINTRA; + FLAG_SKIP_COMP_BESTINTRA | + FLAG_SKIP_INTRA_LOWVAR; sf->use_uv_intra_rd_estimate = 1; sf->use_rd_breakout = 1; sf->skip_encode_sb = 1; @@ -818,7 +819,9 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH | FLAG_SKIP_INTRA_BESTINTER | FLAG_SKIP_COMP_BESTINTRA | - FLAG_SKIP_COMP_REFMISMATCH; + FLAG_SKIP_COMP_REFMISMATCH | + FLAG_SKIP_INTRA_LOWVAR | + FLAG_EARLY_TERMINATE; sf->last_chroma_intra_mode = DC_PRED; sf->use_uv_intra_rd_estimate = 1; sf->use_rd_breakout = 1; @@ -839,7 +842,9 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH | FLAG_SKIP_INTRA_BESTINTER | FLAG_SKIP_COMP_BESTINTRA | - FLAG_SKIP_COMP_REFMISMATCH; + FLAG_SKIP_COMP_REFMISMATCH | + FLAG_SKIP_INTRA_LOWVAR | + FLAG_EARLY_TERMINATE; sf->use_rd_breakout = 1; sf->skip_encode_sb = 1; sf->disable_splitmv = 1; @@ -857,7 +862,9 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH | FLAG_SKIP_INTRA_BESTINTER | FLAG_SKIP_COMP_BESTINTRA | - FLAG_SKIP_COMP_REFMISMATCH; + FLAG_SKIP_COMP_REFMISMATCH | + FLAG_SKIP_INTRA_LOWVAR | + FLAG_EARLY_TERMINATE; sf->use_rd_breakout = 1; sf->optimize_coefficients = 0; sf->auto_mv_step_size = 1; diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index 4529ff083105c166cb1e191af855373b58dfa8fa..c258829c2fe9b185bc119f1f5f9c4e168412bde2 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -145,6 +145,8 @@ typedef struct { // const MODE_DEFINITION vp9_mode_order[MAX_MODES] used in the rd code. typedef enum { THR_NEARESTMV, + THR_DC, + THR_NEARESTA, THR_NEARESTG, THR_NEWMV, @@ -152,8 +154,6 @@ typedef enum { THR_NEARMV, THR_COMP_NEARESTGA, - THR_DC, - THR_NEWG, THR_NEWA, THR_NEARA, @@ -224,6 +224,10 @@ typedef enum { // skips oblique intra modes at angles 27, 63, 117, 153 if the best // intra so far is not one of the neighboring directions FLAG_SKIP_INTRA_DIRMISMATCH = 16, + + // skips intra modes other than DC_PRED if the source variance + // is small + FLAG_SKIP_INTRA_LOWVAR = 32, } MODE_SEARCH_SKIP_LOGIC; typedef struct { diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index f9c8f6e1478fc134ba8418411a09041a0c4ae9ab..2d932500e5f2b4762d604b374486cb86dca7bf52 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -54,6 +54,8 @@ DECLARE_ALIGNED(16, extern const uint8_t, const MODE_DEFINITION vp9_mode_order[MAX_MODES] = { {NEARESTMV, LAST_FRAME, NONE}, + {DC_PRED, INTRA_FRAME, NONE}, + {NEARESTMV, ALTREF_FRAME, NONE}, {NEARESTMV, GOLDEN_FRAME, NONE}, {NEWMV, LAST_FRAME, NONE}, @@ -61,8 +63,6 @@ const MODE_DEFINITION vp9_mode_order[MAX_MODES] = { {NEARMV, LAST_FRAME, NONE}, {NEARESTMV, GOLDEN_FRAME, ALTREF_FRAME}, - {DC_PRED, INTRA_FRAME, NONE}, - {NEWMV, GOLDEN_FRAME, NONE}, {NEWMV, ALTREF_FRAME, NONE}, {NEARMV, ALTREF_FRAME, NONE}, @@ -3518,6 +3518,16 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, tx_cache[i] = tx_cache[ONLY_4X4]; } else if (ref_frame == INTRA_FRAME) { TX_SIZE uv_tx; + // Disable intra modes other than DC_PRED for blocks with low variance + // Threshold for intra skipping based on source variance + // TODO(debargha): Specialize the threshold for super block sizes + static const int skip_intra_var_thresh[BLOCK_SIZE_TYPES] = { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + }; + if ((cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_LOWVAR) && + this_mode != DC_PRED && + x->source_variance < skip_intra_var_thresh[mbmi->sb_type]) + continue; // Only search the oblique modes if the best so far is // one of the neighboring directional modes if ((cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) && @@ -3844,8 +3854,6 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, if (this_rd < best_rd || x->skip) { if (!mode_excluded) { // Note index of best mode so far - const int qstep = xd->plane[0].dequant[1]; - best_mode_index = mode_index; if (ref_frame == INTRA_FRAME) { @@ -3868,9 +3876,19 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, // TODO(debargha): enhance this test with a better distortion prediction // based on qp, activity mask and history - if (cpi->sf.mode_search_skip_flags & FLAG_EARLY_TERMINATE) - if (ref_frame > INTRA_FRAME && distortion2 * 4 < qstep * qstep) + if (cpi->sf.mode_search_skip_flags & FLAG_EARLY_TERMINATE) { + const int qstep = xd->plane[0].dequant[1]; + // TODO(debargha): Enhance this by specializing for each mode_index + int scale = 4; + if (x->source_variance < UINT_MAX) { + const int var_adjust = (x->source_variance < 16); + scale -= var_adjust; + } + if (ref_frame > INTRA_FRAME && + distortion2 * scale < qstep * qstep) { early_term = 1; + } + } } #if 0 // Testing this mode gave rise to an improvement in best error score.