shithub: libvpx

Download patch

ref: 83cef816fdb16d64be160d5b740a1b242fe3481e
parent: 630d3b95e297405bb95234c7d2036ca218cdd64d
author: John Koleszar <jkoleszar@google.com>
date: Wed Jan 25 09:55:49 EST 2012

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

--- a/vp8/common/findnearmv.c
+++ b/vp8/common/findnearmv.c
@@ -134,12 +134,50 @@
     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]
--- a/vp8/common/findnearmv.h
+++ b/vp8/common/findnearmv.h
@@ -77,6 +77,19 @@
     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]
 );
--- a/vp8/encoder/bitstream.c
+++ b/vp8/encoder/bitstream.c
@@ -1013,6 +1013,8 @@
                     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
--- a/vp8/encoder/pickinter.c
+++ b/vp8/encoder/pickinter.c
@@ -469,8 +469,10 @@
     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 @@
                                   &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 @@
      */
     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 @@
             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 @@
 
     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);
 }
--- a/vp8/encoder/rdopt.c
+++ b/vp8/encoder/rdopt.c
@@ -1726,8 +1726,10 @@
     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 @@
     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 @@
      */
     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 @@
             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 @@
 
     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);
 }