Combining integer and fractional parts of mvs for entropy coding.
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
diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c
index a1f780a..018f92b 100644
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -157,77 +157,38 @@
}
}
+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);
-}
+ // Fractional part
+ fr = treed_read(r, vp9_mv_fp_tree,
+ mv_class == MV_CLASS_0 ? mvcomp->class0_fp[d] : mvcomp->fp);
-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;
+ // 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 (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);
-
- 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 @@
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 @@
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 @@
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 @@
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,
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 9222133..32cef5e 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -455,16 +455,6 @@
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 @@
#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);
+ 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) {
- write_nmv(cpi, bc, &mi->mv[1].as_mv, &mi->best_second_mv,
- (const nmv_context*) 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 @@
#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);
+ vp9_encode_mv(bc, &blockmv.as_mv, &mi->best_mv.as_mv,
+ 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);
- }
+ 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;
diff --git a/vp9/encoder/vp9_encodemv.c b/vp9/encoder/vp9_encodemv.c
index 553c697..8858e20 100644
--- a/vp9/encoder/vp9_encodemv.c
+++ b/vp9/encoder/vp9_encodemv.c
@@ -24,67 +24,47 @@
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 */
+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
- c = vp9_get_mv_class(z, &o);
+ assert(comp != 0);
- write_token(bc, vp9_mv_class_tree, mvcomp->classes,
- vp9_mv_class_encodings + c);
+ // Sign
+ vp9_write(w, sign, mvcomp->sign);
- d = (o >> 3); /* int mv data */
+ // Class
+ write_token(w, vp9_mv_class_tree, mvcomp->classes,
+ &vp9_mv_class_encodings[mv_class]);
- if (c == MV_CLASS_0) {
- write_token(bc, vp9_mv_class0_tree, mvcomp->class0,
- vp9_mv_class0_encodings + d);
+ // 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]);
}
+
+ // 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 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);
- }
- }
-}
static void build_nmv_component_cost_table(int *mvcost,
const nmv_component* const mvcomp,
@@ -556,27 +536,19 @@
}
}
-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,
diff --git a/vp9/encoder/vp9_encodemv.h b/vp9/encoder/vp9_encodemv.h
index 982c952..cb25d85 100644
--- a/vp9/encoder/vp9_encodemv.h
+++ b/vp9/encoder/vp9_encodemv.h
@@ -15,11 +15,10 @@
#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,