From fe5e2a91bb15241a97515708001c37deda514cdc Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Wed, 24 Jul 2013 14:07:37 +0100 Subject: [PATCH] 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 --- vp9/encoder/vp9_encodeframe.c | 71 +++++++++++++++++++++++++++++++++-- vp9/encoder/vp9_onyx_if.c | 28 +++++++++----- vp9/encoder/vp9_onyx_int.h | 11 ++++-- 3 files changed, 92 insertions(+), 18 deletions(-) diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 4823c4baa..1894ea166 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -1429,6 +1429,56 @@ static void rd_use_partition(VP9_COMP *cpi, MODE_INFO *m, TOKENEXTRA **tp, *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 @@ -1462,8 +1512,8 @@ static void rd_pick_partition(VP9_COMP *cpi, TOKENEXTRA **tp, int mi_row, 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 @@ static void rd_pick_partition(VP9_COMP *cpi, TOKENEXTRA **tp, int mi_row, } } - 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 @@ static void encode_sb_row(VP9_COMP *cpi, int mi_row, TOKENEXTRA **tp, || 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 @@ static void encode_sb_row(VP9_COMP *cpi, int mi_row, TOKENEXTRA **tp, } } } 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); } diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index fc19bd951..5b9d231a7 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -731,10 +731,13 @@ void vp9_set_speed_features(VP9_COMP *cpi) { 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 @@ void vp9_set_speed_features(VP9_COMP *cpi) { 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 @@ void vp9_set_speed_features(VP9_COMP *cpi) { 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 @@ void vp9_set_speed_features(VP9_COMP *cpi) { 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; } */ diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index 0798927bd..dc5e564ae 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -258,10 +258,13 @@ typedef struct { 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;