Correct clamping in use of vp8_find_near_mvs()
authorJohn Koleszar <jkoleszar@google.com>
Wed, 25 Jan 2012 22:55:49 +0000 (14:55 -0800)
committerJohn Koleszar <jkoleszar@google.com>
Thu, 26 Jan 2012 17:37:27 +0000 (09:37 -0800)
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
vp8/common/findnearmv.h
vp8/encoder/bitstream.c
vp8/encoder/pickinter.c
vp8/encoder/rdopt.c

index c1022363eca524edba01f14279d503ce103419ee..e8ee40f56c6d1a5349d256c07c0f845c4c74c379 100644 (file)
@@ -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]
 )
index a3443d7653b489fe20f7398f49623c1997abd121..06ef060c2d6d17c2474245d6ff7c871ef0d87b14 100644 (file)
@@ -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]
 );
index 669bfad9ab6b2de37c181eb20788ed4e50d01bf8..0bb51730e0b3a55275a1e42fc524a4a0451e2a92 100644 (file)
@@ -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
index 405c72dbd56e2f82cb8bb435141b2e7811138747..3612cc3a801b764df96d942e0f97c42f26f23769 100644 (file)
@@ -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 = cpi->common.ref_frame_sign_bias[ref_frame_map[1]];
+        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);
+
+        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);
 }
index d29aa75fe81311e1e7c001ae6398bd394152a100..53753033cc9e5b96b4202f88a437138582e27607 100644 (file)
@@ -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 = cpi->common.ref_frame_sign_bias[ref_frame_map[1]];
+        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);
+
+        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);
 }