Combining integer and fractional parts of mvs for entropy coding.
authorDmitry Kovalev <dkovalev@google.com>
Wed, 15 May 2013 19:37:03 +0000 (12:37 -0700)
committerDmitry Kovalev <dkovalev@google.com>
Wed, 15 May 2013 19:37:03 +0000 (12:37 -0700)
Combining encode_nmv_component with encode_nmv_component_fp
and read_nmv_component with read_nmv_component_fp. Bitstream is slightly
changed (only the order of bits), here are the results on test sets:
stdhd: +0.047, yt: -0.038, derf: +0.001, hd: -0.011.

Change-Id: I1be312e976796df78ca63368702d0ee19f2b8c50

vp9/decoder/vp9_decodemv.c
vp9/encoder/vp9_bitstream.c
vp9/encoder/vp9_encodemv.c
vp9/encoder/vp9_encodemv.h

index a1f780a..018f92b 100644 (file)
@@ -157,77 +157,38 @@ static void kfread_modes(VP9D_COMP *pbi, MODE_INFO *m,
   }
 }
 
+static int read_mv_component(vp9_reader *r,
+                             const nmv_component *mvcomp, int usehp) {
 
-static int read_nmv_component(vp9_reader *r,
-                              int rv,
-                              const nmv_component *mvcomp) {
-  int mag, d;
+  int mag, d, fr, hp;
   const int sign = vp9_read(r, mvcomp->sign);
   const int mv_class = treed_read(r, vp9_mv_class_tree, mvcomp->classes);
 
+  // Integer part
   if (mv_class == MV_CLASS_0) {
     d = treed_read(r, vp9_mv_class0_tree, mvcomp->class0);
   } else {
     int i;
-    int n = mv_class + CLASS0_BITS - 1;  // number of bits
+    const int n = mv_class + CLASS0_BITS - 1;  // number of bits
 
     d = 0;
     for (i = 0; i < n; ++i)
       d |= vp9_read(r, mvcomp->bits[i]) << i;
   }
 
-  mag = vp9_get_mv_mag(mv_class, d << 3);
-  return sign ? -(mag + 8) : (mag + 8);
-}
-
-static int read_nmv_component_fp(vp9_reader *r,
-                                 int v,
-                                 int rv,
-                                 const nmv_component *mvcomp,
-                                 int usehp) {
-  const int sign = v < 0;
-  int mag = ((sign ? -v : v) - 1) & ~7;  // magnitude - 1
-  int offset;
-  const int mv_class = vp9_get_mv_class(mag, &offset);
-  const int f = mv_class == MV_CLASS_0 ?
-      treed_read(r, vp9_mv_fp_tree, mvcomp->class0_fp[offset >> 3]):
-      treed_read(r, vp9_mv_fp_tree, mvcomp->fp);
-
-  offset += f << 1;
+  // Fractional part
+  fr = treed_read(r, vp9_mv_fp_tree,
+                  mv_class == MV_CLASS_0 ? mvcomp->class0_fp[d] : mvcomp->fp);
 
-  if (usehp) {
-    const vp9_prob p = mv_class == MV_CLASS_0 ? mvcomp->class0_hp : mvcomp->hp;
-    offset += vp9_read(r, p);
-  } else {
-    offset += 1;  // If hp is not used, the default value of the hp bit is 1
-  }
-  mag = vp9_get_mv_mag(mv_class, offset);
-  return sign ? -(mag + 1) : (mag + 1);
-}
-
-static void read_nmv(vp9_reader *r, MV *mv, const MV *ref,
-                     const nmv_context *mvctx) {
-  const MV_JOINT_TYPE j = treed_read(r, vp9_mv_joint_tree, mvctx->joints);
-  mv->row = mv->col = 0;
-
-  if (mv_joint_vertical(j))
-    mv->row = read_nmv_component(r, ref->row, &mvctx->comps[0]);
-
-  if (mv_joint_horizontal(j))
-    mv->col = read_nmv_component(r, ref->col, &mvctx->comps[1]);
-}
 
-static void read_nmv_fp(vp9_reader *r, MV *mv, const MV *ref,
-                        const nmv_context *mvctx, int usehp) {
-  const MV_JOINT_TYPE j = vp9_get_mv_joint(mv);
-  usehp = usehp && vp9_use_nmv_hp(ref);
-  if (mv_joint_vertical(j))
-    mv->row = read_nmv_component_fp(r, mv->row, ref->row, &mvctx->comps[0],
-                                    usehp);
+  // High precision part (if hp is not used, the default value of the hp is 1)
+  hp = usehp ? vp9_read(r,
+                        mv_class == MV_CLASS_0 ? mvcomp->class0_hp : mvcomp->hp)
+             : 1;
 
-  if (mv_joint_horizontal(j))
-    mv->col = read_nmv_component_fp(r, mv->col, ref->col, &mvctx->comps[1],
-                                    usehp);
+  // result
+  mag = vp9_get_mv_mag(mv_class, (d << 3) | (fr << 1) | hp) + 1;
+  return sign ? -mag : mag;
 }
 
 static void update_nmv(vp9_reader *r, vp9_prob *const p,
@@ -516,15 +477,24 @@ static INLINE void assign_and_clamp_mv(int_mv *dst, const int_mv *src,
            mb_to_bottom_edge);
 }
 
-static INLINE void process_mv(vp9_reader *r, MV *mv, const MV *ref,
-                              const nmv_context *nmvc,
-                              nmv_context_counts *mvctx,
-                              int usehp) {
-  read_nmv(r, mv, ref, nmvc);
-  read_nmv_fp(r, mv, ref, nmvc, usehp);
-  vp9_increment_nmv(mv, ref, mvctx, usehp);
-  mv->row += ref->row;
-  mv->col += ref->col;
+static INLINE void decode_mv(vp9_reader *r, MV *mv, const MV *ref,
+                             const nmv_context *ctx,
+                             nmv_context_counts *counts,
+                             int usehp) {
+  const MV_JOINT_TYPE j = treed_read(r, vp9_mv_joint_tree, ctx->joints);
+  MV diff = {0, 0};
+
+  usehp = usehp && vp9_use_nmv_hp(ref);
+  if (mv_joint_vertical(j))
+    diff.row = read_mv_component(r, &ctx->comps[0], usehp);
+
+  if (mv_joint_horizontal(j))
+    diff.col = read_mv_component(r, &ctx->comps[1], usehp);
+
+  vp9_increment_nmv(&diff, ref, counts, usehp);
+
+  mv->row = diff.row + ref->row;
+  mv->col = diff.col + ref->col;
 }
 
 static INLINE INTERPOLATIONFILTERTYPE read_switchable_filter_type(
@@ -710,12 +680,12 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
 
           switch (blockmode) {
             case NEW4X4:
-              process_mv(r, &blockmv.as_mv, &best_mv.as_mv, nmvc,
-                         &cm->fc.NMVcount, xd->allow_high_precision_mv);
+              decode_mv(r, &blockmv.as_mv, &best_mv.as_mv, nmvc,
+                        &cm->fc.NMVcount, xd->allow_high_precision_mv);
 
               if (mbmi->second_ref_frame > 0)
-                process_mv(r, &secondmv.as_mv, &best_mv_second.as_mv, nmvc,
-                           &cm->fc.NMVcount, xd->allow_high_precision_mv);
+                decode_mv(r, &secondmv.as_mv, &best_mv_second.as_mv, nmvc,
+                          &cm->fc.NMVcount, xd->allow_high_precision_mv);
 
 #ifdef VPX_MODE_COUNT
               vp9_mv_cont_count[mv_contz][3]++;
@@ -792,8 +762,8 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
         break;
 
       case NEWMV:
-        process_mv(r, &mv0->as_mv, &best_mv.as_mv, nmvc, &cm->fc.NMVcount,
-                   xd->allow_high_precision_mv);
+        decode_mv(r, &mv0->as_mv, &best_mv.as_mv, nmvc, &cm->fc.NMVcount,
+                  xd->allow_high_precision_mv);
         mbmi->need_to_clamp_mvs = check_mv_bounds(mv0,
                                                   mb_to_left_edge,
                                                   mb_to_right_edge,
@@ -801,8 +771,8 @@ static void read_mb_modes_mv(VP9D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
                                                   mb_to_bottom_edge);
 
         if (mbmi->second_ref_frame > 0) {
-          process_mv(r, &mv1->as_mv, &best_mv_second.as_mv, nmvc,
-                     &cm->fc.NMVcount, xd->allow_high_precision_mv);
+          decode_mv(r, &mv1->as_mv, &best_mv_second.as_mv, nmvc,
+                    &cm->fc.NMVcount, xd->allow_high_precision_mv);
           mbmi->need_to_clamp_secondmv = check_mv_bounds(mv1,
                                                          mb_to_left_edge,
                                                          mb_to_right_edge,
index 9222133..32cef5e 100644 (file)
@@ -455,16 +455,6 @@ static void write_sub_mv_ref(vp9_writer *bc, B_PREDICTION_MODE m,
               vp9_sub_mv_ref_encoding_array - LEFT4X4 + m);
 }
 
-static void write_nmv(VP9_COMP *cpi, vp9_writer *bc,
-                      const MV *mv, const int_mv *ref,
-                      const nmv_context *nmvc, int usehp) {
-  MV e;
-  e.row = mv->row - ref->as_mv.row;
-  e.col = mv->col - ref->as_mv.col;
-
-  vp9_encode_nmv(bc, &e, &ref->as_mv, nmvc);
-  vp9_encode_nmv_fp(bc, &e, &ref->as_mv, nmvc, usehp);
-}
 
 // This function writes the current macro block's segnment id to the bitstream
 // It should only be called if a segment map update is indicated.
@@ -686,15 +676,14 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, MODE_INFO *m,
 #ifdef ENTROPY_STATS
         active_section = 5;
 #endif
-        write_nmv(cpi, bc, &mi->mv[0].as_mv, &mi->best_mv,
-                  (const nmv_context*) nmvc,
-                  xd->allow_high_precision_mv);
-
-        if (mi->second_ref_frame > 0) {
-          write_nmv(cpi, bc, &mi->mv[1].as_mv, &mi->best_second_mv,
-                    (const nmv_context*) nmvc,
-                    xd->allow_high_precision_mv);
-        }
+        vp9_encode_mv(bc,
+                      &mi->mv[0].as_mv, &mi->best_mv.as_mv,
+                      nmvc, xd->allow_high_precision_mv);
+
+        if (mi->second_ref_frame > 0)
+          vp9_encode_mv(bc,
+                        &mi->mv[1].as_mv, &mi->best_second_mv.as_mv,
+                        nmvc, xd->allow_high_precision_mv);
         break;
       case SPLITMV: {
         int j = 0;
@@ -724,17 +713,14 @@ static void pack_inter_mode_mvs(VP9_COMP *cpi, MODE_INFO *m,
 #ifdef ENTROPY_STATS
             active_section = 11;
 #endif
-            write_nmv(cpi, bc, &blockmv.as_mv, &mi->best_mv,
-                      (const nmv_context*) nmvc,
-                      xd->allow_high_precision_mv);
-
-            if (mi->second_ref_frame > 0) {
-              write_nmv(cpi, bc,
-                        &cpi->mb.partition_info->bmi[j].second_mv.as_mv,
-                        &mi->best_second_mv,
-                        (const nmv_context*) nmvc,
-                        xd->allow_high_precision_mv);
-            }
+            vp9_encode_mv(bc, &blockmv.as_mv, &mi->best_mv.as_mv,
+                          nmvc, xd->allow_high_precision_mv);
+
+            if (mi->second_ref_frame > 0)
+              vp9_encode_mv(bc,
+                            &cpi->mb.partition_info->bmi[j].second_mv.as_mv,
+                            &mi->best_second_mv.as_mv,
+                            nmvc, xd->allow_high_precision_mv);
           }
         } while (++j < cpi->mb.partition_info->count);
         break;
index 553c697..8858e20 100644 (file)
@@ -24,68 +24,48 @@ extern unsigned int active_section;
 nmv_context_counts tnmvcounts;
 #endif
 
-static void encode_nmv_component(vp9_writer* const bc,
-                                 int v,
-                                 int r,
-                                 const nmv_component* const mvcomp) {
-  int s, z, c, o, d;
-  assert (v != 0);            /* should not be zero */
-  s = v < 0;
-  vp9_write(bc, s, mvcomp->sign);
-  z = (s ? -v : v) - 1;       /* magnitude - 1 */
-
-  c = vp9_get_mv_class(z, &o);
-
-  write_token(bc, vp9_mv_class_tree, mvcomp->classes,
-              vp9_mv_class_encodings + c);
-
-  d = (o >> 3);               /* int mv data */
-
-  if (c == MV_CLASS_0) {
-    write_token(bc, vp9_mv_class0_tree, mvcomp->class0,
-                vp9_mv_class0_encodings + d);
+static void encode_mv_component(vp9_writer* w, int comp,
+                                const nmv_component* mvcomp, int usehp) {
+  int offset;
+  const int sign = comp < 0;
+  const int mag = sign ? -comp : comp;
+  const int mv_class = vp9_get_mv_class(mag - 1, &offset);
+  const int d = offset >> 3;                // int mv data
+  const int fr = (offset >> 1) & 3;         // fractional mv data
+  const int hp = offset & 1;                // high precision mv data
+
+  assert(comp != 0);
+
+  // Sign
+  vp9_write(w, sign, mvcomp->sign);
+
+  // Class
+  write_token(w, vp9_mv_class_tree, mvcomp->classes,
+              &vp9_mv_class_encodings[mv_class]);
+
+  // Integer bits
+  if (mv_class == MV_CLASS_0) {
+    write_token(w, vp9_mv_class0_tree, mvcomp->class0,
+                &vp9_mv_class0_encodings[d]);
   } else {
-    int i, b;
-    b = c + CLASS0_BITS - 1;  /* number of bits */
-    for (i = 0; i < b; ++i)
-      vp9_write(bc, ((d >> i) & 1), mvcomp->bits[i]);
+    int i;
+    const int n = mv_class + CLASS0_BITS - 1;  // number of bits
+    for (i = 0; i < n; ++i)
+      vp9_write(w, (d >> i) & 1, mvcomp->bits[i]);
   }
-}
 
-static void encode_nmv_component_fp(vp9_writer *bc,
-                                    int v,
-                                    int r,
-                                    const nmv_component* const mvcomp,
-                                    int usehp) {
-  int s, z, c, o, d, f, e;
-  assert (v != 0);            /* should not be zero */
-  s = v < 0;
-  z = (s ? -v : v) - 1;       /* magnitude - 1 */
-
-  c = vp9_get_mv_class(z, &o);
-
-  d = (o >> 3);               /* int mv data */
-  f = (o >> 1) & 3;           /* fractional pel mv data */
-  e = (o & 1);                /* high precision mv data */
-
-  /* Code the fractional pel bits */
-  if (c == MV_CLASS_0) {
-    write_token(bc, vp9_mv_fp_tree, mvcomp->class0_fp[d],
-                vp9_mv_fp_encodings + f);
-  } else {
-    write_token(bc, vp9_mv_fp_tree, mvcomp->fp,
-                vp9_mv_fp_encodings + f);
-  }
-  /* Code the high precision bit */
-  if (usehp) {
-    if (c == MV_CLASS_0) {
-      vp9_write(bc, e, mvcomp->class0_hp);
-    } else {
-      vp9_write(bc, e, mvcomp->hp);
-    }
-  }
+  // Fractional bits
+  write_token(w, vp9_mv_fp_tree,
+              mv_class == MV_CLASS_0 ?  mvcomp->class0_fp[d] : mvcomp->fp,
+              &vp9_mv_fp_encodings[fr]);
+
+  // High precision bit
+  if (usehp)
+    vp9_write(w, hp,
+              mv_class == MV_CLASS_0 ? mvcomp->class0_hp : mvcomp->hp);
 }
 
+
 static void build_nmv_component_cost_table(int *mvcost,
                                            const nmv_component* const mvcomp,
                                            int usehp) {
@@ -556,27 +536,19 @@ void vp9_write_nmv_probs(VP9_COMP* const cpi, int usehp, vp9_writer* const bc) {
   }
 }
 
-void vp9_encode_nmv(vp9_writer* w, const MV* const mv,
-                    const MV* const ref, const nmv_context* const mvctx) {
-  const MV_JOINT_TYPE j = vp9_get_mv_joint(mv);
-  write_token(w, vp9_mv_joint_tree, mvctx->joints, vp9_mv_joint_encodings + j);
-  if (mv_joint_vertical(j))
-    encode_nmv_component(w, mv->row, ref->col, &mvctx->comps[0]);
-
-  if (mv_joint_horizontal(j))
-    encode_nmv_component(w, mv->col, ref->col, &mvctx->comps[1]);
-}
-
-void vp9_encode_nmv_fp(vp9_writer* const bc, const MV* const mv,
-                       const MV* const ref, const nmv_context* const mvctx,
-                       int usehp) {
-  const MV_JOINT_TYPE j = vp9_get_mv_joint(mv);
+void vp9_encode_mv(vp9_writer* w, const MV* mv, const MV* ref,
+                   const nmv_context* mvctx, int usehp) {
+  const MV diff = {mv->row - ref->row,
+                   mv->col - ref->col};
+  const MV_JOINT_TYPE j = vp9_get_mv_joint(&diff);
   usehp = usehp && vp9_use_nmv_hp(ref);
+
+  write_token(w, vp9_mv_joint_tree, mvctx->joints, &vp9_mv_joint_encodings[j]);
   if (mv_joint_vertical(j))
-    encode_nmv_component_fp(bc, mv->row, ref->row, &mvctx->comps[0], usehp);
+    encode_mv_component(w, diff.row, &mvctx->comps[0], usehp);
 
   if (mv_joint_horizontal(j))
-    encode_nmv_component_fp(bc, mv->col, ref->col, &mvctx->comps[1], usehp);
+    encode_mv_component(w, diff.col, &mvctx->comps[1], usehp);
 }
 
 void vp9_build_nmv_cost_table(int *mvjoint,
index 982c952..cb25d85 100644 (file)
 #include "vp9/encoder/vp9_onyx_int.h"
 
 void vp9_write_nmv_probs(VP9_COMP* const, int usehp, vp9_writer* const);
-void vp9_encode_nmv(vp9_writer* const w, const MV* const mv,
-                    const MV* const ref, const nmv_context* const mvctx);
-void vp9_encode_nmv_fp(vp9_writer* const w, const MV* const mv,
-                       const MV* const ref, const nmv_context* const mvctx,
-                       int usehp);
+
+void vp9_encode_mv(vp9_writer* w, const MV* mv, const MV* ref,
+                   const nmv_context* mvctx, int usehp);
+
 void vp9_build_nmv_cost_table(int *mvjoint,
                               int *mvcost[2],
                               const nmv_context* const mvctx,