ref: 0c6d3a03e196e50410d8e2f06b3a4adb553d17d7
parent: 3a5d40608ef5603764f45ec33448f5c013b875b4
author: Jingning Han <[email protected]>
date: Wed Jan 21 04:32:23 EST 2015
Account for chroma component costs in RTC mode decision This commit allows the encoder to account for additional chroma plane costs in the mode decision process, if the current block potentially contains significant color change. It improves the visual quality at very low bit-rates. The compression performance of dark720p is improved by 12.39% in speed 6. For jimred at 150 kbps, the PSNR of V component (red) increased by 0.2 dB, at the expense of about 5% increase in encoding time. Note that for sequences where the chroma components are fairly consistent, the encoding time increase is negligible. On average the rtc set compression performance is improved by 1.172% in PSNR and 1.920% in SSIM. Change-Id: Ia55b24ef23a25304f7ec9958fbf07fd6e658505c
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -264,11 +264,18 @@
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,
--- a/vp9/common/vp9_reconinter.h
+++ b/vp9/common/vp9_reconinter.h
@@ -52,6 +52,9 @@
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);
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -118,6 +118,10 @@
// 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
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -529,6 +529,7 @@
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;
@@ -535,7 +536,18 @@
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;
} else {
@@ -3382,6 +3394,8 @@
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) {
@@ -3677,7 +3691,6 @@
cpi->sf.partition_search_type == VAR_BASED_PARTITION) {
cm->tx_mode = ALLOW_16X16;
}
-
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth)
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -283,6 +283,71 @@
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 @@
// 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);
@@ -774,6 +842,20 @@
vp9_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
model_rd_for_sb_y(cpi, bsize, x, xd, &this_rdc.rate, &this_rdc.dist,
&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;