shithub: libvpx

Download patch

ref: 2b26cf17862949123618d2dbe60a661fbb7eb4a9
parent: d406334f2712a1ec1bef890b2397927918a84e48
author: Deb Mukherjee <debargha@google.com>
date: Thu Sep 6 05:07:42 EDT 2012

Adds feature for companded MV encoding

The high-precision (1/8) pel bit is turned off if the reference
MV is larger than a threshold. The motivation for this patch is
the intuition that if motion is likely large (as indicated by
the reference), there is likley to be more motion blur, and as
a result 1/8 pel precision would be wasteful both in rd sense
as well as computationally.

The feature is incorporated as part of the newmventropy experiment.
There is a modest RD improvement with the patch. Overall the
results with the newmventropy experiment with the threshold being
16 integer pels are:

derf: +0.279%
std-hd: +0.617%
hd: +1.299%
yt: +0.822%

With threshold 8 integer pels are:

derf: +0.295%
std-hd: +0.623%
hd: +1.365%
yt: +0.847%

Patch: rebased
Patch: rebase fixes

Change-Id: I4ed14600df3c457944e6541ed407cb6e91fe428b

--- a/vp8/common/entropymv.c
+++ b/vp8/common/entropymv.c
@@ -19,6 +19,9 @@
 #define MV_COUNT_SAT 16
 #define MV_MAX_UPDATE_FACTOR 160
 
+/* Integer pel reference mv threshold for use of high-precision 1/8 mv */
+#define COMPANDED_MVREF_THRESH    8
+
 /* Smooth or bias the mv-counts before prob computation */
 /* #define SMOOTH_MV_COUNTS */
 
@@ -103,6 +106,14 @@
   return c;
 }
 
+int vp8_use_nmv_hp(const MV *ref) {
+  if ((abs(ref->row) >> 3) < COMPANDED_MVREF_THRESH &&
+      (abs(ref->col) >> 3) < COMPANDED_MVREF_THRESH)
+    return 1;
+  else
+    return 0;
+}
+
 int vp8_get_mv_mag(MV_CLASS_TYPE c, int offset) {
   return mv_class_base(c) + offset;
 }
@@ -154,12 +165,6 @@
     } else {
       mvcomp->hp[e] += incr;
     }
-  } else {  /* assume the extra bit is 1 */
-    if (c == MV_CLASS_0) {
-      mvcomp->class0_hp[1] += incr;
-    } else {
-      mvcomp->hp[1] += incr;
-    }
   }
 }
 
@@ -194,6 +199,7 @@
                        int usehp) {
   MV_JOINT_TYPE j = vp8_get_mv_joint(*mv);
   mvctx->joints[j]++;
+  usehp = usehp && vp8_use_nmv_hp(ref);
   if (j == MV_JOINT_HZVNZ || j == MV_JOINT_HNZVNZ) {
     increment_nmv_component_count(mv->row, &mvctx->comps[0], 1, usehp);
   }
--- a/vp8/common/entropymv.h
+++ b/vp8/common/entropymv.h
@@ -21,11 +21,11 @@
 void vp8_entropy_mv_init();
 void vp8_init_mv_probs(struct VP8Common *cm);
 void vp8_adapt_mv_probs(struct VP8Common *cm);
-#if CONFIG_NEWMVENTROPY
-void vp8_adapt_nmv_probs(struct VP8Common *cm, int usehp);
-#endif
 
 #if CONFIG_NEWMVENTROPY
+void vp8_adapt_nmv_probs(struct VP8Common *cm, int usehp);
+void vp8_lower_mv_precision(MV *mv);
+int vp8_use_nmv_hp(const MV *ref);
 
 #define VP8_NMV_UPDATE_PROB  255
 //#define MV_GROUP_UPDATE
--- a/vp8/common/findnearmv.c
+++ b/vp8/common/findnearmv.c
@@ -20,15 +20,20 @@
   { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15}
 };
 
