Allintra: Introduce adapt_top_model_rd_count_using_neighbors sf
The sf top_intra_model_count_allowed indicates the number of top
model rds to be stored during intra mode decision and these stored
model rds are used to prune the luma intra modes. This CL
introduces aggressive pruning of modes by reducing the number of
candidates used to store the model rd and by adapting the index of
the candidate for pruning based on neighbor blocks and quantizer
information. This change is applicable for speed >= 6.
For AVIF still-image encode,
Instruction Count BD-Rate Loss(%)
cpu-used Reduction(%) psnr ssim
6 5.481 0.0222 -0.0281
7 4.170 0.2591 0.2361
8 2.437 0.1108 0.1157
9 0.000 0.0000 0.0000
STATS_CHANGED
Change-Id: Ib1bf8cae2f78c640c387050e6a2d4dfb988e742e
diff --git a/av1/encoder/intra_mode_search.c b/av1/encoder/intra_mode_search.c
index 9b664ca..e8bbe11 100644
--- a/av1/encoder/intra_mode_search.c
+++ b/av1/encoder/intra_mode_search.c
@@ -335,21 +335,56 @@
}
}
+static AOM_INLINE int get_model_rd_index_for_pruning(
+ const MACROBLOCK *const x,
+ const INTRA_MODE_SPEED_FEATURES *const intra_sf) {
+ const int top_intra_model_count_allowed =
+ intra_sf->top_intra_model_count_allowed;
+ if (!intra_sf->adapt_top_model_rd_count_using_neighbors)
+ return top_intra_model_count_allowed - 1;
+
+ const MACROBLOCKD *const xd = &x->e_mbd;
+ const PREDICTION_MODE mode = xd->mi[0]->mode;
+ int model_rd_index_for_pruning = top_intra_model_count_allowed - 1;
+ int is_left_mode_neq_cur_mode = 0, is_above_mode_neq_cur_mode = 0;
+ if (xd->left_available)
+ is_left_mode_neq_cur_mode = xd->left_mbmi->mode != mode;
+ if (xd->up_available)
+ is_above_mode_neq_cur_mode = xd->above_mbmi->mode != mode;
+ // The pruning of luma intra modes is made more aggressive at lower quantizers
+ // and vice versa. The value for model_rd_index_for_pruning is derived as
+ // follows.
+ // qidx 0 to 127: Reduce the index of a candidate used for comparison only if
+ // the current mode does not match either of the available neighboring modes.
+ // qidx 128 to 255: Reduce the index of a candidate used for comparison only
+ // if the current mode does not match both the available neighboring modes.
+ if (x->qindex <= 127) {
+ if (is_left_mode_neq_cur_mode || is_above_mode_neq_cur_mode)
+ model_rd_index_for_pruning = AOMMAX(model_rd_index_for_pruning - 1, 0);
+ } else {
+ if (is_left_mode_neq_cur_mode && is_above_mode_neq_cur_mode)
+ model_rd_index_for_pruning = AOMMAX(model_rd_index_for_pruning - 1, 0);
+ }
+ return model_rd_index_for_pruning;
+}
+
int prune_intra_y_mode(int64_t this_model_rd, int64_t *best_model_rd,
- int64_t top_intra_model_rd[], int model_cnt_allowed) {
+ int64_t top_intra_model_rd[], int max_model_cnt_allowed,
+ int model_rd_index_for_pruning) {
const double thresh_best = 1.50;
const double thresh_top = 1.00;
- for (int i = 0; i < model_cnt_allowed; i++) {
+ for (int i = 0; i < max_model_cnt_allowed; i++) {
if (this_model_rd < top_intra_model_rd[i]) {
- for (int j = model_cnt_allowed - 1; j > i; j--) {
+ for (int j = max_model_cnt_allowed - 1; j > i; j--) {
top_intra_model_rd[j] = top_intra_model_rd[j - 1];
}
top_intra_model_rd[i] = this_model_rd;
break;
}
}
- if (top_intra_model_rd[model_cnt_allowed - 1] != INT64_MAX &&
- this_model_rd > thresh_top * top_intra_model_rd[model_cnt_allowed - 1])
+ if (top_intra_model_rd[model_rd_index_for_pruning] != INT64_MAX &&
+ this_model_rd >
+ thresh_top * top_intra_model_rd[model_rd_index_for_pruning])
return 1;
if (this_model_rd != INT64_MAX &&
@@ -1022,7 +1057,7 @@
int64_t *best_model_rd,
int64_t top_intra_model_rd[]) {
const AV1_COMMON *cm = &cpi->common;
- const SPEED_FEATURES *const sf = &cpi->sf;
+ const INTRA_MODE_SPEED_FEATURES *const intra_sf = &cpi->sf.intra_sf;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = xd->mi[0];
assert(mbmi->ref_frame[0] == INTRA_FRAME);
@@ -1049,12 +1084,12 @@
const int is_directional_mode = av1_is_directional_mode(mode);
if (is_directional_mode && av1_use_angle_delta(bsize) &&
cpi->oxcf.intra_mode_cfg.enable_angle_delta) {
- if (sf->intra_sf.intra_pruning_with_hog &&
+ if (intra_sf->intra_pruning_with_hog &&
!intra_search_state->dir_mode_skip_mask_ready) {
const float thresh[4] = { -1.2f, 0.0f, 0.0f, 1.2f };
const int is_chroma = 0;
prune_intra_mode_with_hog(x, bsize, cm->seq_params->sb_size,
- thresh[sf->intra_sf.intra_pruning_with_hog - 1],
+ thresh[intra_sf->intra_pruning_with_hog - 1],
intra_search_state->directional_mode_skip_mask,
is_chroma);
intra_search_state->dir_mode_skip_mask_ready = 1;
@@ -1064,8 +1099,13 @@
const TX_SIZE tx_size = AOMMIN(TX_32X32, max_txsize_lookup[bsize]);
const int64_t this_model_rd =
intra_model_rd(&cpi->common, x, 0, bsize, tx_size, /*use_hadamard=*/1);
+
+ const int model_rd_index_for_pruning =
+ get_model_rd_index_for_pruning(x, intra_sf);
+
if (prune_intra_y_mode(this_model_rd, best_model_rd, top_intra_model_rd,
- sf->intra_sf.top_intra_model_count_allowed))
+ intra_sf->top_intra_model_count_allowed,
+ model_rd_index_for_pruning))
return 0;
av1_init_rd_stats(rd_stats_y);
av1_pick_uniform_tx_size_type_yrd(cpi, x, rd_stats_y, bsize, best_rd);
@@ -1083,7 +1123,7 @@
intra_mode_info_cost_y(cpi, x, mbmi, bsize, mode_cost);
best_rd_so_far = RDCOST(x->rdmult, tmp_rate, rd_stats_y->dist);
try_filter_intra = (best_rd_so_far / 2) <= best_rd;
- } else if (sf->intra_sf.skip_filter_intra_in_inter_frames >= 1) {
+ } else if (intra_sf->skip_filter_intra_in_inter_frames >= 1) {
// As rd cost of luma intra dc mode is more than best_rd (i.e.,
// rd_stats_y->rate = INT_MAX), skip the evaluation of filter intra modes.
try_filter_intra = 0;
@@ -1202,16 +1242,16 @@
bmode_costs = x->mode_costs.y_mode_costs[above_ctx][left_ctx];
mbmi->angle_delta[PLANE_TYPE_Y] = 0;
- if (cpi->sf.intra_sf.intra_pruning_with_hog) {
+ const INTRA_MODE_SPEED_FEATURES *const intra_sf = &cpi->sf.intra_sf;
+ if (intra_sf->intra_pruning_with_hog) {
// Less aggressive thresholds are used here than those used in inter frame
// encoding in av1_handle_intra_y_mode() because we want key frames/intra
// frames to have higher quality.
const float thresh[4] = { -1.2f, -1.2f, -0.6f, 0.4f };
const int is_chroma = 0;
- prune_intra_mode_with_hog(
- x, bsize, cpi->common.seq_params->sb_size,
- thresh[cpi->sf.intra_sf.intra_pruning_with_hog - 1],
- directional_mode_skip_mask, is_chroma);
+ prune_intra_mode_with_hog(x, bsize, cpi->common.seq_params->sb_size,
+ thresh[intra_sf->intra_pruning_with_hog - 1],
+ directional_mode_skip_mask, is_chroma);
}
mbmi->filter_intra_mode_info.use_filter_intra = 0;
pmi->palette_size[0] = 0;
@@ -1247,7 +1287,7 @@
// than horizontal / vertical smooth prediction modes. Hence treat
// them differently in speed features.
if ((!intra_mode_cfg->enable_smooth_intra ||
- cpi->sf.intra_sf.disable_smooth_intra) &&
+ intra_sf->disable_smooth_intra) &&
(mbmi->mode == SMOOTH_H_PRED || mbmi->mode == SMOOTH_V_PRED))
continue;
if (!intra_mode_cfg->enable_smooth_intra && mbmi->mode == SMOOTH_PRED)
@@ -1256,9 +1296,8 @@
// The functionality of filter intra modes and smooth prediction
// overlap. Hence smooth prediction is pruned only if all the
// filter intra modes are enabled.
- if (cpi->sf.intra_sf.disable_smooth_intra &&
- cpi->sf.intra_sf.prune_filter_intra_level == 0 &&
- mbmi->mode == SMOOTH_PRED)
+ if (intra_sf->disable_smooth_intra &&
+ intra_sf->prune_filter_intra_level == 0 && mbmi->mode == SMOOTH_PRED)
continue;
if (!intra_mode_cfg->enable_paeth_intra && mbmi->mode == PAETH_PRED)
continue;
@@ -1275,15 +1314,20 @@
continue;
// Use intra_y_mode_mask speed feature to skip intra mode evaluation.
- if (!(cpi->sf.intra_sf.intra_y_mode_mask[max_txsize_lookup[bsize]] &
+ if (!(intra_sf->intra_y_mode_mask[max_txsize_lookup[bsize]] &
(1 << mbmi->mode)))
continue;
const TX_SIZE tx_size = AOMMIN(TX_32X32, max_txsize_lookup[bsize]);
const int64_t this_model_rd =
intra_model_rd(&cpi->common, x, 0, bsize, tx_size, /*use_hadamard=*/1);
+
+ const int model_rd_index_for_pruning =
+ get_model_rd_index_for_pruning(x, intra_sf);
+
if (prune_intra_y_mode(this_model_rd, &best_model_rd, top_intra_model_rd,
- cpi->sf.intra_sf.top_intra_model_count_allowed))
+ intra_sf->top_intra_model_count_allowed,
+ model_rd_index_for_pruning))
continue;
// Builds the actual prediction. The prediction from
diff --git a/av1/encoder/intra_mode_search.h b/av1/encoder/intra_mode_search.h
index 5a52440..ff03b02 100644
--- a/av1/encoder/intra_mode_search.h
+++ b/av1/encoder/intra_mode_search.h
@@ -279,16 +279,20 @@
*/
void set_y_mode_and_delta_angle(const int mode_idx, MB_MODE_INFO *const mbmi);
-/*! \brief prune luma intra mode based on the model rd.
- * \param[in] this_model_rd model rd for current mode.
- * \param[in] best_model_rd Best model RD seen for this block so
- * far.
- * \param[in] top_intra_model_rd Top intra model RD seen for this
- * block so far.
- * \param[in] model_cnt_allowed The number of top intra model RD allowed.
+/*! \brief prune luma intra mode based on the model rd.
+ * \param[in] this_model_rd model rd for current mode.
+ * \param[in] best_model_rd Best model RD seen for this block so
+ * far.
+ * \param[in] top_intra_model_rd Top intra model RD seen for this
+ * block so far.
+ * \param[in] max_model_cnt_allowed The maximum number of top intra
+ * model RD allowed.
+ * \param[in] model_rd_index_for_pruning Index of the candidate used for
+ * pruning based on model rd.
*/
int prune_intra_y_mode(int64_t this_model_rd, int64_t *best_model_rd,
- int64_t top_intra_model_rd[], int model_cnt_allowed);
+ int64_t top_intra_model_rd[], int max_model_cnt_allowed,
+ int model_rd_index_for_pruning);
#ifdef __cplusplus
} // extern "C"
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index e096377..4b2ab6f 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -476,6 +476,8 @@
sf->intra_sf.chroma_intra_pruning_with_hog = 4;
sf->intra_sf.intra_pruning_with_hog = 4;
sf->intra_sf.cfl_search_range = 1;
+ sf->intra_sf.top_intra_model_count_allowed = 2;
+ sf->intra_sf.adapt_top_model_rd_count_using_neighbors = 1;
sf->part_sf.prune_rectangular_split_based_on_qidx =
allow_screen_content_tools ? 0 : 2;
@@ -1727,6 +1729,7 @@
intra_sf->prune_chroma_modes_using_luma_winner = 0;
intra_sf->cfl_search_range = 3;
intra_sf->top_intra_model_count_allowed = TOP_INTRA_MODEL_COUNT;
+ intra_sf->adapt_top_model_rd_count_using_neighbors = 0;
intra_sf->early_term_chroma_palette_size_search = 0;
intra_sf->skip_filter_intra_in_inter_frames = 0;
}
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 087e56d..3d8bc6c 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -1070,6 +1070,10 @@
// higher speeds.
int top_intra_model_count_allowed;
+ // Adapt top_intra_model_count_allowed locally to prune luma intra modes using
+ // neighbor block and quantizer information.
+ int adapt_top_model_rd_count_using_neighbors;
+
// Terminate early in chroma palette_size search.
// 0: No early termination
// 1: Terminate early for higher palette_size, if header rd cost of lower