ref: fe5e2a91bb15241a97515708001c37deda514cdc
parent: 67b07c520d253955d1b4ea2d0fca2a7d3b905bba
author: Paul Wilkins <[email protected]>
date: Wed Jul 24 10:07:37 EDT 2013
Auto min and max partition size experiment. Speed feature experiment to set an upper and lower partition size limit based on what has been seen in spatial neighbors. This seems to gives quite reasonable speed gains in local (10-15%) and when used with speed 0 the losses are small (0.25% derf, 0.35% stdhd). However, for now I am only enabling it on speed 1 as there may be clashes with the existing temporal partition selection in speed 2. Using a tighter min / max around the range derived from the neighbors increases speed further but at the cost of a bigger quality loss. However, I think this spatial method could be combined with data from either the last frame or a variance method (or both) to refine the range of minimum and maximum partition size. I.e. consider the min and max from spatial and temporal neighbors and the variance recommendation. Change-Id: I1b96bf8b84368d6aad0c7aa600fe141b4f07435f
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -1429,7 +1429,57 @@
*dist = chosen_dist;
}
+static BLOCK_SIZE_TYPE min_partition_size[BLOCK_SIZE_TYPES] =
+ { BLOCK_4X4, BLOCK_4X4, BLOCK_4X4, BLOCK_4X4,
+ BLOCK_4X4, BLOCK_4X4, BLOCK_8X8, BLOCK_8X8,
+ BLOCK_8X8, BLOCK_16X16, BLOCK_16X16, BLOCK_16X16, BLOCK_16X16 };
+static BLOCK_SIZE_TYPE max_partition_size[BLOCK_SIZE_TYPES] =
+ { BLOCK_8X8, BLOCK_16X16, BLOCK_16X16, BLOCK_16X16,
+ BLOCK_32X32, BLOCK_32X32, BLOCK_32X32, BLOCK_64X64,
+ BLOCK_64X64, BLOCK_64X64, BLOCK_64X64, BLOCK_64X64, BLOCK_64X64 };
+
+// Look at neighbouring blocks and set a min and max partition size based on
+// what they chose.
+static void rd_auto_partition_range(VP9_COMP *cpi,
+ BLOCK_SIZE_TYPE * min_block_size,
+ BLOCK_SIZE_TYPE * max_block_size) {
+ MACROBLOCKD *const xd = &cpi->mb.e_mbd;
+ const MODE_INFO *const mi = xd->mode_info_context;
+ const MB_MODE_INFO *const above_mbmi = &mi[-xd->mode_info_stride].mbmi;
+ const MB_MODE_INFO *const left_mbmi = &mi[-1].mbmi;
+ const int left_in_image = xd->left_available && left_mbmi->mb_in_image;
+ const int above_in_image = xd->up_available && above_mbmi->mb_in_image;
+
+ // Frequency check
+ if (cpi->sf.auto_min_max_partition_count <= 0) {
+ cpi->sf.auto_min_max_partition_count =
+ cpi->sf.auto_min_max_partition_interval;
+ *min_block_size = BLOCK_4X4;
+ *max_block_size = BLOCK_64X64;
+ return;
+ } else {
+ --cpi->sf.auto_min_max_partition_count;
+ }
+
+ // Check for edge cases
+ if (!left_in_image && !above_in_image) {
+ *min_block_size = BLOCK_4X4;
+ *max_block_size = BLOCK_64X64;
+ } else if (!left_in_image) {
+ *min_block_size = min_partition_size[above_mbmi->sb_type];
+ *max_block_size = max_partition_size[above_mbmi->sb_type];
+ } else if (!above_in_image) {
+ *min_block_size = min_partition_size[left_mbmi->sb_type];
+ *max_block_size = max_partition_size[left_mbmi->sb_type];
+ } else {
+ *min_block_size =
+ min_partition_size[MIN(left_mbmi->sb_type, above_mbmi->sb_type)];
+ *max_block_size =
+ max_partition_size[MAX(left_mbmi->sb_type, above_mbmi->sb_type)];
+ }
+}
+
// TODO(jingning,jimbankoski,rbultje): properly skip partition types that are
// unlikely to be selected depending on previously rate-distortion optimization
// results, for encoding speed-up.
@@ -1462,8 +1512,8 @@
save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
// PARTITION_SPLIT
- if (!cpi->sf.use_partitions_greater_than ||
- bsize > cpi->sf.greater_than_block_size) {
+ if (!cpi->sf.auto_min_max_partition_size ||
+ bsize >= cpi->sf.min_partition_size) {
if (bsize > BLOCK_SIZE_SB8X8) {
int r4 = 0;
int64_t d4 = 0, sum_rd = 0;
@@ -1604,8 +1654,8 @@
}
}
- if (!cpi->sf.use_partitions_less_than ||
- bsize <= cpi->sf.less_than_block_size) {
+ if (!cpi->sf.use_max_partition_size ||
+ bsize <= cpi->sf.max_partition_size) {
int larger_is_better = 0;
// PARTITION_NONE
if ((mi_row + (ms >> 1) < cm->mi_rows) &&
@@ -1876,6 +1926,12 @@
|| cpi->common.show_frame == 0
|| cpi->common.frame_type == KEY_FRAME
|| cpi->is_src_frame_alt_ref) {
+ // If required set upper and lower partition size limits
+ if (cpi->sf.auto_min_max_partition_size) {
+ rd_auto_partition_range(cpi,
+ &cpi->sf.min_partition_size,
+ &cpi->sf.max_partition_size);
+ }
rd_pick_partition(cpi, tp, mi_row, mi_col, BLOCK_SIZE_SB64X64,
&dummy_rate, &dummy_dist, 1, INT64_MAX);
} else {
@@ -1885,6 +1941,13 @@
}
}
} else {
+ // If required set upper and lower partition size limits
+ if (cpi->sf.auto_min_max_partition_size) {
+ rd_auto_partition_range(cpi,
+ &cpi->sf.min_partition_size,
+ &cpi->sf.max_partition_size);
+ }
+
rd_pick_partition(cpi, tp, mi_row, mi_col, BLOCK_SIZE_SB64X64,
&dummy_rate, &dummy_dist, 1, INT64_MAX);
}
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -731,10 +731,13 @@
sf->use_one_partition_size_always = 0;
sf->less_rectangular_check = 0;
sf->use_square_partition_only = 0;
- sf->use_partitions_less_than = 0;
- sf->less_than_block_size = BLOCK_SIZE_MB16X16;
- sf->use_partitions_greater_than = 0;
- sf->greater_than_block_size = BLOCK_SIZE_SB8X8;
+ sf->auto_min_max_partition_size = 0;
+ sf->auto_min_max_partition_interval = 0;
+ sf->auto_min_max_partition_count = 0;
+ sf->use_max_partition_size = 0;
+ sf->max_partition_size = BLOCK_64X64;
+ sf->use_min_partition_size = 0;
+ sf->min_partition_size = BLOCK_4X4;
sf->adjust_partitioning_from_last_frame = 0;
sf->last_partitioning_redo_frequency = 4;
sf->disable_splitmv = 0;
@@ -788,10 +791,15 @@
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH |
FLAG_SKIP_INTRA_BESTINTER |
FLAG_SKIP_COMP_BESTINTRA;
- sf->last_chroma_intra_mode = H_PRED;
+ sf->use_uv_intra_rd_estimate = 1;
sf->use_rd_breakout = 1;
sf->skip_encode_sb = 1;
sf->auto_mv_step_size = 1;
+
+ sf->auto_min_max_partition_size = 1;
+ sf->use_max_partition_size = 1;
+ sf->use_min_partition_size = 1;
+ sf->auto_min_max_partition_interval = 1;
}
if (speed == 2) {
sf->adjust_thresholds_by_speed = 1;
@@ -812,9 +820,9 @@
FLAG_SKIP_COMP_BESTINTRA |
FLAG_SKIP_COMP_REFMISMATCH;
sf->last_chroma_intra_mode = DC_PRED;
+ sf->use_uv_intra_rd_estimate = 1;
sf->use_rd_breakout = 1;
sf->skip_encode_sb = 1;
- sf->use_uv_intra_rd_estimate = 1;
sf->using_small_partition_info = 1;
sf->disable_splitmv =
(MIN(cpi->common.width, cpi->common.height) >= 720)? 1 : 0;
@@ -862,14 +870,14 @@
if (speed == 2) {
sf->first_step = 0;
sf->comp_inter_joint_search_thresh = BLOCK_SIZE_SB8X8;
- sf->use_partitions_less_than = 1;
- sf->less_than_block_size = BLOCK_SIZE_MB16X16;
+ sf->use_max_partition_size = 1;
+ sf->max_partition_size = BLOCK_SIZE_MB16X16;
}
if (speed == 3) {
sf->first_step = 0;
sf->comp_inter_joint_search_thresh = BLOCK_SIZE_SB8X8;
- sf->use_partitions_greater_than = 1;
- sf->greater_than_block_size = BLOCK_SIZE_SB8X8;
+ sf->use_min_partition_size = 1;
+ sf->min_partition_size = BLOCK_SIZE_SB8X8;
}
*/
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -258,10 +258,13 @@
int unused_mode_skip_lvl;
int reference_masking;
BLOCK_SIZE_TYPE always_this_block_size;
- int use_partitions_greater_than;
- BLOCK_SIZE_TYPE greater_than_block_size;
- int use_partitions_less_than;
- BLOCK_SIZE_TYPE less_than_block_size;
+ int auto_min_max_partition_size;
+ int auto_min_max_partition_interval;
+ int auto_min_max_partition_count;
+ int use_min_partition_size;
+ BLOCK_SIZE_TYPE min_partition_size;
+ int use_max_partition_size;
+ BLOCK_SIZE_TYPE max_partition_size;
int adjust_partitioning_from_last_frame;
int last_partitioning_redo_frequency;
int disable_splitmv;