[dist-8x8] Bug fix - exclude invisible pixels There were two places where invisible pixels are included when calculating distortion with dist-8x8 is turned on. Those are bugs and fixed by this commit. 1) When av1_dist_8x8() is called in dist_8x8_sub8x8_txfm_rd() - New assert() are also added to detect any failures in the future. 2) Inside av1_dist_8x8() and av1_dist_8x8_diff(), with tune-metric == PSNR. Change-Id: I078d1feb3bb010c0e34041640bb69a400125817a
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c index 8f7862a..b1c0fb3 100644 --- a/av1/encoder/rdopt.c +++ b/av1/encoder/rdopt.c
@@ -628,6 +628,37 @@ #define FAST_EXT_TX_CORR_MARGIN 0.5 #define FAST_EXT_TX_EDST_MARGIN 0.3 +static unsigned pixel_dist_visible_only( + const AV1_COMP *const cpi, const MACROBLOCK *x, const uint8_t *src, + const int src_stride, const uint8_t *dst, const int dst_stride, + const BLOCK_SIZE tx_bsize, int txb_rows, int txb_cols, int visible_rows, + int visible_cols) { + unsigned sse; + + if (txb_rows == visible_rows && txb_cols == visible_cols +#if CONFIG_RECT_TX_EXT && (CONFIG_EXT_TX || CONFIG_VAR_TX) + && tx_bsize < BLOCK_SIZES +#endif + ) { + cpi->fn_ptr[tx_bsize].vf(src, src_stride, dst, dst_stride, &sse); + return sse; + } +#if CONFIG_HIGHBITDEPTH + const MACROBLOCKD *xd = &x->e_mbd; + + if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { + uint64_t sse64 = aom_highbd_sse_odd_size(src, src_stride, dst, dst_stride, + visible_cols, visible_rows); + return (unsigned int)ROUND_POWER_OF_TWO(sse64, (xd->bd - 8) * 2); + } +#else + (void)x; +#endif // CONFIG_HIGHBITDEPTH + sse = aom_sse_odd_size(src, src_stride, dst, dst_stride, visible_cols, + visible_rows); + return sse; +} + #if CONFIG_DIST_8X8 static uint64_t cdef_dist_8x8_16bit(uint16_t *dst, int dstride, uint16_t *src, int sstride, int coeff_shift) { @@ -953,10 +984,8 @@ #endif } else { // Otherwise, MSE by default - unsigned sse; - // TODO(Any): Use even faster function which does not calculate variance - cpi->fn_ptr[tx_bsize].vf(src, src_stride, dst, dst_stride, &sse); - d = sse; + d = pixel_dist_visible_only(cpi, x, src, src_stride, dst, dst_stride, + tx_bsize, bsh, bsw, visible_h, visible_w); } return d; @@ -1036,7 +1065,7 @@ // input } else { // Otherwise, MSE by default - d = aom_sum_squares_2d_i16(diff, diff_stride, bsw, bsh); + d = aom_sum_squares_2d_i16(diff, diff_stride, visible_w, visible_h); } return d; @@ -1725,25 +1754,10 @@ visible_rows, x->qindex); #endif // CONFIG_DIST_8X8 -#if CONFIG_RECT_TX_EXT && (CONFIG_EXT_TX || CONFIG_VAR_TX) - if ((txb_rows == visible_rows && txb_cols == visible_cols) && - tx_bsize < BLOCK_SIZES) { -#else - if (txb_rows == visible_rows && txb_cols == visible_cols) { -#endif - unsigned sse; - cpi->fn_ptr[tx_bsize].vf(src, src_stride, dst, dst_stride, &sse); - return sse; - } -#if CONFIG_HIGHBITDEPTH - if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { - uint64_t sse = aom_highbd_sse_odd_size(src, src_stride, dst, dst_stride, - visible_cols, visible_rows); - return (unsigned int)ROUND_POWER_OF_TWO(sse, (xd->bd - 8) * 2); - } -#endif // CONFIG_HIGHBITDEPTH - unsigned sse = aom_sse_odd_size(src, src_stride, dst, dst_stride, - visible_cols, visible_rows); + unsigned sse = pixel_dist_visible_only(cpi, x, src, src_stride, dst, + dst_stride, tx_bsize, txb_rows, + txb_cols, visible_rows, visible_cols); + return sse; } @@ -2156,8 +2170,10 @@ const uint8_t *src = &p->src.buf[0]; const uint8_t *dst = &pd->dst.buf[0]; const int16_t *pred = &pd->pred[0]; - const int bw = block_size_wide[bsize]; - const int bh = block_size_high[bsize]; + int bw = block_size_wide[bsize]; + int bh = block_size_high[bsize]; + int visible_w = bw; + int visible_h = bh; int i, j; int64_t rd, rd1, rd2; @@ -2167,6 +2183,9 @@ assert((bw & 0x07) == 0); assert((bh & 0x07) == 0); + get_txb_dimensions(xd, 0, bsize, 0, 0, bsize, &bw, &bh, &visible_w, + &visible_h); + #if CONFIG_HIGHBITDEPTH uint8_t *pred8; DECLARE_ALIGNED(16, uint16_t, pred16[MAX_TX_SQUARE]); @@ -2193,16 +2212,24 @@ #endif // CONFIG_HIGHBITDEPTH tmp1 = (unsigned)av1_dist_8x8(cpi, x, src, src_stride, pred8, bw, bsize, bw, - bh, bw, bh, qindex); + bh, visible_w, visible_h, qindex); tmp2 = (unsigned)av1_dist_8x8(cpi, x, src, src_stride, dst, dst_stride, bsize, - bw, bh, bw, bh, qindex); + bw, bh, visible_w, visible_h, qindex); if (!is_inter_block(mbmi)) { + if (x->tune_metric == AOM_TUNE_PSNR) { + assert(args->rd_stats.sse == tmp1 * 16); + assert(args->rd_stats.dist == tmp2 * 16); + } args->rd_stats.sse = (int64_t)tmp1 * 16; args->rd_stats.dist = (int64_t)tmp2 * 16; } else { // For inter mode, the decoded pixels are provided in pd->pred, // while the predicted pixels are in dst. + if (x->tune_metric == AOM_TUNE_PSNR) { + assert(args->rd_stats.sse == tmp2 * 16); + assert(args->rd_stats.dist == tmp1 * 16); + } args->rd_stats.sse = (int64_t)tmp2 * 16; args->rd_stats.dist = (int64_t)tmp1 * 16; }