From b121a3e7b8be493c1fa91a740300e1880339fb93 Mon Sep 17 00:00:00 2001 From: Marco Date: Mon, 21 Dec 2015 10:35:05 -0800 Subject: 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 --- vp9/encoder/vp9_aq_cyclicrefresh.c | 28 +++++++++++++++++++++++++--- vp9/encoder/vp9_aq_cyclicrefresh.h | 5 ++++- vp9/encoder/vp9_encodeframe.c | 5 +++-- 3 files changed, 32 insertions(+), 6 deletions(-) (limited to 'vp9/encoder') diff --git a/vp9/encoder/vp9_aq_cyclicrefresh.c b/vp9/encoder/vp9_aq_cyclicrefresh.c index 0def2cf1f..7c71d9d57 100644 --- a/vp9/encoder/vp9_aq_cyclicrefresh.c +++ b/vp9/encoder/vp9_aq_cyclicrefresh.c @@ -191,7 +191,8 @@ void vp9_cyclic_refresh_update_segment(VP9_COMP *const cpi, 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 @@ void vp9_cyclic_refresh_update_segment(VP9_COMP *const cpi, 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 a5b38138b..edf0a973e 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 @@ int vp9_cyclic_refresh_rc_bits_per_mb(const struct VP9_COMP *cpi, int i, 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 cc4d1f14e..c07eee969 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -1045,7 +1045,7 @@ static void update_state(VP9_COMP *cpi, ThreadData *td, 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 @@ static void update_state_rt(VP9_COMP *cpi, ThreadData *td, 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 @@ static void update_state_rt(VP9_COMP *cpi, ThreadData *td, } 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); } -- cgit v1.2.3