From 83cef816fdb16d64be160d5b740a1b242fe3481e Mon Sep 17 00:00:00 2001 From: John Koleszar Date: Wed, 25 Jan 2012 14:55:49 -0800 Subject: [PATCH] Correct clamping in use of vp8_find_near_mvs() Commit e06c242ba introduced a change to call vp8_find_near_mvs() only once instead of once per reference frame by observing that the only effect that the frame had was on the bias applied to the motion vector. By keeping track of the sign_bias value, the mv to use could be flip-flopped by multiplying its components by -1. This behavior was subtley wrong in the case when clamping was applied to the motion vectors found by vp8_find_near_mvs(). A motion vector could be in-bounds with one sign bias, but out of bounds after inverting the sign, or vice versa. The clamping must match that done by the decoder. This change modifies vp8_find_near_mvs() to remove the clamping from that function. The vp8_pick_inter_mode() and vp8_rd_pick_inter_mode() functions instead track the correctly clamped values for both bias values, switching between them by simple assignment. The common clamping and inversion code is in vp8_find_near_mvs_bias() Change-Id: I17e1a348d1643497eca0be232e2fbe2acf8478e1 --- vp8/common/findnearmv.c | 48 ++++++++++++++++++++++++++++++++++++----- vp8/common/findnearmv.h | 13 +++++++++++ vp8/encoder/bitstream.c | 2 ++ vp8/encoder/pickinter.c | 44 +++++++++++++++++-------------------- vp8/encoder/rdopt.c | 44 +++++++++++++++++-------------------- 5 files changed, 98 insertions(+), 53 deletions(-) diff --git a/vp8/common/findnearmv.c b/vp8/common/findnearmv.c index c1022363e..e8ee40f56 100644 --- a/vp8/common/findnearmv.c +++ b/vp8/common/findnearmv.c @@ -134,13 +134,51 @@ void vp8_find_near_mvs best_mv->as_int = near_mvs[0].as_int; nearest->as_int = near_mvs[CNT_NEAREST].as_int; nearby->as_int = near_mvs[CNT_NEAR].as_int; - - //TODO: move clamp outside findnearmv - vp8_clamp_mv2(nearest, xd); - vp8_clamp_mv2(nearby, xd); - vp8_clamp_mv2(best_mv, xd); } + +static void invert_and_clamp_mvs(int_mv *inv, int_mv *src, MACROBLOCKD *xd) +{ + inv->as_mv.row = src->as_mv.row * -1; + inv->as_mv.col = src->as_mv.col * -1; + vp8_clamp_mv2(inv, xd); + vp8_clamp_mv2(src, xd); +} + + +int vp8_find_near_mvs_bias +( + MACROBLOCKD *xd, + const MODE_INFO *here, + int_mv mode_mv_sb[2][MB_MODE_COUNT], + int_mv best_mv_sb[2], + int cnt[4], + int refframe, + int *ref_frame_sign_bias +) +{ + int sign_bias = ref_frame_sign_bias[refframe]; + + vp8_find_near_mvs(xd, + here, + &mode_mv_sb[sign_bias][NEARESTMV], + &mode_mv_sb[sign_bias][NEARMV], + &best_mv_sb[sign_bias], + cnt, + refframe, + ref_frame_sign_bias); + + invert_and_clamp_mvs(&mode_mv_sb[!sign_bias][NEARESTMV], + &mode_mv_sb[sign_bias][NEARESTMV], xd); + invert_and_clamp_mvs(&mode_mv_sb[!sign_bias][NEARMV], + &mode_mv_sb[sign_bias][NEARMV], xd); + invert_and_clamp_mvs(&best_mv_sb[!sign_bias], + &best_mv_sb[sign_bias], xd); + + return sign_bias; +} + + vp8_prob *vp8_mv_ref_probs( vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4] ) diff --git a/vp8/common/findnearmv.h b/vp8/common/findnearmv.h index a3443d765..06ef060c2 100644 --- a/vp8/common/findnearmv.h +++ b/vp8/common/findnearmv.h @@ -77,6 +77,19 @@ void vp8_find_near_mvs int *ref_frame_sign_bias ); + +int vp8_find_near_mvs_bias +( + MACROBLOCKD *xd, + const MODE_INFO *here, + int_mv mode_mv_sb[2][MB_MODE_COUNT], + int_mv best_mv_sb[2], + int cnt[4], + int refframe, + int *ref_frame_sign_bias +); + + vp8_prob *vp8_mv_ref_probs( vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4] ); diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index 669bfad9a..0bb51730e 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -1013,6 +1013,8 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) int ct[4]; vp8_find_near_mvs(xd, m, &n1, &n2, &best_mv, ct, rf, cpi->common.ref_frame_sign_bias); + vp8_clamp_mv2(&best_mv, xd); + vp8_mv_ref_probs(mv_ref_p, ct); #ifdef ENTROPY_STATS diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c index 405c72dbd..3612cc3a8 100644 --- a/vp8/encoder/pickinter.c +++ b/vp8/encoder/pickinter.c @@ -469,8 +469,10 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, MACROBLOCKD *xd = &x->e_mbd; MB_MODE_INFO best_mbmode; + int_mv best_ref_mv_sb[2]; + int_mv mode_mv_sb[2][MB_MODE_COUNT]; int_mv best_ref_mv; - int_mv mode_mv[MB_MODE_COUNT]; + int_mv *mode_mv; MB_PREDICTION_MODE this_mode; int num00; int mdcounts[4]; @@ -508,7 +510,9 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, &parent_mode, &parent_ref_mv, mb_row, mb_col); #endif - vpx_memset(mode_mv, 0, sizeof(mode_mv)); + mode_mv = mode_mv_sb[sign_bias]; + best_ref_mv.as_int = 0; + vpx_memset(mode_mv_sb, 0, sizeof(mode_mv_sb)); vpx_memset(&best_mbmode, 0, sizeof(best_mbmode)); /* Setup search priorities */ @@ -519,15 +523,16 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, */ if (ref_frame_map[1] > 0) { - vp8_find_near_mvs(&x->e_mbd, - x->e_mbd.mode_info_context, - &mode_mv[NEARESTMV], &mode_mv[NEARMV], - &best_ref_mv, - mdcounts, - ref_frame_map[1], - cpi->common.ref_frame_sign_bias); + sign_bias = vp8_find_near_mvs_bias(&x->e_mbd, + x->e_mbd.mode_info_context, + mode_mv_sb, + best_ref_mv_sb, + mdcounts, + ref_frame_map[1], + cpi->common.ref_frame_sign_bias); - sign_bias = cpi->common.ref_frame_sign_bias[ref_frame_map[1]]; + mode_mv = mode_mv_sb[sign_bias]; + best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int; } get_predictor_pointers(cpi, plane, recon_yoffset, recon_uvoffset); @@ -578,17 +583,11 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, x->e_mbd.pre.u_buffer = plane[this_ref_frame][1]; x->e_mbd.pre.v_buffer = plane[this_ref_frame][2]; - if (sign_bias != - cpi->common.ref_frame_sign_bias[x->e_mbd.mode_info_context->mbmi.ref_frame]) + if (sign_bias != cpi->common.ref_frame_sign_bias[this_ref_frame]) { - mode_mv[NEARESTMV].as_mv.row *= -1; - mode_mv[NEARESTMV].as_mv.col *= -1; - mode_mv[NEARMV].as_mv.row *= -1; - mode_mv[NEARMV].as_mv.col *= -1; - best_ref_mv.as_mv.row *= -1; - best_ref_mv.as_mv.col *= -1; - sign_bias - = cpi->common.ref_frame_sign_bias[x->e_mbd.mode_info_context->mbmi.ref_frame]; + sign_bias = cpi->common.ref_frame_sign_bias[this_ref_frame]; + mode_mv = mode_mv_sb[sign_bias]; + best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int; } #if CONFIG_MULTI_RES_ENCODING @@ -1049,10 +1048,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, if (sign_bias != cpi->common.ref_frame_sign_bias[xd->mode_info_context->mbmi.ref_frame]) - { - best_ref_mv.as_mv.row *= -1; - best_ref_mv.as_mv.col *= -1; - } + best_ref_mv.as_int = best_ref_mv_sb[!sign_bias].as_int; update_mvcount(cpi, &x->e_mbd, &best_ref_mv); } diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c index d29aa75fe..53753033c 100644 --- a/vp8/encoder/rdopt.c +++ b/vp8/encoder/rdopt.c @@ -1726,8 +1726,10 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, union b_mode_info best_bmodes[16]; MB_MODE_INFO best_mbmode; PARTITION_INFO best_partition; + int_mv best_ref_mv_sb[2]; + int_mv mode_mv_sb[2][MB_MODE_COUNT]; int_mv best_ref_mv; - int_mv mode_mv[MB_MODE_COUNT]; + int_mv *mode_mv; MB_PREDICTION_MODE this_mode; int num00; int best_mode_index = 0; @@ -1755,7 +1757,9 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int ref_frame_map[4]; int sign_bias = 0; - vpx_memset(mode_mv, 0, sizeof(mode_mv)); + mode_mv = mode_mv_sb[sign_bias]; + best_ref_mv.as_int = 0; + vpx_memset(mode_mv_sb, 0, sizeof(mode_mv_sb)); vpx_memset(&best_mbmode, 0, sizeof(best_mbmode)); vpx_memset(&best_bmodes, 0, sizeof(best_bmodes)); @@ -1767,15 +1771,16 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, */ if (ref_frame_map[1] > 0) { - vp8_find_near_mvs(&x->e_mbd, - x->e_mbd.mode_info_context, - &mode_mv[NEARESTMV], &mode_mv[NEARMV], - &best_ref_mv, - mdcounts, - ref_frame_map[1], - cpi->common.ref_frame_sign_bias); + sign_bias = vp8_find_near_mvs_bias(&x->e_mbd, + x->e_mbd.mode_info_context, + mode_mv_sb, + best_ref_mv_sb, + mdcounts, + ref_frame_map[1], + cpi->common.ref_frame_sign_bias); - sign_bias = cpi->common.ref_frame_sign_bias[ref_frame_map[1]]; + mode_mv = mode_mv_sb[sign_bias]; + best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int; } get_predictor_pointers(cpi, plane, recon_yoffset, recon_uvoffset); @@ -1829,17 +1834,11 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, x->e_mbd.pre.u_buffer = plane[this_ref_frame][1]; x->e_mbd.pre.v_buffer = plane[this_ref_frame][2]; - if (sign_bias != - cpi->common.ref_frame_sign_bias[x->e_mbd.mode_info_context->mbmi.ref_frame]) + if (sign_bias != cpi->common.ref_frame_sign_bias[this_ref_frame]) { - mode_mv[NEARESTMV].as_mv.row *= -1; - mode_mv[NEARESTMV].as_mv.col *= -1; - mode_mv[NEARMV].as_mv.row *= -1; - mode_mv[NEARMV].as_mv.col *= -1; - best_ref_mv.as_mv.row *= -1; - best_ref_mv.as_mv.col *= -1; - sign_bias - = cpi->common.ref_frame_sign_bias[x->e_mbd.mode_info_context->mbmi.ref_frame]; + sign_bias = cpi->common.ref_frame_sign_bias[this_ref_frame]; + mode_mv = mode_mv_sb[sign_bias]; + best_ref_mv.as_int = best_ref_mv_sb[sign_bias].as_int; } } @@ -2372,10 +2371,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, if (sign_bias != cpi->common.ref_frame_sign_bias[xd->mode_info_context->mbmi.ref_frame]) - { - best_ref_mv.as_mv.row *= -1; - best_ref_mv.as_mv.col *= -1; - } + best_ref_mv.as_int = best_ref_mv_sb[!sign_bias].as_int; rd_update_mvcount(cpi, x, &best_ref_mv); }