From 2ee338ce3b9ab816270e6d413d4674fe9f2d45ca Mon Sep 17 00:00:00 2001 From: Paul Wilkins <paulwilkins@google.com> Date: Tue, 16 Jul 2013 18:12:34 +0100 Subject: [PATCH] Move uv intra mode selection in rd loop. Use an estimate based on DC_PRED for intra uv cost within the rd loop then only do a full uv mode analysis if an intra mode is chosen. Significant speed gains in some cases. Currently only enabled for speed 2 pending speed/quality tests. Change-Id: Ie851a12400d5483bce47ec0e3ccb8516041e91c0 --- vp9/encoder/vp9_onyx_if.c | 2 ++ vp9/encoder/vp9_onyx_int.h | 1 + vp9/encoder/vp9_rdopt.c | 56 ++++++++++++++++++++++++++++++++++---- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index cbb9f87c6f..211271927a 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -722,6 +722,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->last_chroma_intra_mode = TM_PRED; sf->use_rd_breakout = 0; sf->skip_encode_sb = 0; + sf->use_uv_intra_rd_estimate = 0; // Skip any mode not chosen at size < X for all sizes > X // Hence BLOCK_SIZE_SB64X64 (skip is off) @@ -793,6 +794,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) { sf->last_chroma_intra_mode = DC_PRED; sf->use_rd_breakout = 1; sf->skip_encode_sb = 1; + sf->use_uv_intra_rd_estimate = 1; } if (speed == 3) { sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES; diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index 48f5a12e4a..4c700c6b1c 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -275,6 +275,7 @@ typedef struct { unsigned int mode_search_skip_flags; MB_PREDICTION_MODE last_chroma_intra_mode; int use_rd_breakout; + int use_uv_intra_rd_estimate; } SPEED_FEATURES; typedef struct VP9_COMP { diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index e98e78e623..9e9cbf17ad 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -1524,6 +1524,24 @@ static int64_t rd_pick_intra_sbuv_mode(VP9_COMP *cpi, MACROBLOCK *x, return best_rd; } +static int64_t rd_sbuv_dcpred(VP9_COMP *cpi, MACROBLOCK *x, + int *rate, int *rate_tokenonly, + int64_t *distortion, int *skippable, + BLOCK_SIZE_TYPE bsize) { + int64_t this_rd; + + x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED; + super_block_uvrd(&cpi->common, x, rate_tokenonly, + distortion, skippable, NULL, bsize); + *rate = *rate_tokenonly + + x->intra_uv_mode_cost[x->e_mbd.frame_type][DC_PRED]; + this_rd = RDCOST(x->rdmult, x->rddiv, *rate, *distortion); + + x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED; + + return this_rd; +} + static int cost_mv_ref(VP9_COMP *cpi, MB_PREDICTION_MODE mode, int mode_context) { MACROBLOCK *const x = &cpi->mb; @@ -3090,7 +3108,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, frame_mv[ZEROMV][ref_frame].as_int = 0; } - // If intra is not masked off then get best uv intra mode rd. + // If intra is not masked off then get uv intra mode rd. if (!cpi->sf.use_avoid_tested_higherror || (cpi->sf.use_avoid_tested_higherror && (ref_frame_mask & (1 << INTRA_FRAME)))) { @@ -3104,12 +3122,26 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, mbmi->mode = DC_PRED; mbmi->ref_frame[0] = INTRA_FRAME; + + // Test all possible UV transform sizes that may be used in the main loop for (i = min_uvtxfm_size; i <= max_uvtxfm_size; ++i) { mbmi->txfm_size = i; - rd_pick_intra_sbuv_mode(cpi, x, &rate_uv_intra[i], - &rate_uv_tokenonly[i], &dist_uv[i], &skip_uv[i], - (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 : - bsize); + + // Use an estimated rd for uv_intra based on DC_PRED if the + // appropriate speed flag is set. + if (cpi->sf.use_uv_intra_rd_estimate) { + rd_sbuv_dcpred(cpi, x, &rate_uv_intra[i], + &rate_uv_tokenonly[i], &dist_uv[i], &skip_uv[i], + (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 : + bsize); + // Else do a proper rd search for each possible transform size that may + // be considered in the main rd loop. + } else { + rd_pick_intra_sbuv_mode(cpi, x, &rate_uv_intra[i], + &rate_uv_tokenonly[i], &dist_uv[i], &skip_uv[i], + (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 + : bsize); + } mode_uv[i] = mbmi->uv_mode; } } @@ -3761,6 +3793,20 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, break; } + // If we used an estimate for the uv intra rd in the loop above... + if (cpi->sf.use_uv_intra_rd_estimate) { + // Do Intra UV best rd mode selection if best mode choice above was intra. + if (vp9_mode_order[best_mode_index].ref_frame == INTRA_FRAME) { + TX_SIZE uv_tx_size = get_uv_tx_size(mbmi); + rd_pick_intra_sbuv_mode(cpi, x, &rate_uv_intra[uv_tx_size], + &rate_uv_tokenonly[uv_tx_size], + &dist_uv[uv_tx_size], + &skip_uv[uv_tx_size], + (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 + : bsize); + } + } + // If indicated then mark the index of the chosen mode to be inspected at // other block sizes. if (bsize <= cpi->sf.unused_mode_skip_lvl) { -- GitLab