diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c index ed3ea7e1f..1be358e87 100644 --- a/vp9/common/vp9_reconinter.c +++ b/vp9/common/vp9_reconinter.c @@ -264,11 +264,18 @@ void vp9_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col, BLOCK_SIZE bsize) { build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0); } + +void vp9_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col, + BLOCK_SIZE bsize, int plane) { + build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, plane, plane); +} + void vp9_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col, BLOCK_SIZE bsize) { build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1, MAX_MB_PLANE - 1); } + void vp9_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col, BLOCK_SIZE bsize) { build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, diff --git a/vp9/common/vp9_reconinter.h b/vp9/common/vp9_reconinter.h index d5ecf85b4..e7057445a 100644 --- a/vp9/common/vp9_reconinter.h +++ b/vp9/common/vp9_reconinter.h @@ -52,6 +52,9 @@ void build_inter_predictors(MACROBLOCKD *xd, int plane, int block, void vp9_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col, BLOCK_SIZE bsize); +void vp9_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col, + BLOCK_SIZE bsize, int plane); + void vp9_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col, BLOCK_SIZE bsize); diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h index 68174a6cc..04a1b8f3c 100644 --- a/vp9/encoder/vp9_block.h +++ b/vp9/encoder/vp9_block.h @@ -118,6 +118,10 @@ struct macroblock { // Used to store sub partition's choices. MV pred_mv[MAX_REF_FRAMES]; + // Strong color activity detection. Used in RTC coding mode to enhance + // the visual quality at the boundary of moving color objects. + uint8_t color_sensitivity[2]; + void (*fwd_txm4x4)(const int16_t *input, tran_low_t *output, int stride); void (*itxm_add)(const tran_low_t *input, uint8_t *dest, int stride, int eob); #if CONFIG_VP9_HIGHBITDEPTH diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 091013060..a8e7f5ea6 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -529,12 +529,24 @@ static void choose_partitioning(VP9_COMP *cpi, if (cm->frame_type != KEY_FRAME) { MB_MODE_INFO *mbmi = &xd->mi[0].src_mi->mbmi; + unsigned int var = 0, sse; vp9_setup_pre_planes(xd, 0, yv12, mi_row, mi_col, sf); mbmi->ref_frame[0] = LAST_FRAME; mbmi->ref_frame[1] = NONE; mbmi->sb_type = BLOCK_64X64; mbmi->mv[0].as_int = 0; vp9_build_inter_predictors_sby(xd, mi_row, mi_col, BLOCK_64X64); + vp9_build_inter_predictors_sbuv(xd, mi_row, mi_col, BLOCK_64X64); + + for (i = 1; i <= 2; ++i) { + struct macroblock_plane *p = &x->plane[i]; + struct macroblockd_plane *pd = &xd->plane[i]; + const BLOCK_SIZE bs = get_plane_block_size(BLOCK_64X64, pd); + var += cpi->fn_ptr[bs].vf(p->src.buf, p->src.stride, + pd->dst.buf, pd->dst.stride, &sse); + if (sse > 2048) + x->color_sensitivity[i - 1] = 1; + } d = xd->plane[0].dst.buf; dp = xd->plane[0].dst.stride; @@ -3382,6 +3394,8 @@ static void encode_nonrd_sb_row(VP9_COMP *cpi, x->source_variance = UINT_MAX; vp9_zero(x->pred_mv); vp9_rd_cost_init(&dummy_rdc); + x->color_sensitivity[0] = 0; + x->color_sensitivity[1] = 0; // Set the partition type of the 64X64 block switch (sf->partition_search_type) { @@ -3678,7 +3692,6 @@ static void encode_frame_internal(VP9_COMP *cpi) { cm->tx_mode = ALLOW_16X16; } - #if CONFIG_VP9_HIGHBITDEPTH if (cm->use_highbitdepth) x->fwd_txm4x4 = xd->lossless ? vp9_highbd_fwht4x4 : vp9_highbd_fdct4x4; diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c index e239c008f..b751bf6de 100644 --- a/vp9/encoder/vp9_pickmode.c +++ b/vp9/encoder/vp9_pickmode.c @@ -283,6 +283,71 @@ static void model_rd_for_sb_y(VP9_COMP *cpi, BLOCK_SIZE bsize, x->skip_txfm[0] = 1; } +static void model_rd_for_sb_uv(VP9_COMP *cpi, BLOCK_SIZE bsize, + MACROBLOCK *x, MACROBLOCKD *xd, + int *out_rate_sum, int64_t *out_dist_sum, + unsigned int *var_y, unsigned int *sse_y) { + // Note our transform coeffs are 8 times an orthogonal transform. + // Hence quantizer step is also 8 times. To get effective quantizer + // we need to divide by 8 before sending to modeling function. + unsigned int sse; + int rate; + int64_t dist; + int i; + + *out_rate_sum = 0; + *out_dist_sum = 0; + + for (i = 1; i <= 2; ++i) { + struct macroblock_plane *const p = &x->plane[i]; + struct macroblockd_plane *const pd = &xd->plane[i]; + const uint32_t dc_quant = pd->dequant[0]; + const uint32_t ac_quant = pd->dequant[1]; + const BLOCK_SIZE bs = get_plane_block_size(bsize, pd); + unsigned int var; + + if (!x->color_sensitivity[i - 1]) + continue; + + var = cpi->fn_ptr[bs].vf(p->src.buf, p->src.stride, + pd->dst.buf, pd->dst.stride, &sse); + *var_y += var; + *sse_y += sse; + + #if CONFIG_VP9_HIGHBITDEPTH + if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { + vp9_model_rd_from_var_lapndz(sse - var, num_pels_log2_lookup[bs], + dc_quant >> (xd->bd - 5), &rate, &dist); + } else { + vp9_model_rd_from_var_lapndz(sse - var, num_pels_log2_lookup[bs], + dc_quant >> 3, &rate, &dist); + } + #else + vp9_model_rd_from_var_lapndz(sse - var, num_pels_log2_lookup[bs], + dc_quant >> 3, &rate, &dist); + #endif // CONFIG_VP9_HIGHBITDEPTH + + *out_rate_sum += rate >> 1; + *out_dist_sum += dist << 3; + + #if CONFIG_VP9_HIGHBITDEPTH + if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { + vp9_model_rd_from_var_lapndz(var, num_pels_log2_lookup[bs], + ac_quant >> (xd->bd - 5), &rate, &dist); + } else { + vp9_model_rd_from_var_lapndz(var, num_pels_log2_lookup[bs], + ac_quant >> 3, &rate, &dist); + } + #else + vp9_model_rd_from_var_lapndz(var, num_pels_log2_lookup[bs], + ac_quant >> 3, &rate, &dist); + #endif // CONFIG_VP9_HIGHBITDEPTH + + *out_rate_sum += rate; + *out_dist_sum += dist << 4; + } +} + static int get_pred_buffer(PRED_BUFFER *p, int len) { int i; @@ -660,6 +725,9 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, // Select prediction reference frames. xd->plane[0].pre[0] = yv12_mb[ref_frame][0]; + vp9_setup_pre_planes(xd, 0, get_ref_frame_buffer(cpi, ref_frame), + mi_row, mi_col, &cm->frame_refs[ref_frame - 1].sf); + clamp_mv2(&frame_mv[NEARESTMV][ref_frame].as_mv, xd); clamp_mv2(&frame_mv[NEARMV][ref_frame].as_mv, xd); @@ -776,6 +844,20 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, &var_y, &sse_y); } + // chroma component rate-distortion cost modeling + if (x->color_sensitivity[0] || x->color_sensitivity[1]) { + int uv_rate = 0; + int64_t uv_dist = 0; + if (x->color_sensitivity[0]) + vp9_build_inter_predictors_sbp(xd, mi_row, mi_col, bsize, 1); + if (x->color_sensitivity[1]) + vp9_build_inter_predictors_sbp(xd, mi_row, mi_col, bsize, 2); + model_rd_for_sb_uv(cpi, bsize, x, xd, &uv_rate, &uv_dist, + &var_y, &sse_y); + this_rdc.rate += uv_rate; + this_rdc.dist += uv_dist; + } + this_rdc.rate += rate_mv; this_rdc.rate += cpi->inter_mode_cost[mbmi->mode_context[ref_frame]] [INTER_OFFSET(this_mode)];