Prune interintra search using top smooth interintra RD This CL tracks the top N estimated RD Costs for smooth interintra mode per coding unit. If the current estimated RD cost of smooth interintra mode exceeds the Nth-best cost, interintra mode is skipped. The speed feature skip_interintra_using_top_smooth_rd_lvl configures N=2 for speed 1 and N=1 for speed 2. Encoder performance results averaged over all resolutions are as follows: Instruction Count BD-Rate Loss(%) cpu Reduction(%) avg.psnr ssim vmaf vmaf_neg uvq_1p5 1 4.162 0.0686 0.0924 0.044 0.0492 0.2235 2 2.752 0.0511 0.0589 0.0144 0.06 0.6322 STATS_CHANGED for speed = 1,2 Change-Id: Iddc646028e011068a9f48aa5cf46cd040e9bcb3c
diff --git a/av1/encoder/block.h b/av1/encoder/block.h index a932715..16862d4 100644 --- a/av1/encoder/block.h +++ b/av1/encoder/block.h
@@ -879,6 +879,9 @@ //! Maximum number of estimated RD Cost records for compound average. #define TOP_COMP_AVG_EST_RD_COUNT 5 +//! Maximum number of estimated RD Cost records for smooth interintra. +#define TOP_SMOOTH_INTERINTRA_RD_COUNT 2 + /*! \brief Encoder's parameters related to the current coding block. * * This struct contains most of the information the encoder needs to encode the @@ -1439,6 +1442,9 @@ /*!\brief Array of best estimated RD Costs of compound average. */ int64_t top_comp_avg_est_rd[TOP_COMP_AVG_EST_RD_COUNT]; + /*!\brief Array of best estimated RD Costs of smooth interintra. */ + int64_t top_smooth_interintra_rd[TOP_SMOOTH_INTERINTRA_RD_COUNT]; + #if CONFIG_PARTITION_SEARCH_ORDER /*!\brief Pointer to RD_STATS structure to be used in * av1_rd_partition_search().
diff --git a/av1/encoder/compound_type.c b/av1/encoder/compound_type.c index 3bfe78f..569cfa9 100644 --- a/av1/encoder/compound_type.c +++ b/av1/encoder/compound_type.c
@@ -29,6 +29,11 @@ // speed feature. static const int num_comp_mode_skip_cand[3] = { 5, 4, 2 }; +// Look-up table for the number of top smooth interintra estimated RD Costs that +// should be considered based on skip_interintra_using_top_smooth_rd_lvl +// speed feature. +static const int num_interintra_skip_cand[2] = { 2, 1 }; + // Checks if characteristics of search match static inline int is_comp_rd_match(const AV1_COMP *const cpi, const MACROBLOCK *const x, @@ -602,12 +607,6 @@ } *best_rd = rd; *best_mode_rate = rmode; - // Return early if best rd not good enough - if (ref_best_rd < INT64_MAX && - (*best_rd >> INTER_INTRA_RD_THRESH_SHIFT) * INTER_INTRA_RD_THRESH_SCALE > - ref_best_rd) { - return IGNORE_MODE; - } return 0; } @@ -757,6 +756,24 @@ } } +// Store the estimated smooth interintra RD Cost in the sorted top-N array. +static inline void push_smooth_interintra_rd( + int64_t *top_smooth_interintra_rd, int64_t tmp_rd, + int skip_interintra_using_top_smooth_rd_lvl) { + if (!skip_interintra_using_top_smooth_rd_lvl) return; + + // Insert the RD Cost in sorted order. + for (int i = 0; i < TOP_SMOOTH_INTERINTRA_RD_COUNT; ++i) { + if (tmp_rd < top_smooth_interintra_rd[i]) { + for (int j = TOP_SMOOTH_INTERINTRA_RD_COUNT - 1; j > i; --j) { + top_smooth_interintra_rd[j] = top_smooth_interintra_rd[j - 1]; + } + top_smooth_interintra_rd[i] = tmp_rd; + break; + } + } +} + // Avoid further evaluation of compound modes based on top estimated RD Costs of // compound average. static inline bool prune_comp_eval_using_comp_avg_est_rd( @@ -779,6 +796,22 @@ return false; } +static inline bool prune_interintra_using_smooth_rd( + const int64_t *top_smooth_interintra_rd, int64_t tmp_rd, + int skip_interintra_using_top_smooth_rd_lvl) { + if (!skip_interintra_using_top_smooth_rd_lvl) return false; + + const int num_top_cand = + num_interintra_skip_cand[skip_interintra_using_top_smooth_rd_lvl - 1]; + + // Do not prune if there is no valid top RD Cost for comparison. + if (top_smooth_interintra_rd[num_top_cand - 1] == INT64_MAX) return false; + + if (tmp_rd > top_smooth_interintra_rd[num_top_cand - 1]) return true; + + return false; +} + int av1_handle_inter_intra_mode(const AV1_COMP *const cpi, MACROBLOCK *const x, BLOCK_SIZE bsize, MB_MODE_INFO *mbmi, HandleInterModeArgs *args, int64_t ref_best_rd, @@ -826,6 +859,24 @@ if (ret == IGNORE_MODE) { return IGNORE_MODE; } + + push_smooth_interintra_rd( + x->top_smooth_interintra_rd, best_interintra_rd_nowedge, + cpi->sf.inter_sf.skip_interintra_using_top_smooth_rd_lvl); + + if (prune_interintra_using_smooth_rd( + x->top_smooth_interintra_rd, best_interintra_rd_nowedge, + cpi->sf.inter_sf.skip_interintra_using_top_smooth_rd_lvl)) { + return IGNORE_MODE; + } + + // Return early if best rd not good enough. + if (ref_best_rd < INT64_MAX && + (best_interintra_rd_nowedge >> INTER_INTRA_RD_THRESH_SHIFT) * + INTER_INTRA_RD_THRESH_SCALE > + ref_best_rd) { + return IGNORE_MODE; + } } // Compute wedge interintra
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c index 169d181..28649da 100644 --- a/av1/encoder/rdopt.c +++ b/av1/encoder/rdopt.c
@@ -522,6 +522,16 @@ } } +// Initialize estimated RD Cost records of smooth interintra. +static inline void init_smooth_interintra_est_rd( + struct macroblock *x, int skip_interintra_using_top_smooth_rd_lvl) { + if (!skip_interintra_using_top_smooth_rd_lvl) return; + + for (int j = 0; j < TOP_SMOOTH_INTERINTRA_RD_COUNT; ++j) { + x->top_smooth_interintra_rd[j] = INT64_MAX; + } +} + // Similar to get_horver_correlation, but also takes into account first // row/column, when computing horizontal/vertical correlation. void av1_get_horver_correlation_full_c(const int16_t *diff, int stride, @@ -6452,6 +6462,8 @@ mode_end = SINGLE_REF_MODE_END; } init_comp_avg_est_rd(x, sf->inter_sf.skip_cmp_using_top_cmp_avg_est_rd_lvl); + init_smooth_interintra_est_rd( + x, sf->inter_sf.skip_interintra_using_top_smooth_rd_lvl); for (THR_MODES midx = mode_start; midx < mode_end; ++midx) { // Get the actual prediction mode we are trying in this iteration const THR_MODES mode_enum = av1_default_mode_order[midx];
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c index 3760b82..249c9d2 100644 --- a/av1/encoder/speed_features.c +++ b/av1/encoder/speed_features.c
@@ -1206,6 +1206,7 @@ sf->inter_sf.prune_comp_using_best_single_mode_ref = 2; sf->inter_sf.use_dist_wtd_comp_flag = DIST_WTD_COMP_DISABLED; sf->inter_sf.enable_comp_wedge_search_using_model_rd = 1; + sf->inter_sf.skip_interintra_using_top_smooth_rd_lvl = 1; sf->interp_sf.use_interp_filter = 1; sf->interp_sf.skip_model_rd_uv = 1; @@ -1266,6 +1267,7 @@ sf->inter_sf.inter_mode_txfm_breakout = boosted ? 0 : 1; sf->inter_sf.alt_ref_search_fp = 1; sf->inter_sf.prune_single_ref = boosted ? 1 : 2; + sf->inter_sf.skip_interintra_using_top_smooth_rd_lvl = 2; sf->interp_sf.adaptive_interp_filter_search = 1; @@ -2422,6 +2424,7 @@ inter_sf->skip_cmp_using_top_cmp_avg_est_rd_lvl = 0; inter_sf->skip_interinter_wedge_search_based_on_mse = 0; inter_sf->enable_comp_wedge_search_using_model_rd = 0; + inter_sf->skip_interintra_using_top_smooth_rd_lvl = 0; set_txfm_rd_gate_level(inter_sf->txfm_rd_gate_level, 0); }
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h index 49fdd77..c095780 100644 --- a/av1/encoder/speed_features.h +++ b/av1/encoder/speed_features.h
@@ -1270,6 +1270,11 @@ // Enable/disable model RD based fast compound wedge mask search. int enable_comp_wedge_search_using_model_rd; + + // Avoid further evaluation of interintra modes using top estimate RD Costs of + // smooth interintra. Values are 0 (not used),1 - 2 with progressively + // increasing aggressiveness, i.e., decreasing number of top candidates. + int skip_interintra_using_top_smooth_rd_lvl; } INTER_MODE_SPEED_FEATURES; typedef struct INTERP_FILTER_SPEED_FEATURES {