aq-mode=3: Don't reset segment if block is determined to be skin. For coding block sizes <=16X16, if the block is determined to be skin, then always allow for that block to be candidate for refresh. So if that block happens to be on the boost segment(s), segment won't get reset to 0 and delta-q will be applied. PSNR/SSIM metrics neutral (little/no change) on RTC clips. Speed increase small/negligible (< 1%). Some visual improvement on faces in a few RTC clips. Change-Id: I6bf0fce6f39d820b491ce05d7c017ad168fce7d6
diff --git a/vp9/encoder/vp9_aq_cyclicrefresh.c b/vp9/encoder/vp9_aq_cyclicrefresh.c index 0def2cf..7c71d9d 100644 --- a/vp9/encoder/vp9_aq_cyclicrefresh.c +++ b/vp9/encoder/vp9_aq_cyclicrefresh.c
@@ -191,7 +191,8 @@ BLOCK_SIZE bsize, int64_t rate, int64_t dist, - int skip) { + int skip, + struct macroblock_plane *const p) { const VP9_COMMON *const cm = &cpi->common; CYCLIC_REFRESH *const cr = cpi->cyclic_refresh; const int bw = num_8x8_blocks_wide_lookup[bsize]; @@ -199,12 +200,33 @@ const int xmis = VPXMIN(cm->mi_cols - mi_col, bw); const int ymis = VPXMIN(cm->mi_rows - mi_row, bh); const int block_index = mi_row * cm->mi_cols + mi_col; - const int refresh_this_block = candidate_refresh_aq(cr, mbmi, rate, dist, - bsize); + int refresh_this_block = candidate_refresh_aq(cr, mbmi, rate, dist, bsize); // Default is to not update the refresh map. int new_map_value = cr->map[block_index]; int x = 0; int y = 0; + int is_skin = 0; + if (refresh_this_block == 0 && + bsize <= BLOCK_16X16 && + cpi->oxcf.content != VP9E_CONTENT_SCREEN) { + // Take center pixel in block to determine is_skin. + const int y_width_shift = (4 << b_width_log2_lookup[bsize]) >> 1; + const int y_height_shift = (4 << b_height_log2_lookup[bsize]) >> 1; + const int uv_width_shift = y_width_shift >> 1; + const int uv_height_shift = y_height_shift >> 1; + const int stride = p[0].src.stride; + const int strideuv = p[1].src.stride; + const uint8_t ysource = + p[0].src.buf[y_height_shift * stride + y_width_shift]; + const uint8_t usource = + p[1].src.buf[uv_height_shift * strideuv + uv_width_shift]; + const uint8_t vsource = + p[2].src.buf[uv_height_shift * strideuv + uv_width_shift]; + is_skin = vp9_skin_pixel(ysource, usource, vsource); + if (is_skin) + refresh_this_block = 1; + } + // If this block is labeled for refresh, check if we should reset the // segment_id. if (cyclic_refresh_segment_id_boosted(mbmi->segment_id)) {
diff --git a/vp9/encoder/vp9_aq_cyclicrefresh.h b/vp9/encoder/vp9_aq_cyclicrefresh.h index a5b3813..edf0a97 100644 --- a/vp9/encoder/vp9_aq_cyclicrefresh.h +++ b/vp9/encoder/vp9_aq_cyclicrefresh.h
@@ -14,6 +14,8 @@ #include "vpx/vpx_integer.h" #include "vp9/common/vp9_blockd.h" +#include "vp9/encoder/vp9_block.h" +#include "vp9/encoder/vp9_skin_detection.h" #ifdef __cplusplus extern "C" { @@ -93,7 +95,8 @@ void vp9_cyclic_refresh_update_segment(struct VP9_COMP *const cpi, MB_MODE_INFO *const mbmi, int mi_row, int mi_col, BLOCK_SIZE bsize, - int64_t rate, int64_t dist, int skip); + int64_t rate, int64_t dist, int skip, + struct macroblock_plane *const p); void vp9_cyclic_refresh_update_sb_postencode(struct VP9_COMP *const cpi, const MB_MODE_INFO *const mbmi,
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index cc4d1f1..c07eee9 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c
@@ -1045,7 +1045,7 @@ if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) { vp9_cyclic_refresh_update_segment(cpi, &xd->mi[0]->mbmi, mi_row, mi_col, bsize, ctx->rate, ctx->dist, - x->skip); + x->skip, p); } } @@ -1705,6 +1705,7 @@ MACROBLOCKD *const xd = &x->e_mbd; MODE_INFO *const mi = xd->mi[0]; MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi; + struct macroblock_plane *const p = x->plane; const struct segmentation *const seg = &cm->seg; const int bw = num_8x8_blocks_wide_lookup[mi->mbmi.sb_type]; const int bh = num_8x8_blocks_high_lookup[mi->mbmi.sb_type]; @@ -1725,7 +1726,7 @@ } else { // Setting segmentation map for cyclic_refresh. vp9_cyclic_refresh_update_segment(cpi, mbmi, mi_row, mi_col, bsize, - ctx->rate, ctx->dist, x->skip); + ctx->rate, ctx->dist, x->skip, p); } vp9_init_plane_quantizers(cpi, x); }