Fix normalization in dq3 mode Make the normalization calculation process account for the fact that deltaq mode is operated in units of superblocks. This resolves a mismatch between the normalization and superblock QP decision process that leads to universally increased operating bit-rate at low QPs. For a few 4K test clips at low QPs, this improves the encoding speed by 20-40% on a single threads. BUG=b/257074966 Change-Id: I392ffcae9aeef40d63a2e610167043ab5899160a
diff --git a/av1/encoder/allintra_vis.c b/av1/encoder/allintra_vis.c index b0a9e24..a3e3e69 100644 --- a/av1/encoder/allintra_vis.c +++ b/av1/encoder/allintra_vis.c
@@ -202,121 +202,10 @@ return sb_wiener_var; } -static double calc_src_mean_var(const uint8_t *const src_buffer, - const int buf_stride, const int block_size, - const int use_hbd, double *mean) { - double src_mean = 0.0; - double src_variance = 0.0; - for (int pix_row = 0; pix_row < block_size; ++pix_row) { - for (int pix_col = 0; pix_col < block_size; ++pix_col) { - int src_pix; - if (use_hbd) { - const uint16_t *src = CONVERT_TO_SHORTPTR(src_buffer); - src_pix = src[pix_row * buf_stride + pix_col]; - } else { - src_pix = src_buffer[pix_row * buf_stride + pix_col]; - } - src_mean += src_pix; - src_variance += src_pix * src_pix; - } - } - const int pix_num = block_size * block_size; - src_variance -= (src_mean * src_mean) / pix_num; - src_variance /= pix_num; - *mean = src_mean / pix_num; - return src_variance; -} - -static BLOCK_SIZE pick_block_size(AV1_COMP *cpi, - const BLOCK_SIZE orig_block_size) { - const BLOCK_SIZE sub_block_size = - get_partition_subsize(orig_block_size, PARTITION_SPLIT); - const int mb_step = mi_size_wide[orig_block_size]; - const int sub_step = mb_step >> 1; - const TX_SIZE tx_size = max_txsize_lookup[orig_block_size]; - const int block_size = tx_size_wide[tx_size]; - const int split_block_size = block_size >> 1; - assert(split_block_size >= 8); - const uint8_t *const buffer = cpi->source->y_buffer; - const int buf_stride = cpi->source->y_stride; - const int use_hbd = cpi->source->flags & YV12_FLAG_HIGHBITDEPTH; - - double vote = 0.0; - for (int mi_row = 0; mi_row < cpi->frame_info.mi_rows; mi_row += mb_step) { - for (int mi_col = 0; mi_col < cpi->frame_info.mi_cols; mi_col += mb_step) { - const uint8_t *mb_buffer = - buffer + mi_row * MI_SIZE * buf_stride + mi_col * MI_SIZE; - // (1). Calculate mean and var using the original block size - double mean = 0.0; - const double orig_var = - calc_src_mean_var(mb_buffer, buf_stride, block_size, use_hbd, &mean); - // (2). Calculate mean and var using the split block size - double split_var[4] = { 0 }; - double split_mean[4] = { 0 }; - int sub_idx = 0; - for (int row = mi_row; row < mi_row + mb_step; row += sub_step) { - for (int col = mi_col; col < mi_col + mb_step; col += sub_step) { - mb_buffer = buffer + row * MI_SIZE * buf_stride + col * MI_SIZE; - split_var[sub_idx] = - calc_src_mean_var(mb_buffer, buf_stride, split_block_size, - use_hbd, &split_mean[sub_idx]); - ++sub_idx; - } - } - // (3). Determine whether to use the original or the split block size. - // If use original, vote += 1.0. - // If use split, vote -= 1.0. - double max_split_mean = 0.0; - double max_split_var = 0.0; - double geo_split_var = 0.0; - for (int i = 0; i < 4; ++i) { - max_split_mean = AOMMAX(max_split_mean, split_mean[i]); - max_split_var = AOMMAX(max_split_var, split_var[i]); - geo_split_var += log(0.1 + split_var[i]); - } - geo_split_var = exp(geo_split_var / 4); - const double param_1 = 1.5; - const double param_2 = 1.0; - // If the variance of the large block size is considerably larger than the - // geometric mean of vars of small blocks; - // Or if the variance of the large block size is larger than the local - // variance; - // Or if the variance of the large block size is considerably larger - // than the mean. - // It indicates that the source block is not a flat area, therefore we - // might want to split into smaller block sizes to capture the - // local characteristics. - if (orig_var > param_1 * geo_split_var || orig_var > max_split_var || - sqrt(orig_var) > param_2 * mean) { - vote -= 1.0; - } else { - vote += 1.0; - } - } - } - - return vote > 0.0 ? orig_block_size : sub_block_size; -} - -static int64_t pick_norm_factor_and_block_size(AV1_COMP *const cpi, - BLOCK_SIZE *best_block_size) { +static int64_t estimate_wiener_var_norm(AV1_COMP *const cpi, + const BLOCK_SIZE norm_block_size) { const AV1_COMMON *const cm = &cpi->common; - const BLOCK_SIZE sb_size = cm->seq_params->sb_size; - BLOCK_SIZE last_block_size; - BLOCK_SIZE this_block_size = sb_size; - *best_block_size = sb_size; - // Pick from block size 128x128, 64x64, 32x32 and 16x16. - do { - last_block_size = this_block_size; - assert(this_block_size >= BLOCK_16X16 && this_block_size <= BLOCK_128X128); - const int block_size = block_size_wide[this_block_size]; - if (block_size < 32) break; - this_block_size = pick_block_size(cpi, last_block_size); - } while (this_block_size != last_block_size); - *best_block_size = this_block_size; - int64_t norm_factor = 1; - const BLOCK_SIZE norm_block_size = this_block_size; assert(norm_block_size >= BLOCK_16X16 && norm_block_size <= BLOCK_128X128); const int norm_step = mi_size_wide[norm_block_size]; double sb_wiener_log = 0; @@ -548,9 +437,8 @@ // Determine whether to turn off several intra coding tools. automatic_intra_tools_off(cpi, sum_rec_distortion, sum_est_rate); - BLOCK_SIZE norm_block_size = BLOCK_16X16; - cpi->norm_wiener_variance = - pick_norm_factor_and_block_size(cpi, &norm_block_size); + const BLOCK_SIZE norm_block_size = cm->seq_params->sb_size; + cpi->norm_wiener_variance = estimate_wiener_var_norm(cpi, norm_block_size); const int norm_step = mi_size_wide[norm_block_size]; double sb_wiener_log = 0;