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
This commit is contained in:
Yaowu Xu 2015-02-09 10:21:17 -08:00
Родитель 2d924161c7
Коммит ee5d79995e
5 изменённых файлов: 61 добавлений и 41 удалений

Просмотреть файл

@ -471,6 +471,43 @@ static int set_vt_partitioning(VP9_COMP *cpi,
return 0; 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 // This function chooses partitioning based on the variance between source and
// reconstructed last, where variance is computed for downs-sampled inputs. // reconstructed last, where variance is computed for downs-sampled inputs.
static void choose_partitioning(VP9_COMP *cpi, static void choose_partitioning(VP9_COMP *cpi,
@ -479,7 +516,6 @@ static void choose_partitioning(VP9_COMP *cpi,
int mi_row, int mi_col) { int mi_row, int mi_col) {
VP9_COMMON * const cm = &cpi->common; VP9_COMMON * const cm = &cpi->common;
MACROBLOCKD *xd = &x->e_mbd; MACROBLOCKD *xd = &x->e_mbd;
int i, j, k, m; int i, j, k, m;
v64x64 vt; v64x64 vt;
v16x16 vt2[16]; v16x16 vt2[16];
@ -489,34 +525,12 @@ static void choose_partitioning(VP9_COMP *cpi,
int dp; int dp;
int pixels_wide = 64, pixels_high = 64; int pixels_wide = 64, pixels_high = 64;
const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME); 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. // Always use 4x4 partition for key frame.
const int is_key_frame = (cm->frame_type == KEY_FRAME); const int is_key_frame = (cm->frame_type == KEY_FRAME);
const int use_4x4_partition = is_key_frame; const int use_4x4_partition = is_key_frame;
const int low_res = (cm->width <= 352 && cm->height <= 288);
int variance4x4downsample[16]; 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); 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) { if (!is_key_frame) {
MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi; MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi;
unsigned int var = 0, sse; 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[0] = LAST_FRAME;
mbmi->ref_frame[1] = NONE; mbmi->ref_frame[1] = NONE;
mbmi->sb_type = BLOCK_64X64; mbmi->sb_type = BLOCK_64X64;
@ -619,7 +634,7 @@ static void choose_partitioning(VP9_COMP *cpi,
} }
if (is_key_frame || (low_res && if (is_key_frame || (low_res &&
vt.split[i].split[j].part_variances.none.variance > vt.split[i].split[j].part_variances.none.variance >
(threshold << 1))) { (cpi->vbp_threshold << 1))) {
// Go down to 4x4 down-sampling for variance. // Go down to 4x4 down-sampling for variance.
variance4x4downsample[i2 + j] = 1; variance4x4downsample[i2 + j] = 1;
for (k = 0; k < 4; k++) { for (k = 0; k < 4; k++) {
@ -680,30 +695,22 @@ static void choose_partitioning(VP9_COMP *cpi,
} }
fill_variance_tree(&vt, BLOCK_64X64); fill_variance_tree(&vt, BLOCK_64X64);
// Now go through the entire structure, splitting every block size until // Now go through the entire structure, splitting every block size until
// we get to one that's got a variance lower than our threshold. // 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 || 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, !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) { for (i = 0; i < 4; ++i) {
const int x32_idx = ((i & 1) << 2); const int x32_idx = ((i & 1) << 2);
const int y32_idx = ((i >> 1) << 2); const int y32_idx = ((i >> 1) << 2);
const int i2 = i << 2; const int i2 = i << 2;
if (!set_vt_partitioning(cpi, xd, &vt.split[i], BLOCK_32X32, if (!set_vt_partitioning(cpi, xd, &vt.split[i], BLOCK_32X32,
(mi_row + y32_idx), (mi_col + x32_idx), (mi_row + y32_idx), (mi_col + x32_idx),
threshold, BLOCK_16X16)) { cpi->vbp_threshold,
BLOCK_16X16)) {
for (j = 0; j < 4; ++j) { for (j = 0; j < 4; ++j) {
const int x16_idx = ((j & 1) << 1); const int x16_idx = ((j & 1) << 1);
const int y16_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 // For inter frames: if variance4x4downsample[] == 1 for this 16x16
// block, then the variance is based on 4x4 down-sampling, so use vt2 // block, then the variance is based on 4x4 down-sampling, so use vt2
// in set_vt_partioning(), otherwise use vt. // 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, if (!set_vt_partitioning(cpi, xd, vtemp, BLOCK_16X16,
mi_row + y32_idx + y16_idx, mi_row + y32_idx + y16_idx,
mi_col + x32_idx + x16_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) { for (k = 0; k < 4; ++k) {
const int x8_idx = (k & 1); const int x8_idx = (k & 1);
const int y8_idx = (k >> 1); const int y8_idx = (k >> 1);
@ -722,7 +730,8 @@ static void choose_partitioning(VP9_COMP *cpi,
BLOCK_8X8, BLOCK_8X8,
mi_row + y32_idx + y16_idx + y8_idx, mi_row + y32_idx + y16_idx + y8_idx,
mi_col + x32_idx + x16_idx + x8_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, set_block_size(cpi, xd,
(mi_row + y32_idx + y16_idx + y8_idx), (mi_row + y32_idx + y16_idx + y8_idx),
(mi_col + x32_idx + x16_idx + x8_idx), (mi_col + x32_idx + x16_idx + x8_idx),

Просмотреть файл

@ -38,6 +38,8 @@ void vp9_init_tile_data(struct VP9_COMP *cpi);
void vp9_encode_tile(struct VP9_COMP *cpi, struct ThreadData *td, void vp9_encode_tile(struct VP9_COMP *cpi, struct ThreadData *td,
int tile_row, int tile_col); int tile_row, int tile_col);
void vp9_set_vbp_thresholds(struct VP9_COMP *cpi, int q);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

Просмотреть файл

@ -2800,7 +2800,10 @@ static void encode_without_recode_loop(VP9_COMP *cpi) {
set_size_dependent_vars(cpi, &q, &bottom_index, &top_index); set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
vp9_set_quantizer(cm, q); vp9_set_quantizer(cm, q);
vp9_set_vbp_thresholds(cpi, q);
setup_frame(cpi); setup_frame(cpi);
// Variance adaptive and in frame q adjustment experiments are mutually // Variance adaptive and in frame q adjustment experiments are mutually
// exclusive. // exclusive.
if (cpi->oxcf.aq_mode == VARIANCE_AQ) { if (cpi->oxcf.aq_mode == VARIANCE_AQ) {

Просмотреть файл

@ -450,6 +450,13 @@ typedef struct VP9_COMP {
int resize_pending; 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 // Multi-threading
int num_workers; int num_workers;
VP9Worker *workers; VP9Worker *workers;

Просмотреть файл

@ -421,4 +421,3 @@ void vp9_set_speed_features_framesize_dependent(struct VP9_COMP *cpi);
#endif #endif
#endif // VP9_ENCODER_VP9_SPEED_FEATURES_H_ #endif // VP9_ENCODER_VP9_SPEED_FEATURES_H_