From: Sai Deng Date: Sat, 13 Apr 2019 17:47:46 +0000 (+0000) Subject: Merge "Add Tune for SSIM" X-Git-Tag: v1.8.1~117 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a9b722e00c2df9a4a731c28521d43aeca5b3a035;p=libvpx Merge "Add Tune for SSIM" --- a9b722e00c2df9a4a731c28521d43aeca5b3a035 diff --cc vp9/encoder/vp9_encoder.c index cc7d1bb3b,8cae60958..f92c8a464 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@@ -4718,15 -4731,73 +4732,81 @@@ static void set_frame_index(VP9_COMP *c } } + // Implementation and modifications of C. Yeo, H. L. Tan, and Y. H. Tan, "On + // rate distortion optimization using SSIM," Circuits and Systems for Video + // Technology, IEEE Transactions on, vol. 23, no. 7, pp. 1170-1181, 2013. + // SSIM_VAR_SCALE defines the strength of the bias towards SSIM in RDO. + // Some sample values are: + // SSIM_VAR_SCALE avg_psnr ssim ms_ssim (for midres test set) + // 16.0 2.312 -3.062 -3.882 + // 32.0 0.852 -2.260 -2.821 + // 64.0 0.294 -1.606 -1.925 + #define SSIM_VAR_SCALE 16.0 + static void set_mb_ssim_rdmult_scaling(VP9_COMP *cpi) { + const double c2 = 0.03 * 0.03 * 255 * 255; + VP9_COMMON *cm = &cpi->common; + ThreadData *td = &cpi->td; + MACROBLOCK *x = &td->mb; + MACROBLOCKD *xd = &x->e_mbd; + uint8_t *y_buffer = cpi->Source->y_buffer; + const int y_stride = cpi->Source->y_stride; + const int block_size = BLOCK_64X64; + + const int num_8x8_w = num_8x8_blocks_wide_lookup[block_size]; + const int num_8x8_h = num_8x8_blocks_high_lookup[block_size]; + const int num_cols = (cm->mi_cols + num_8x8_w - 1) / num_8x8_w; + const int num_rows = (cm->mi_rows + num_8x8_h - 1) / num_8x8_h; + double log_sum = 0.0; + int row, col; + + // Loop through each 64x64 block. + for (row = 0; row < num_rows; ++row) { + for (col = 0; col < num_cols; ++col) { + int mi_row, mi_col; + double var = 0.0, num_of_var = 0.0; + const int index = row * num_cols + col; + + for (mi_row = row * num_8x8_h; + mi_row < cm->mi_rows && mi_row < (row + 1) * num_8x8_h; ++mi_row) { + for (mi_col = col * num_8x8_w; + mi_col < cm->mi_cols && mi_col < (col + 1) * num_8x8_w; ++mi_col) { + struct buf_2d buf; + const int row_offset_y = mi_row << 3; + const int col_offset_y = mi_col << 3; + + buf.buf = y_buffer + row_offset_y * y_stride + col_offset_y; + buf.stride = y_stride; + var += vp9_get_sby_variance(cpi, &buf, BLOCK_8X8) / 64.0; + num_of_var += 1.0; + } + } + var = var / num_of_var / SSIM_VAR_SCALE; + var = 2.0 * var + c2; + cpi->mi_ssim_rdmult_scaling_factors[index] = var; + log_sum += log(var); + } + } + log_sum = exp(log_sum / (double)(num_rows * num_cols)); + + for (row = 0; row < num_rows; ++row) { + for (col = 0; col < num_cols; ++col) { + const int index = row * num_cols + col; + cpi->mi_ssim_rdmult_scaling_factors[index] /= log_sum; + } + } + + (void)xd; + } + // Process the wiener variance in 16x16 block basis. +static int qsort_comp(const void *elem1, const void *elem2) { + int a = *((const int *)elem1); + int b = *((const int *)elem2); + if (a > b) return 1; + if (a < b) return -1; + return 0; +} + static void set_mb_wiener_variance(VP9_COMP *cpi) { VP9_COMMON *cm = &cpi->common; uint8_t *buffer = cpi->Source->y_buffer;