-static void lower_mv_precision(int_mv *mv)
+static void lower_mv_precision(int_mv *mv, int usehp)
 {
-  if (mv->as_mv.row & 1)
-    mv->as_mv.row += (mv->as_mv.row > 0 ? -1 : 1);
-  if (mv->as_mv.col & 1)
-    mv->as_mv.col += (mv->as_mv.col > 0 ? -1 : 1);
+#if CONFIG_NEWMVENTROPY
+  if (!usehp || !vp8_use_nmv_hp(&mv->as_mv)) {
+#else
+  if (!usehp) {
+#endif
+    if (mv->as_mv.row & 1)
+      mv->as_mv.row += (mv->as_mv.row > 0 ? -1 : 1);
+    if (mv->as_mv.col & 1)
+      mv->as_mv.col += (mv->as_mv.col > 0 ? -1 : 1);
+  }
 }
 
-
 /* Predict motion vectors using those from already-decoded nearby blocks.
    Note that we only consider one 4x4 subblock from each candidate 16x16
    macroblock.   */
@@ -173,11 +178,9 @@
   /* Make sure that the 1/8th bits of the Mvs are zero if high_precision
    * is not being used, by truncating the last bit towards 0
    */
-  if (!xd->allow_high_precision_mv) {
-    lower_mv_precision(best_mv);
-    lower_mv_precision(nearest);
-    lower_mv_precision(nearby);
-  }
+  lower_mv_precision(best_mv, xd->allow_high_precision_mv);
+  lower_mv_precision(nearest, xd->allow_high_precision_mv);
+  lower_mv_precision(nearby, xd->allow_high_precision_mv);
 
   // TODO: move clamp outside findnearmv
   vp8_clamp_mv2(nearest, xd);
@@ -301,9 +304,7 @@
 
   // Copy back the re-ordered mv list
   vpx_memcpy(mvlist, sorted_mvs, sizeof(sorted_mvs));
-
-  if (!xd->allow_high_precision_mv)
-    lower_mv_precision(best_mv);
+  lower_mv_precision(best_mv, xd->allow_high_precision_mv);
 
   vp8_clamp_mv2(best_mv, xd);
 }
--- a/vp8/decoder/decodemv.c
+++ b/vp8/decoder/decodemv.c
@@ -244,6 +244,7 @@
 static void read_nmv_fp(vp8_reader *r, MV *mv, const MV *ref,
                         const nmv_context *mvctx, int usehp) {
   MV_JOINT_TYPE j = vp8_get_mv_joint(*mv);
+  usehp = usehp && vp8_use_nmv_hp(ref);
   if (j == MV_JOINT_HZVNZ || j == MV_JOINT_HNZVNZ) {
     mv->row = read_nmv_component_fp(r, mv->row, ref->row, &mvctx->comps[0],
                                     usehp);
@@ -252,6 +253,7 @@
     mv->col = read_nmv_component_fp(r, mv->col, ref->col, &mvctx->comps[1],
                                     usehp);
   }
+  //printf("  %d: %d %d ref: %d %d\n", usehp, mv->row, mv-> col, ref->row, ref->col);
 }
 
 static void update_nmv(vp8_reader *bc, vp8_prob *const p,
--- a/vp8/encoder/encodemv.c
+++ b/vp8/encoder/encodemv.c
@@ -526,6 +526,7 @@
 void vp8_encode_nmv_fp(vp8_writer *w, const MV *mv, const MV *ref,
                        const nmv_context *mvctx, int usehp) {
   MV_JOINT_TYPE j = vp8_get_mv_joint(*mv);
+  usehp = usehp && vp8_use_nmv_hp(ref);
   if (j == MV_JOINT_HZVNZ || j == MV_JOINT_HNZVNZ) {
     encode_nmv_component_fp(w, mv->row, ref->row, &mvctx->comps[0], usehp);
   }
--- a/vp8/encoder/mcomp.c
+++ b/vp8/encoder/mcomp.c
@@ -276,6 +276,7 @@
   int maxc, minc, maxr, minr;
   int y_stride;
   int offset;
+  int usehp = xd->allow_high_precision_mv;
 
 #if !CONFIG_SUPERBLOCKS && (ARCH_X86 || ARCH_X86_64)
   unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
@@ -301,7 +302,6 @@
   y_stride = d->pre_stride;
 #endif
 
-
   rr = ref_mv->as_mv.row;
   rc = ref_mv->as_mv.col;
   br = bestmv->as_mv.row << 3;
@@ -403,7 +403,15 @@
     tc = bc;
   }
 
-  if (x->e_mbd.allow_high_precision_mv) {
+#if CONFIG_NEWMVENTROPY
+  if (xd->allow_high_precision_mv) {
+    usehp = vp8_use_nmv_hp(&ref_mv->as_mv);
+  } else {
+    usehp = 0;
+  }
+#endif
+
+  if (usehp) {
     hstep >>= 1;
     while (--eighthiters) {
       CHECK_BETTER(left, tr, tc - hstep);
@@ -471,6 +479,7 @@
   int thismse;
   int y_stride;
   MACROBLOCKD *xd = &x->e_mbd;
+  int usehp = xd->allow_high_precision_mv;
 
 #if !CONFIG_SUPERBLOCKS && (ARCH_X86 || ARCH_X86_64)
   unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col;
@@ -762,7 +771,14 @@
     *sse1 = sse;
   }
 
-  if (!x->e_mbd.allow_high_precision_mv)
+#if CONFIG_NEWMVENTROPY
+  if (x->e_mbd.allow_high_precision_mv) {
+    usehp = vp8_use_nmv_hp(&ref_mv->as_mv);
+  } else {
+    usehp = 0;
+  }
+#endif
+  if (!usehp)
     return bestmse;
 
   /* Now do 1/8th pixel */