From ee5d79995e5e5adc2b4f38f374f3f63624b73c57 Mon Sep 17 00:00:00 2001 From: Yaowu Xu Date: Mon, 9 Feb 2015 10:21:17 -0800 Subject: [PATCH] Move computation up to frame level This is to avoid redo the same calculation repeatly, and also allow easier adjustments for further experiments. This commit shall have no effect on quality/compression. Change-Id: I4460acf5c808ff5518da18d21e002c5da58af857 --- vp9/encoder/vp9_encodeframe.c | 89 ++++++++++++++++++++++------------------ vp9/encoder/vp9_encodeframe.h | 2 + vp9/encoder/vp9_encoder.c | 3 ++ vp9/encoder/vp9_encoder.h | 7 ++++ vp9/encoder/vp9_speed_features.h | 1 - 5 files changed, 61 insertions(+), 41 deletions(-) diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 0885909..99bb930 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -471,6 +471,43 @@ static int set_vt_partitioning(VP9_COMP *cpi, return 0; } + +void vp9_set_vbp_thresholds(VP9_COMP *cpi, int q) { + SPEED_FEATURES *const sf = &cpi->sf; + if (sf->partition_search_type != VAR_BASED_PARTITION) { + return; + } else { + VP9_COMMON *const cm = &cpi->common; + const VP9EncoderConfig *const oxcf = &cpi->oxcf; + const int is_key_frame = (cm->frame_type == KEY_FRAME); + const int use_4x4_partition = is_key_frame; + const int low_res = (cm->width <= 352 && cm->height <= 288); + const int threshold_multiplier = is_key_frame ? 80 : 4; + const int64_t threshold_base = (int64_t)(threshold_multiplier * + vp9_convert_qindex_to_q(q, cm->bit_depth)); + cpi->vbp_threshold = threshold_base; + cpi->vbp_threshold_bsize_min = threshold_base << oxcf->speed; + cpi->vbp_threshold_bsize_max = threshold_base; + + if (is_key_frame) { + cpi->vbp_threshold = threshold_base >> 2; + cpi->vbp_threshold_bsize_min = threshold_base << 2; + } else if (low_res) { + cpi->vbp_threshold_bsize_min = threshold_base << 3; + cpi->vbp_threshold_bsize_max = threshold_base >> 2; + } + // TODO(marpan): Allow 4x4 partitions for inter-frames. + // use_4x4_partition = (variance4x4downsample[i2 + j] == 1); + // If 4x4 partition is not used, then 8x8 partition will be selected + // if variance of 16x16 block is very high, so use larger threshold + // for 16x16 (threshold_bsize_min) in that case. + cpi->vbp_threshold_16x16 = (use_4x4_partition) ? + cpi->vbp_threshold : cpi->vbp_threshold_bsize_min; + cpi->vbp_bsize_min = (use_4x4_partition) ? BLOCK_8X8 : BLOCK_16X16; + } +} + + // This function chooses partitioning based on the variance between source and // reconstructed last, where variance is computed for downs-sampled inputs. static void choose_partitioning(VP9_COMP *cpi, @@ -479,7 +516,6 @@ static void choose_partitioning(VP9_COMP *cpi, int mi_row, int mi_col) { VP9_COMMON * const cm = &cpi->common; MACROBLOCKD *xd = &x->e_mbd; - int i, j, k, m; v64x64 vt; v16x16 vt2[16]; @@ -489,34 +525,12 @@ static void choose_partitioning(VP9_COMP *cpi, int dp; int pixels_wide = 64, pixels_high = 64; const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME); - const struct scale_factors *const sf = &cm->frame_refs[LAST_FRAME - 1].sf; + // Always use 4x4 partition for key frame. const int is_key_frame = (cm->frame_type == KEY_FRAME); const int use_4x4_partition = is_key_frame; + const int low_res = (cm->width <= 352 && cm->height <= 288); int variance4x4downsample[16]; - int low_res = (cm->width <= 352 && cm->height <= 288) ? 1 : 0; - const int threshold_multiplier = is_key_frame ? 80 : 4; - int64_t threshold_base; - int64_t threshold; - int64_t threshold_bsize_min; - int64_t threshold_bsize_max; - - vp9_clear_system_state(); - threshold_base = (int64_t)(threshold_multiplier * - vp9_convert_qindex_to_q(cm->base_qindex, cm->bit_depth)); - threshold = threshold_base; - threshold_bsize_min = threshold_base << cpi->oxcf.speed; - threshold_bsize_max = threshold_base; - - // Modify thresholds for key frame and for low-resolutions (set lower - // thresholds to favor split). - if (is_key_frame) { - threshold = threshold_base >> 2; - threshold_bsize_min = threshold_base << 2; - } else if (low_res) { - threshold_bsize_min = threshold_base << 3; - threshold_bsize_max = threshold_base >> 2; - } set_offsets(cpi, tile, x, mi_row, mi_col, BLOCK_64X64); @@ -531,7 +545,8 @@ static void choose_partitioning(VP9_COMP *cpi, if (!is_key_frame) { MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi; unsigned int var = 0, sse; - vp9_setup_pre_planes(xd, 0, yv12, mi_row, mi_col, sf); + vp9_setup_pre_planes(xd, 0, yv12, mi_row, mi_col, + &cm->frame_refs[LAST_FRAME - 1].sf); mbmi->ref_frame[0] = LAST_FRAME; mbmi->ref_frame[1] = NONE; mbmi->sb_type = BLOCK_64X64; @@ -619,7 +634,7 @@ static void choose_partitioning(VP9_COMP *cpi, } if (is_key_frame || (low_res && vt.split[i].split[j].part_variances.none.variance > - (threshold << 1))) { + (cpi->vbp_threshold << 1))) { // Go down to 4x4 down-sampling for variance. variance4x4downsample[i2 + j] = 1; for (k = 0; k < 4; k++) { @@ -680,30 +695,22 @@ static void choose_partitioning(VP9_COMP *cpi, } fill_variance_tree(&vt, BLOCK_64X64); - // Now go through the entire structure, splitting every block size until // we get to one that's got a variance lower than our threshold. if ( mi_col + 8 > cm->mi_cols || mi_row + 8 > cm->mi_rows || !set_vt_partitioning(cpi, xd, &vt, BLOCK_64X64, mi_row, mi_col, - threshold_bsize_max, BLOCK_16X16)) { + cpi->vbp_threshold_bsize_max, BLOCK_16X16)) { for (i = 0; i < 4; ++i) { const int x32_idx = ((i & 1) << 2); const int y32_idx = ((i >> 1) << 2); const int i2 = i << 2; if (!set_vt_partitioning(cpi, xd, &vt.split[i], BLOCK_32X32, (mi_row + y32_idx), (mi_col + x32_idx), - threshold, BLOCK_16X16)) { + cpi->vbp_threshold, + BLOCK_16X16)) { for (j = 0; j < 4; ++j) { const int x16_idx = ((j & 1) << 1); const int y16_idx = ((j >> 1) << 1); - // TODO(marpan): Allow 4x4 partitions for inter-frames. - // use_4x4_partition = (variance4x4downsample[i2 + j] == 1); - // If 4x4 partition is not used, then 8x8 partition will be selected - // if variance of 16x16 block is very high, so use larger threshold - // for 16x16 (threshold_bsize_min) in that case. - uint64_t threshold_16x16 = (use_4x4_partition) ? threshold : - threshold_bsize_min; - BLOCK_SIZE bsize_min = (use_4x4_partition) ? BLOCK_8X8 : BLOCK_16X16; // For inter frames: if variance4x4downsample[] == 1 for this 16x16 // block, then the variance is based on 4x4 down-sampling, so use vt2 // in set_vt_partioning(), otherwise use vt. @@ -713,7 +720,8 @@ static void choose_partitioning(VP9_COMP *cpi, if (!set_vt_partitioning(cpi, xd, vtemp, BLOCK_16X16, mi_row + y32_idx + y16_idx, mi_col + x32_idx + x16_idx, - threshold_16x16, bsize_min)) { + cpi->vbp_threshold_16x16, + cpi->vbp_bsize_min)) { for (k = 0; k < 4; ++k) { const int x8_idx = (k & 1); const int y8_idx = (k >> 1); @@ -722,7 +730,8 @@ static void choose_partitioning(VP9_COMP *cpi, BLOCK_8X8, mi_row + y32_idx + y16_idx + y8_idx, mi_col + x32_idx + x16_idx + x8_idx, - threshold_bsize_min, BLOCK_8X8)) { + cpi->vbp_threshold_bsize_min, + BLOCK_8X8)) { set_block_size(cpi, xd, (mi_row + y32_idx + y16_idx + y8_idx), (mi_col + x32_idx + x16_idx + x8_idx), diff --git a/vp9/encoder/vp9_encodeframe.h b/vp9/encoder/vp9_encodeframe.h index 556f3a5..8d545b6 100644 --- a/vp9/encoder/vp9_encodeframe.h +++ b/vp9/encoder/vp9_encodeframe.h @@ -38,6 +38,8 @@ void vp9_init_tile_data(struct VP9_COMP *cpi); void vp9_encode_tile(struct VP9_COMP *cpi, struct ThreadData *td, int tile_row, int tile_col); +void vp9_set_vbp_thresholds(struct VP9_COMP *cpi, int q); + #ifdef __cplusplus } // extern "C" #endif diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 65b6605..eda38ff 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -2800,7 +2800,10 @@ static void encode_without_recode_loop(VP9_COMP *cpi) { set_size_dependent_vars(cpi, &q, &bottom_index, &top_index); vp9_set_quantizer(cm, q); + vp9_set_vbp_thresholds(cpi, q); + setup_frame(cpi); + // Variance adaptive and in frame q adjustment experiments are mutually // exclusive. if (cpi->oxcf.aq_mode == VARIANCE_AQ) { diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index 1e4c982..35c5a48 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -450,6 +450,13 @@ typedef struct VP9_COMP { int resize_pending; + // VAR_BASED_PARTITION thresholds + int64_t vbp_threshold; + int64_t vbp_threshold_bsize_min; + int64_t vbp_threshold_bsize_max; + int64_t vbp_threshold_16x16; + BLOCK_SIZE vbp_bsize_min; + // Multi-threading int num_workers; VP9Worker *workers; diff --git a/vp9/encoder/vp9_speed_features.h b/vp9/encoder/vp9_speed_features.h index eaa0acc..8722d9c 100644 --- a/vp9/encoder/vp9_speed_features.h +++ b/vp9/encoder/vp9_speed_features.h @@ -421,4 +421,3 @@ void vp9_set_speed_features_framesize_dependent(struct VP9_COMP *cpi); #endif #endif // VP9_ENCODER_VP9_SPEED_FEATURES_H_ - -- 2.7.4