shithub: libvpx

Download patch

ref: 293e20df9128444a21b8ac483ee88e96386861c2
parent: dec4405cfa2a940fa24972fa1def50d8e02b7cb2
author: Ronald S. Bultje <[email protected]>
date: Tue Oct 20 09:31:40 EDT 2015

vp10: clip MVs before adding to find_ref_mvs() list.

This causes the output of find_ref_mvs() to always be unique or zero.
A nice side-effect of this is that it also causes the output of
find_ref_mvs_sub8x8() to be unique-or-zero, and it will not ignore
available candidate MVs under certain conditions.

See issue 1012.

Change-Id: If4792789cb7885dbc9db420001d95f9b91b63bfa

--- a/vp10/common/mvref_common.c
+++ b/vp10/common/mvref_common.c
@@ -30,8 +30,10 @@
   const int bw = num_8x8_blocks_wide_lookup[mi->mbmi.sb_type] << 3;
   const int bh = num_8x8_blocks_high_lookup[mi->mbmi.sb_type] << 3;
 
+#if !CONFIG_MISC_FIXES
   // Blank the reference vector list
   memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
+#endif
 
   // The nearest 2 blocks are treated differently
   // if the size < 8x8 we get the mv from the bmi substructure,
@@ -48,10 +50,10 @@
 
       if (candidate->ref_frame[0] == ref_frame)
         ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block),
-                        refmv_count, mv_ref_list, Done);
+                        refmv_count, mv_ref_list, bw, bh, xd, Done);
       else if (candidate->ref_frame[1] == ref_frame)
         ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block),
-                        refmv_count, mv_ref_list, Done);
+                        refmv_count, mv_ref_list, bw, bh, xd, Done);
     }
   }
 
@@ -66,9 +68,11 @@
       different_ref_found = 1;
 
       if (candidate->ref_frame[0] == ref_frame)
-        ADD_MV_REF_LIST(candidate->mv[0], refmv_count, mv_ref_list, Done);
+        ADD_MV_REF_LIST(candidate->mv[0], refmv_count, mv_ref_list,
+                        bw, bh, xd, Done);
       else if (candidate->ref_frame[1] == ref_frame)
-        ADD_MV_REF_LIST(candidate->mv[1], refmv_count, mv_ref_list, Done);
+        ADD_MV_REF_LIST(candidate->mv[1], refmv_count, mv_ref_list,
+                        bw, bh, xd, Done);
     }
   }
 
@@ -90,9 +94,11 @@
     }
 
     if (prev_frame_mvs->ref_frame[0] == ref_frame) {
-      ADD_MV_REF_LIST(prev_frame_mvs->mv[0], refmv_count, mv_ref_list, Done);
+      ADD_MV_REF_LIST(prev_frame_mvs->mv[0], refmv_count, mv_ref_list,
+                      bw, bh, xd, Done);
     } else if (prev_frame_mvs->ref_frame[1] == ref_frame) {
-      ADD_MV_REF_LIST(prev_frame_mvs->mv[1], refmv_count, mv_ref_list, Done);
+      ADD_MV_REF_LIST(prev_frame_mvs->mv[1], refmv_count, mv_ref_list,
+                      bw, bh, xd, Done);
     }
   }
 
@@ -108,7 +114,7 @@
 
         // If the candidate is INTRA we don't want to consider its mv.
         IF_DIFF_REF_FRAME_ADD_MV(candidate, ref_frame, ref_sign_bias,
-                                 refmv_count, mv_ref_list, Done);
+                                 refmv_count, mv_ref_list, bw, bh, xd, Done);
       }
     }
   }
@@ -123,7 +129,7 @@
         mv.as_mv.row *= -1;
         mv.as_mv.col *= -1;
       }
-      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done);
+      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
     }
 
     if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME &&
@@ -137,7 +143,7 @@
         mv.as_mv.row *= -1;
         mv.as_mv.col *= -1;
       }
-      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done);
+      ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done);
     }
   }
 
@@ -145,9 +151,14 @@
 
   mode_context[ref_frame] = counter_to_context[context_counter];
 
+#if CONFIG_MISC_FIXES
+  for (i = refmv_count; i < MAX_MV_REF_CANDIDATES; ++i)
+      mv_ref_list[i].as_int = 0;
+#else
   // Clamp vectors
   for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i)
     clamp_mv_ref(&mv_ref_list[i].as_mv, bw, bh, xd);
+#endif
 }
 
 void vp10_find_mv_refs(const VP10_COMMON *cm, const MACROBLOCKD *xd,
--- a/vp10/common/mvref_common.h
+++ b/vp10/common/mvref_common.h
@@ -164,36 +164,41 @@
   return mv;
 }
 
+#if CONFIG_MISC_FIXES
+#define CLIP_IN_ADD(mv, bw, bh, xd) clamp_mv_ref(mv, bw, bh, xd)
+#else
+#define CLIP_IN_ADD(mv, bw, bh, xd) do {} while (0)
+#endif
+
 // This macro is used to add a motion vector mv_ref list if it isn't
 // already in the list.  If it's the second motion vector it will also
 // skip all additional processing and jump to done!
-#define ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done) \
+#define ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, bw, bh, xd, Done) \
   do { \
-    if (refmv_count) { \
-      if ((mv).as_int != (mv_ref_list)[0].as_int) { \
-        (mv_ref_list)[(refmv_count)] = (mv); \
+    (mv_ref_list)[(refmv_count)] = (mv); \
+    CLIP_IN_ADD(&(mv_ref_list)[(refmv_count)].as_mv, (bw), (bh), (xd)); \
+    if (refmv_count && (mv_ref_list)[1].as_int != (mv_ref_list)[0].as_int) { \
+        (refmv_count) = 2; \
         goto Done; \
-      } \
-    } else { \
-      (mv_ref_list)[(refmv_count)++] = (mv); \
     } \
+    (refmv_count) = 1; \
   } while (0)
 
 // If either reference frame is different, not INTRA, and they
 // are different from each other scale and add the mv to our list.
 #define IF_DIFF_REF_FRAME_ADD_MV(mbmi, ref_frame, ref_sign_bias, refmv_count, \
-                                 mv_ref_list, Done) \
+                                 mv_ref_list, bw, bh, xd, Done) \
   do { \
     if (is_inter_block(mbmi)) { \
       if ((mbmi)->ref_frame[0] != ref_frame) \
         ADD_MV_REF_LIST(scale_mv((mbmi), 0, ref_frame, ref_sign_bias), \
-                        refmv_count, mv_ref_list, Done); \
+                        refmv_count, mv_ref_list, bw, bh, xd, Done); \
       if (has_second_ref(mbmi) && \
           (CONFIG_MISC_FIXES || \
            (mbmi)->mv[1].as_int != (mbmi)->mv[0].as_int) && \
           (mbmi)->ref_frame[1] != ref_frame) \
         ADD_MV_REF_LIST(scale_mv((mbmi), 1, ref_frame, ref_sign_bias), \
-                        refmv_count, mv_ref_list, Done); \
+                        refmv_count, mv_ref_list, bw, bh, xd, Done); \
     } \
   } while (0)