Commit 18375238 authored by Dmitry Kovalev's avatar Dmitry Kovalev

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
parent 089ed30d
......@@ -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,
......
......@@ -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;
......
......@@ -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,
......
......@@ -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,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment