summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPengchong Jin <pengchong@google.com>2014-07-29 19:49:47 -0700
committerPengchong Jin <pengchong@google.com>2014-07-30 11:54:49 -0700
commit49866baae60f863d36ca42f40ff4fddd987461cc (patch)
tree34b1d8a1d133ee40f40146748d32a74acd144c06
parent838b53b9fb639917e1566dc1b5d3714d70556e7e (diff)
downloadlibvpx-49866baae60f863d36ca42f40ff4fddd987461cc.tar
libvpx-49866baae60f863d36ca42f40ff4fddd987461cc.tar.gz
libvpx-49866baae60f863d36ca42f40ff4fddd987461cc.tar.bz2
libvpx-49866baae60f863d36ca42f40ff4fddd987461cc.zip
Early termination after partition NONE is done in RD.
This patch allows the encoder to skip the search for partition SPLIT, HORZ, VERT after the search for partition NONE is done in RD optimization. It uses the first pass block-wise statistics to make the decision. If all 16x16 blocks in the current partition have zero motions and small residues from the frist pass statistics, and it has small difference variance, further partition search is skipped. For speed 2 setting, experiments on general youtube clips show that the speedup varies from 1% - 10%, 5% on average. On the performance side in PSNR, derf 0.004%, yt -0.059%, hd -0.106%, stdhd 0.032%. For hard stdhd clips: park_joy_1080p, 502952 ms -> 503307 ms (-0.07%) pedestrian_area_1080p, 227049 ms -> 220531 ms (+3%) This feature is under the compilation flag CONFIG_FP_MB_STATS and it is off in current setting. Change-Id: I554537e9242178263b65ebe14a04f9c221b58bae
-rw-r--r--vp9/encoder/vp9_encodeframe.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 584bcb8f5..6f21e9cd4 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -1888,6 +1888,15 @@ static INLINE void load_pred_mv(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
vpx_memcpy(x->pred_mv, ctx->pred_mv, sizeof(x->pred_mv));
}
+#if CONFIG_FP_MB_STATS
+const int num_16x16_blocks_wide_lookup[BLOCK_SIZES] =
+ {1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 4, 4};
+const int num_16x16_blocks_high_lookup[BLOCK_SIZES] =
+ {1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 4, 2, 4};
+const int qindex_skip_threshold_lookup[BLOCK_SIZES] =
+ {0, 10, 10, 30, 40, 40, 60, 80, 80, 90, 100, 100, 120};
+#endif
+
// TODO(jingning,jimbankoski,rbultje): properly skip partition types that are
// unlikely to be selected depending on previous rate-distortion optimization
// results, for encoding speed-up.
@@ -1993,6 +2002,52 @@ static void rd_pick_partition(VP9_COMP *cpi, const TileInfo *const tile,
do_split = 0;
do_rect = 0;
}
+
+#if CONFIG_FP_MB_STATS
+ // Check if every 16x16 first pass block statistics has zero
+ // motion and the corresponding first pass residue is small enough.
+ // If that is the case, check the difference variance between the
+ // current frame and the last frame. If the variance is small enough,
+ // stop further splitting in RD optimization
+ if (cpi->use_fp_mb_stats && do_split != 0 &&
+ cm->base_qindex > qindex_skip_threshold_lookup[bsize]) {
+ VP9_COMMON *cm = &cpi->common;
+ int mb_row = mi_row >> 1;
+ int mb_col = mi_col >> 1;
+ int mb_row_end =
+ MIN(mb_row + num_16x16_blocks_high_lookup[bsize], cm->mb_rows);
+ int mb_col_end =
+ MIN(mb_col + num_16x16_blocks_wide_lookup[bsize], cm->mb_cols);
+ int r, c;
+
+ int skip = 1;
+ for (r = mb_row; r < mb_row_end; r++) {
+ for (c = mb_col; c < mb_col_end; c++) {
+ const int mb_index = r * cm->mb_cols + c;
+ if ((cpi->twopass.this_frame_mb_stats[mb_index] &
+ FPMB_NONZERO_MOTION_MASK) ||
+ !(cpi->twopass.this_frame_mb_stats[mb_index] &
+ FPMB_ERROR_LEVEL0_MASK)) {
+ skip = 0;
+ break;
+ }
+ }
+ if (skip == 0) {
+ break;
+ }
+ }
+ if (skip) {
+ unsigned int var;
+ set_offsets(cpi, tile, mi_row, mi_col, bsize);
+ var = get_sby_perpixel_diff_variance(cpi, &cpi->mb.plane[0].src,
+ mi_row, mi_col, bsize);
+ if (var < 8) {
+ do_split = 0;
+ do_rect = 0;
+ }
+ }
+ }
+#endif
}
}
restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);