Non RD: Add hybrid intra search. Add speed feature for it, and enabled for speed 8. Add tests for periodic key frames. Change-Id: I142003f61925461189a127f324632d1cbef5feac
diff --git a/av1/common/pred_common.h b/av1/common/pred_common.h index a681e4e..826c631 100644 --- a/av1/common/pred_common.h +++ b/av1/common/pred_common.h
@@ -203,6 +203,10 @@ return xd->tile_ctx->comp_inter_cdf[av1_get_reference_mode_context(xd)]; } +static INLINE aom_cdf_prob *av1_get_skip_cdf(const MACROBLOCKD *xd) { + return xd->tile_ctx->skip_cdfs[av1_get_skip_context(xd)]; +} + int av1_get_comp_reference_type_context(const MACROBLOCKD *xd); // == Uni-directional contexts ==
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c index 0b7ebcf..cd7f51a 100644 --- a/av1/encoder/encodeframe.c +++ b/av1/encoder/encodeframe.c
@@ -668,6 +668,15 @@ sizeof(x->mbmi_ext->global_mvs)); } +static void hybrid_intra_mode_search(AV1_COMP *cpi, MACROBLOCK *const x, + RD_STATS *rd_cost, BLOCK_SIZE bsize, + PICK_MODE_CONTEXT *ctx) { + if (!cpi->sf.hybrid_intra_pickmode || bsize < BLOCK_16X16) + av1_rd_pick_intra_mode_sb(cpi, x, rd_cost, bsize, ctx, INT64_MAX); + else + av1_pick_intra_mode(cpi, x, rd_cost, bsize, ctx); +} + static AOM_INLINE void pick_sb_modes(AV1_COMP *const cpi, TileDataEnc *tile_data, MACROBLOCK *const x, int mi_row, @@ -783,7 +792,15 @@ #if CONFIG_COLLECT_COMPONENT_TIMING start_timing(cpi, av1_rd_pick_intra_mode_sb_time); #endif - av1_rd_pick_intra_mode_sb(cpi, x, rd_cost, bsize, ctx, best_rd.rdcost); + switch (pick_mode_type) { + case PICK_MODE_RD: + av1_rd_pick_intra_mode_sb(cpi, x, rd_cost, bsize, ctx, best_rd.rdcost); + break; + case PICK_MODE_NONRD: + hybrid_intra_mode_search(cpi, x, rd_cost, bsize, ctx); + break; + default: assert(0 && "Unknown pick mode type."); + } #if CONFIG_COLLECT_COMPONENT_TIMING end_timing(cpi, av1_rd_pick_intra_mode_sb_time); #endif @@ -795,8 +812,7 @@ av1_rd_pick_inter_mode_sb_seg_skip(cpi, tile_data, x, mi_row, mi_col, rd_cost, bsize, ctx, best_rd.rdcost); } else { - // TODO(kyslov): do the same for pick_intra_mode and - // pick_inter_mode_sb_seg_skip + // TODO(kyslov): do the same for pick_inter_mode_sb_seg_skip switch (pick_mode_type) { case PICK_MODE_RD: av1_rd_pick_inter_mode_sb(cpi, tile_data, x, rd_cost, bsize, ctx,
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c index 39598da..f65b860 100644 --- a/av1/encoder/nonrd_pickmode.c +++ b/av1/encoder/nonrd_pickmode.c
@@ -1361,6 +1361,76 @@ pd->dst.buf = dst_buf_base; } +void av1_pick_intra_mode(AV1_COMP *cpi, MACROBLOCK *x, RD_STATS *rd_cost, + BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx) { + AV1_COMMON *const cm = &cpi->common; + MACROBLOCKD *const xd = &x->e_mbd; + MB_MODE_INFO *const mi = xd->mi[0]; + RD_STATS this_rdc, best_rdc; + struct estimate_block_intra_args args = { cpi, x, DC_PRED, 1, 0 }; + const TX_SIZE intra_tx_size = + AOMMIN(max_txsize_lookup[bsize], + tx_mode_to_biggest_tx_size[x->tx_mode_search_type]); + int *bmode_costs; + const MB_MODE_INFO *above_mi = xd->above_mbmi; + const MB_MODE_INFO *left_mi = xd->left_mbmi; + const PREDICTION_MODE A = av1_above_block_mode(above_mi); + const PREDICTION_MODE L = av1_left_block_mode(left_mi); + bmode_costs = x->y_mode_costs[A][L]; + + av1_invalid_rd_stats(&best_rdc); + av1_invalid_rd_stats(&this_rdc); + + mi->ref_frame[0] = INTRA_FRAME; + mi->ref_frame[1] = NONE_FRAME; + mi->use_intrabc = 0; + mi->skip_mode = 0; + + // Initialize interp_filter here so we do not have to check for inter block + // modes in get_pred_context_switchable_interp() + mi->interp_filters = av1_broadcast_interp_filter(SWITCHABLE_FILTERS); + + mi->mv[0].as_int = INVALID_MV; + mi->uv_mode = DC_PRED; + memset(xd->tx_type_map, DCT_DCT, + sizeof(xd->tx_type_map[0]) * ctx->num_4x4_blk); + av1_zero(x->blk_skip); + + // Change the limit of this loop to add other intra prediction + // mode tests. + for (int i = 0; i < 4; ++i) { + PREDICTION_MODE this_mode = intra_mode_list[i]; + this_rdc.dist = this_rdc.rate = 0; + args.mode = this_mode; + args.skippable = 1; + args.rdc = &this_rdc; + mi->tx_size = intra_tx_size; + init_mbmi(mi, this_mode, INTRA_FRAME, NONE_FRAME, cm); + av1_foreach_transformed_block_in_plane(xd, bsize, 0, estimate_block_intra, + &args); + if (args.skippable) { + this_rdc.rate = av1_cost_symbol(av1_get_skip_cdf(xd)[1]); + } else { + this_rdc.rate += av1_cost_symbol(av1_get_skip_cdf(xd)[0]); + } + this_rdc.rate += bmode_costs[this_mode]; + this_rdc.rdcost = RDCOST(x->rdmult, this_rdc.rate, this_rdc.dist); + + if (this_rdc.rdcost < best_rdc.rdcost) { + best_rdc = this_rdc; + mi->mode = this_mode; + } + } + + *rd_cost = best_rdc; + +#if CONFIG_INTERNAL_STATS + store_coding_context(x, ctx, mi->mode); +#else + store_coding_context(x, ctx); +#endif // CONFIG_INTERNAL_STATS +} + void av1_nonrd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data, MACROBLOCK *x, RD_STATS *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
diff --git a/av1/encoder/rdopt.h b/av1/encoder/rdopt.h index e953c8c..a0294ea8b 100644 --- a/av1/encoder/rdopt.h +++ b/av1/encoder/rdopt.h
@@ -123,6 +123,9 @@ BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd_so_far); +void av1_pick_intra_mode(AV1_COMP *cpi, MACROBLOCK *x, RD_STATS *rd_cost, + BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx); + void av1_nonrd_pick_inter_mode_sb(struct AV1_COMP *cpi, struct TileDataEnc *tile_data, struct macroblock *x,
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c index 6569085..51d8393 100644 --- a/av1/encoder/speed_features.c +++ b/av1/encoder/speed_features.c
@@ -538,6 +538,7 @@ sf->use_nonrd_filter_search = 1; sf->nonrd_use_blockyrd_interp_filter = 0; sf->nonrd_reduce_golden_mode_search = 0; + sf->hybrid_intra_pickmode = 0; if (speed >= 1) { sf->gm_erroradv_type = GM_ERRORADV_TR_1; @@ -722,7 +723,7 @@ sf->nonrd_use_blockyrd_interp_filter = 0; sf->use_nonrd_altref_frame = 0; sf->nonrd_reduce_golden_mode_search = 1; - + sf->hybrid_intra_pickmode = 1; // TODO(kyslov) Enable when better model is available // It gives +5% speedup and 11% overall BDRate degradation // So, can not enable now until better CurvFit is there
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h index eac4697..7a77d35 100644 --- a/av1/encoder/speed_features.h +++ b/av1/encoder/speed_features.h
@@ -880,6 +880,10 @@ // colors to remaining colors) and terminate the search if current number of // palette colors is not the winner. int prune_palette_search_level; + + // Use hybrid (rd for bsize < 16x16, otherwise nonrd) intra search for intra + // only frames. + int hybrid_intra_pickmode; } SPEED_FEATURES; struct AV1_COMP;
diff --git a/test/datarate_test.cc b/test/datarate_test.cc index b9a89f4..053c055 100644 --- a/test/datarate_test.cc +++ b/test/datarate_test.cc
@@ -84,6 +84,30 @@ << " The datarate for the file is greater than target by too much!"; } + virtual void BasicRateTargetingCBRPeriodicKeyFrameTest() { + cfg_.rc_buf_initial_sz = 500; + cfg_.rc_buf_optimal_sz = 500; + cfg_.rc_buf_sz = 1000; + cfg_.rc_dropframe_thresh = 1; + cfg_.rc_min_quantizer = 0; + cfg_.rc_max_quantizer = 63; + cfg_.rc_end_usage = AOM_CBR; + cfg_.g_lag_in_frames = 0; + // Periodic keyframe + cfg_.kf_max_dist = 50; + + ::libaom_test::I420VideoSource video("pixel_capture_w320h240.yuv", 320, 240, + 30, 1, 0, 310); + const int bitrate_array[2] = { 150, 550 }; + cfg_.rc_target_bitrate = bitrate_array[GET_PARAM(4)]; + ResetModel(); + ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); + ASSERT_GE(effective_datarate_, cfg_.rc_target_bitrate * 0.85) + << " The datarate for the file is lower than target by too much!"; + ASSERT_LE(effective_datarate_, cfg_.rc_target_bitrate * 1.15) + << " The datarate for the file is greater than target by too much!"; + } + virtual void BasicRateTargetingAQModeOnOffCBRTest() { if (GET_PARAM(4) > 0) return; cfg_.rc_buf_initial_sz = 500; @@ -211,11 +235,16 @@ BasicRateTargetingVBRTest(); } -// Check basic rate targeting for CBR, +// Check basic rate targeting for CBR. TEST_P(DatarateTestLarge, BasicRateTargetingCBR) { BasicRateTargetingCBRTest(); } +// Check basic rate targeting for periodic key frame. +TEST_P(DatarateTestLarge, PeriodicKeyFrameCBR) { + BasicRateTargetingCBRPeriodicKeyFrameTest(); +} + // Check basic rate targeting for CBR. TEST_P(DatarateTestLarge, BasicRateTargeting444CBR) { BasicRateTargeting444CBRTest(); @@ -291,11 +320,16 @@ BasicRateTargetingVBRTest(); } -// Check basic rate targeting for CBR, +// Check basic rate targeting for CBR. TEST_P(DatarateTestRealtime, BasicRateTargetingCBR) { BasicRateTargetingCBRTest(); } +// Check basic rate targeting for periodic key frame. +TEST_P(DatarateTestRealtime, PeriodicKeyFrameCBR) { + BasicRateTargetingCBRPeriodicKeyFrameTest(); +} + // Check basic rate targeting for CBR. TEST_P(DatarateTestRealtime, BasicRateTargeting444CBR) { BasicRateTargeting444CBRTest();