summaryrefslogtreecommitdiff
path: root/vp9/encoder
diff options
context:
space:
mode:
Diffstat (limited to 'vp9/encoder')
-rw-r--r--vp9/encoder/vp9_denoiser.c49
-rw-r--r--vp9/encoder/vp9_denoiser.h2
-rw-r--r--vp9/encoder/vp9_encodeframe.c47
-rw-r--r--vp9/encoder/vp9_pickmode.c4
-rw-r--r--vp9/encoder/vp9_speed_features.c2
5 files changed, 79 insertions, 25 deletions
diff --git a/vp9/encoder/vp9_denoiser.c b/vp9/encoder/vp9_denoiser.c
index 9bc9f26c1..9eca2a229 100644
--- a/vp9/encoder/vp9_denoiser.c
+++ b/vp9/encoder/vp9_denoiser.c
@@ -316,13 +316,14 @@ static VP9_DENOISER_DECISION perform_motion_compensation(VP9_DENOISER *denoiser,
return FILTER_BLOCK;
}
-void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
+void vp9_denoiser_denoise(VP9_COMP *cpi, MACROBLOCK *mb,
int mi_row, int mi_col, BLOCK_SIZE bs,
PICK_MODE_CONTEXT *ctx,
VP9_DENOISER_DECISION *denoiser_decision) {
int mv_col, mv_row;
int motion_magnitude = 0;
int zeromv_filter = 0;
+ VP9_DENOISER *denoiser = &cpi->denoiser;
VP9_DENOISER_DECISION decision = COPY_BLOCK;
YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME];
YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y;
@@ -331,21 +332,53 @@ void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
mi_row, mi_col);
struct buf_2d src = mb->plane[0].src;
int is_skin = 0;
+ mv_col = ctx->best_sse_mv.as_mv.col;
+ mv_row = ctx->best_sse_mv.as_mv.row;
+ motion_magnitude = mv_row * mv_row + mv_col * mv_col;
- if (bs <= BLOCK_32X32 && denoiser->denoising_level >= kDenLow) {
+ if (cpi->use_skin_detection &&
+ bs <= BLOCK_32X32 &&
+ denoiser->denoising_level >= kDenLow) {
+ int motion_level = (motion_magnitude < 16) ? 0 : 1;
+ // If motion for current block is small/zero, compute consec_zeromv for
+ // skin detection (early exit in skin detection is done for large
+ // consec_zeromv when current block has small/zero motion).
+ int consec_zeromv = 0;
+ if (motion_level == 0) {
+ CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
+ VP9_COMMON * const cm = &cpi->common;
+ int j, i;
+ // Loop through the 8x8 sub-blocks.
+ const int bw = num_8x8_blocks_wide_lookup[BLOCK_64X64];
+ const int bh = num_8x8_blocks_high_lookup[BLOCK_64X64];
+ 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;
+ consec_zeromv = 100;
+ for (i = 0; i < ymis; i++) {
+ for (j = 0; j < xmis; j++) {
+ int bl_index = block_index + i * cm->mi_cols + j;
+ consec_zeromv = VPXMIN(cr->consec_zero_mv[bl_index], consec_zeromv);
+ // No need to keep checking 8x8 blocks if any of the sub-blocks
+ // has small consec_zeromv (since threshold for no_skin based on
+ // zero/small motion in skin detection is high, i.e, > 5).
+ if (consec_zeromv < 5) {
+ i = ymis;
+ j = xmis;
+ }
+ }
+ }
+ }
+ // TODO(marpan): Compute skin detection over sub-blocks.
is_skin = vp9_compute_skin_block(mb->plane[0].src.buf,
mb->plane[1].src.buf,
mb->plane[2].src.buf,
mb->plane[0].src.stride,
mb->plane[1].src.stride,
bs,
- 0,
- 0);
+ consec_zeromv,
+ motion_level);
}
-
- mv_col = ctx->best_sse_mv.as_mv.col;
- mv_row = ctx->best_sse_mv.as_mv.row;
- motion_magnitude = mv_row * mv_row + mv_col * mv_col;
if (!is_skin &&
denoiser->denoising_level == kDenHigh &&
motion_magnitude < 16) {
diff --git a/vp9/encoder/vp9_denoiser.h b/vp9/encoder/vp9_denoiser.h
index 9f13bd533..a0e201781 100644
--- a/vp9/encoder/vp9_denoiser.h
+++ b/vp9/encoder/vp9_denoiser.h
@@ -53,7 +53,7 @@ void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser,
int refresh_last_frame,
int resized);
-void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
+void vp9_denoiser_denoise(struct VP9_COMP *cpi, MACROBLOCK *mb,
int mi_row, int mi_col, BLOCK_SIZE bs,
PICK_MODE_CONTEXT *ctx ,
VP9_DENOISER_DECISION *denoiser_decision);
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 84593836c..40b332ac8 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -772,36 +772,55 @@ static int choose_partitioning(VP9_COMP *cpi,
vp9_build_inter_predictors_sb(xd, mi_row, mi_col, BLOCK_64X64);
// Check if most of the superblock is skin content, and if so, force split
- // to 32x32. Avoid checking superblocks on/near boundary and avoid low
- // resolutons for now.
+ // to 32x32, and set x->sb_is_skin for use in mode selection.
+ // Avoid checking superblocks on/near boundary and avoid low resolutions.
// Note superblock may still pick 64X64 if y_sad is very small
// (i.e., y_sad < cpi->vbp_threshold_sad) below. For now leave this as is.
x->sb_is_skin = 0;
#if !CONFIG_VP9_HIGHBITDEPTH
if (cpi->use_skin_detection && !low_res && (mi_col >= 8 &&
mi_col + 8 < cm->mi_cols && mi_row >= 8 && mi_row + 8 < cm->mi_rows)) {
+ CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
+ int bl_index1, bl_index2, bl_index3;
int num_16x16_skin = 0;
int num_16x16_nonskin = 0;
+ int is_skin = 0;
+ int consec_zeromv = 0;
uint8_t *ysignal = x->plane[0].src.buf;
uint8_t *usignal = x->plane[1].src.buf;
uint8_t *vsignal = x->plane[2].src.buf;
int spuv = x->plane[1].src.stride;
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- int is_skin = vp9_compute_skin_block(ysignal,
- usignal,
- vsignal,
- sp,
- spuv,
- BLOCK_16X16,
- 0,
- 0);
+ const int block_index = mi_row * cm->mi_cols + mi_col;
+ const int bw = num_8x8_blocks_wide_lookup[BLOCK_64X64];
+ const int bh = num_8x8_blocks_high_lookup[BLOCK_64X64];
+ const int xmis = VPXMIN(cm->mi_cols - mi_col, bw);
+ const int ymis = VPXMIN(cm->mi_rows - mi_row, bh);
+ // Loop through the 16x16 sub-blocks.
+ int j, i;
+ for (i = 0; i < ymis; i+=2) {
+ for (j = 0; j < xmis; j+=2) {
+ int bl_index = block_index + i * cm->mi_cols + j;
+ bl_index1 = bl_index + 1;
+ bl_index2 = bl_index + cm->mi_cols;
+ bl_index3 = bl_index2 + 1;
+ consec_zeromv = VPXMIN(cr->consec_zero_mv[bl_index],
+ VPXMIN(cr->consec_zero_mv[bl_index1],
+ VPXMIN(cr->consec_zero_mv[bl_index2],
+ cr->consec_zero_mv[bl_index3])));
+ is_skin = vp9_compute_skin_block(ysignal,
+ usignal,
+ vsignal,
+ sp,
+ spuv,
+ BLOCK_16X16,
+ consec_zeromv,
+ 0);
num_16x16_skin += is_skin;
num_16x16_nonskin += (1 - is_skin);
if (num_16x16_nonskin > 3) {
// Exit loop if at least 4 of the 16x16 blocks are not skin.
- i = 4;
- j = 4;
+ i = ymis;
+ j = xmis;
}
ysignal += 16;
usignal += 8;
diff --git a/vp9/encoder/vp9_pickmode.c b/vp9/encoder/vp9_pickmode.c
index 3ea2ccd88..8b2e98549 100644
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -1825,8 +1825,8 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
if (cpi->oxcf.noise_sensitivity > 0 &&
cpi->resize_pending == 0) {
VP9_DENOISER_DECISION decision = COPY_BLOCK;
- vp9_denoiser_denoise(&cpi->denoiser, x, mi_row, mi_col,
- VPXMAX(BLOCK_8X8, bsize), ctx, &decision);
+ vp9_denoiser_denoise(cpi, x, mi_row, mi_col, VPXMAX(BLOCK_8X8, bsize),
+ ctx, &decision);
// If INTRA or GOLDEN reference was selected, re-evaluate ZEROMV on denoised
// result. Only do this under noise conditions, and if rdcost of ZEROMV on
// original source is not significantly higher than rdcost of best mode.
diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c
index c014ca174..02be3c3f9 100644
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -400,6 +400,8 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH;
sf->tx_size_search_method = is_keyframe ? USE_LARGESTALL : USE_TX_8X8;
sf->simple_model_rd_from_var = 1;
+ if (cpi->oxcf.rc_mode == VPX_VBR)
+ sf->mv.search_method = NSTEP;
if (!is_keyframe) {
int i;