From 2fbdfd2c66f987cf4c0e4c870b6a04c4ad49ef5c Mon Sep 17 00:00:00 2001 From: Jingning Han Date: Thu, 20 Nov 2014 11:28:00 -0800 Subject: [PATCH] Key frame non-RD mode decision process This commit makes a non-RD coding mode decision process for key frame coding. It can be optionally turned on in speed -6 and above. Change-Id: I0847258b392877a0210b4768bef88ebc9ad009b5 --- vp9/encoder/vp9_encodeframe.c | 6 ++-- vp9/encoder/vp9_pickmode.c | 51 ++++++++++++++++++++++++++++++++ vp9/encoder/vp9_pickmode.h | 3 ++ vp9/encoder/vp9_speed_features.c | 5 +++- 4 files changed, 62 insertions(+), 3 deletions(-) diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 49272590d..f220157ae 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -2601,7 +2601,9 @@ static void nonrd_pick_sb_modes(VP9_COMP *cpi, if (mbmi->segment_id) x->rdmult = vp9_cyclic_refresh_get_rdmult(cpi->cyclic_refresh); - if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) + if (cm->frame_type == KEY_FRAME) + vp9_pick_intra_mode(cpi, x, rd_cost, bsize, ctx); + else if (vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) set_mode_info_seg_skip(x, cm->tx_mode, rd_cost, bsize); else vp9_pick_inter_mode(cpi, x, tile_data, mi_row, mi_col, @@ -3456,7 +3458,7 @@ static void encode_tiles(VP9_COMP *cpi) { for (mi_row = tile_info->mi_row_start; mi_row < tile_info->mi_row_end; mi_row += MI_BLOCK_SIZE) { - if (cpi->sf.use_nonrd_pick_mode && !frame_is_intra_only(cm)) + if (cpi->sf.use_nonrd_pick_mode) encode_nonrd_sb_row(cpi, this_tile, mi_row, &tok[tile_row][tile_col]); else encode_rd_sb_row(cpi, this_tile, mi_row, &tok[tile_row][tile_col]); diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c index 3d1d1b4fa..fb0786669 100644 --- a/vp9/encoder/vp9_pickmode.c +++ b/vp9/encoder/vp9_pickmode.c @@ -464,6 +464,57 @@ static const PREDICTION_MODE intra_mode_list[] = { DC_PRED, V_PRED, H_PRED, TM_PRED }; +void vp9_pick_intra_mode(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *rd_cost, + BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx) { + MACROBLOCKD *const xd = &x->e_mbd; + MB_MODE_INFO *const mbmi = &xd->mi[0].src_mi->mbmi; + RD_COST this_rdc, best_rdc; + PREDICTION_MODE this_mode; + struct estimate_block_intra_args args = { cpi, x, DC_PRED, 0, 0 }; + const TX_SIZE intra_tx_size = + MIN(max_txsize_lookup[bsize], + tx_mode_to_biggest_tx_size[cpi->common.tx_mode]); + MODE_INFO *const mic = xd->mi[0].src_mi; + int *bmode_costs; + const MODE_INFO *above_mi = xd->mi[-xd->mi_stride].src_mi; + const MODE_INFO *left_mi = xd->left_available ? xd->mi[-1].src_mi : NULL; + const PREDICTION_MODE A = vp9_above_block_mode(mic, above_mi, 0); + const PREDICTION_MODE L = vp9_left_block_mode(mic, left_mi, 0); + bmode_costs = cpi->y_mode_costs[A][L]; + + (void) ctx; + vp9_rd_cost_reset(&best_rdc); + vp9_rd_cost_reset(&this_rdc); + + mbmi->ref_frame[0] = INTRA_FRAME; + mbmi->mv[0].as_int = INVALID_MV; + mbmi->uv_mode = DC_PRED; + vpx_memset(x->skip_txfm, 0, sizeof(x->skip_txfm)); + + // Change the limit of this loop to add other intra prediction + // mode tests. + for (this_mode = DC_PRED; this_mode <= H_PRED; ++this_mode) { + args.mode = this_mode; + args.rate = 0; + args.dist = 0; + mbmi->tx_size = intra_tx_size; + vp9_foreach_transformed_block_in_plane(xd, bsize, 0, + estimate_block_intra, &args); + this_rdc.rate = args.rate; + this_rdc.dist = args.dist; + this_rdc.rate += bmode_costs[this_mode]; + this_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, + this_rdc.rate, this_rdc.dist); + + if (this_rdc.rdcost < best_rdc.rdcost) { + best_rdc = this_rdc; + mbmi->mode = this_mode; + } + } + + *rd_cost = best_rdc; +} + // TODO(jingning) placeholder for inter-frame non-RD mode decision. // this needs various further optimizations. to be continued.. void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, diff --git a/vp9/encoder/vp9_pickmode.h b/vp9/encoder/vp9_pickmode.h index 23d347d94..57a1cf937 100644 --- a/vp9/encoder/vp9_pickmode.h +++ b/vp9/encoder/vp9_pickmode.h @@ -17,6 +17,9 @@ extern "C" { #endif +void vp9_pick_intra_mode(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *rd_cost, + BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx); + void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data, int mi_row, int mi_col, RD_COST *rd_cost, diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c index 27c882967..1801b2059 100644 --- a/vp9/encoder/vp9_speed_features.c +++ b/vp9/encoder/vp9_speed_features.c @@ -294,7 +294,7 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf, (frames_since_key % (sf->last_partitioning_redo_frequency << 1) == 1); sf->max_delta_qindex = is_keyframe ? 20 : 15; sf->partition_search_type = REFERENCE_PARTITION; - sf->use_nonrd_pick_mode = 1; + sf->use_nonrd_pick_mode = !is_keyframe; sf->allow_skip_recode = 0; sf->inter_mode_mask[BLOCK_32X32] = INTER_NEAREST_NEW_ZERO; sf->inter_mode_mask[BLOCK_32X64] = INTER_NEAREST_NEW_ZERO; @@ -319,6 +319,9 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf, if (speed >= 6) { // Adaptively switch between SOURCE_VAR_BASED_PARTITION and FIXED_PARTITION. sf->partition_search_type = VAR_BASED_PARTITION; + + // Turn on this to use non-RD key frame coding mode. + // sf->use_nonrd_pick_mode = 1; sf->search_type_check_frequency = 50; sf->mv.search_method = NSTEP; sf->tx_size_search_method = is_keyframe ? USE_LARGESTALL : USE_TX_8X8;