Introduce sf prune_rect_part_using_4x4_var_deviation
In this CL, a speed feature,
prune_rect_part_using_4x4_var_deviation, is introduced
to prune rectangular partitions based on variance of 4x4
sub-blocks in the block. If the difference between
maximum and minimum of sub-block variances is less than
a threshold, rectangular partitions are pruned. This
change is applicable only for --allintra speed=6.
For AVIF still-image encode,
Encode Time BD-Rate Loss(%)
cpu-used Reduction(%) psnr ssim
6 8.140 0.1539 0.3797
STATS_CHANGED for speed=6
Change-Id: I42f5f972d982eac2f0b24c1f071ab5b337522ac9
diff --git a/av1/encoder/partition_search.c b/av1/encoder/partition_search.c
index a41cc0c..38f423a 100644
--- a/av1/encoder/partition_search.c
+++ b/av1/encoder/partition_search.c
@@ -5373,27 +5373,41 @@
start_timing(cpi, none_partition_search_time);
#endif
- // Further pruning or in some cases reverse pruning when allintra is set
- // This code helps visual and in some cases metrics quality where the current
- // block comprises at least one very low variance sub-block and at least one
- // where the variance is much higher.
- //
- // The idea is that in such cases there is danger of ringing and other visual
- // artifacts from a high variance feature such as an edge into a very low
- // variance region.
- //
- // The approach taken is to force break down / split to a smaller block size
- // to try and separate out the low variance and well predicted blocks from the
- // more complex ones and to prevent propagation of ringing over a large
- // region.
- if ((cpi->oxcf.mode == ALLINTRA) && (bsize >= BLOCK_16X16)) {
- double var_min, var_max;
- log_sub_block_var(cpi, x, bsize, &var_min, &var_max);
+ if (cpi->oxcf.mode == ALLINTRA) {
+ const bool bsize_at_least_16x16 = (bsize >= BLOCK_16X16);
+ const bool prune_rect_part_using_4x4_var_deviation =
+ (cpi->sf.part_sf.prune_rect_part_using_4x4_var_deviation &&
+ !x->must_find_valid_partition);
- if ((var_min < 0.272) && ((var_max - var_min) > 3.0)) {
- part_search_state.partition_none_allowed = 0;
- part_search_state.terminate_partition_search = 0;
- part_search_state.do_square_split = 1;
+ if (bsize_at_least_16x16 || prune_rect_part_using_4x4_var_deviation) {
+ double var_min, var_max;
+ log_sub_block_var(cpi, x, bsize, &var_min, &var_max);
+
+ // Further pruning or in some cases reverse pruning when allintra is set.
+ // This code helps visual and in some cases metrics quality where the
+ // current block comprises at least one very low variance sub-block and at
+ // least one where the variance is much higher.
+ //
+ // The idea is that in such cases there is danger of ringing and other
+ // visual artifacts from a high variance feature such as an edge into a
+ // very low variance region.
+ //
+ // The approach taken is to force break down / split to a smaller block
+ // size to try and separate out the low variance and well predicted blocks
+ // from the more complex ones and to prevent propagation of ringing over a
+ // large region.
+ if (bsize_at_least_16x16 && (var_min < 0.272) &&
+ ((var_max - var_min) > 3.0)) {
+ part_search_state.partition_none_allowed = 0;
+ part_search_state.terminate_partition_search = 0;
+ part_search_state.do_square_split = 1;
+ } else if (prune_rect_part_using_4x4_var_deviation &&
+ (var_max - var_min < 3.0)) {
+ // Prune rectangular partitions if the variance deviation of 4x4
+ // sub-blocks within the block is less than a threshold (derived
+ // empirically).
+ part_search_state.do_rectangular_split = 0;
+ }
}
}
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 7e244d0..9e42391 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -502,6 +502,7 @@
sf->part_sf.prune_rectangular_split_based_on_qidx =
allow_screen_content_tools ? 0 : 2;
+ sf->part_sf.prune_rect_part_using_4x4_var_deviation = true;
sf->part_sf.prune_sub_8x8_partition_level =
allow_screen_content_tools ? 0 : 1;
sf->part_sf.prune_part4_search = 3;
@@ -1878,6 +1879,7 @@
part_sf->rect_partition_eval_thresh = BLOCK_128X128;
part_sf->prune_ext_part_using_split_info = 0;
part_sf->prune_rectangular_split_based_on_qidx = 0;
+ part_sf->prune_rect_part_using_4x4_var_deviation = false;
part_sf->early_term_after_none_split = 0;
part_sf->ml_predict_breakout_level = 0;
part_sf->prune_sub_8x8_partition_level = 0;
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index da0fd7a..4ff85f9 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -646,6 +646,18 @@
// 2 : prune all block size based on qindex
int prune_rectangular_split_based_on_qidx;
+ // Prune rectangular partitions based on 4x4 sub-block variance
+ // false : no pruning
+ // true : prune rectangular partitions based on 4x4 sub-block variance
+ // deviation
+ //
+ // For allintra encode, this speed feature reduces instruction count by 6.4%
+ // for speed=6 with coding performance change less than 0.24%. For AVIF image
+ // encode, this speed feature reduces encode time by 8.14% for speed 6 on a
+ // typical image dataset with coding performance change less than 0.16%. This
+ // speed feature is not applicable to speed >= 7.
+ bool prune_rect_part_using_4x4_var_deviation;
+
// Terminate partition search for child partition,
// when NONE and SPLIT partition rd_costs are INT64_MAX.
int early_term_after_none_split;