From 18375238e98676e8fcf4c024ed19bcae95a960b7 Mon Sep 17 00:00:00 2001 From: Dmitry Kovalev <dkovalev@google.com> Date: Wed, 15 May 2013 12:37:03 -0700 Subject: [PATCH] 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 --- vp9/decoder/vp9_decodemv.c | 112 ++++++++++++--------------------- vp9/encoder/vp9_bitstream.c | 46 +++++--------- vp9/encoder/vp9_encodemv.c | 120 ++++++++++++++---------------------- vp9/encoder/vp9_encodemv.h | 9 ++- 4 files changed, 107 insertions(+), 180 deletions(-) diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c index a1f780abb3..018f92b083 100644 --- a/vp9/decoder/vp9_decodemv.c +++ b/vp9/decoder/vp9_decodemv.c @@ -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, diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 9222133ce1..32cef5e6cc 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -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; diff --git a/vp9/encoder/vp9_encodemv.c b/vp9/encoder/vp9_encodemv.c index 553c69790b..8858e206bc 100644 --- a/vp9/encoder/vp9_encodemv.c +++ b/vp9/encoder/vp9_encodemv.c @@ -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, diff --git a/vp9/encoder/vp9_encodemv.h b/vp9/encoder/vp9_encodemv.h index 982c952c17..cb25d85ee3 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, -- GitLab