diff --git a/vp8/common/entropymode.c b/vp8/common/entropymode.c index 540da33ed147ef6c54e3ed93516c4b80f2166b4d..f220a6ba0afdec6aa59f5184e46039a999d2f9ad 100644 --- a/vp8/common/entropymode.c +++ b/vp8/common/entropymode.c @@ -226,7 +226,7 @@ struct vp8_token_struct vp8_mv_ref_encoding_array [VP8_MVREFS]; struct vp8_token_struct vp8_sub_mv_ref_encoding_array [VP8_SUBMVREFS]; #if CONFIG_HIGH_PRECISION_MV -const vp8_tree_index vp8_small_mvtree [30] = +const vp8_tree_index vp8_small_mvtree_hp [30] = { 2, 16, 4, 10, @@ -244,9 +244,8 @@ const vp8_tree_index vp8_small_mvtree [30] = -12, -13, -14, -15 }; -struct vp8_token_struct vp8_small_mvencodings [16]; - -#else +struct vp8_token_struct vp8_small_mvencodings_hp [16]; +#endif /* CONFIG_HIGH_PRECISION_MV */ const vp8_tree_index vp8_small_mvtree [14] = { @@ -260,7 +259,6 @@ const vp8_tree_index vp8_small_mvtree [14] = }; struct vp8_token_struct vp8_small_mvencodings [8]; -#endif /* CONFIG_HIGH_PRECISION_MV */ void vp8_init_mbmode_probs(VP8_COMMON *x) @@ -381,6 +379,9 @@ void vp8_entropy_mode_init() vp8_sub_mv_ref_tree, LEFT4X4); vp8_tokens_from_tree(vp8_small_mvencodings, vp8_small_mvtree); +#if CONFIG_HIGH_PRECISION_MV + vp8_tokens_from_tree(vp8_small_mvencodings_hp, vp8_small_mvtree_hp); +#endif } void vp8_init_mode_contexts(VP8_COMMON *pc) diff --git a/vp8/common/entropymode.h b/vp8/common/entropymode.h index 31170677c281d3b8287a34708b25a3df8c91a907..5c14ccaded9ba659d58e5464214cf8f79e915b81 100644 --- a/vp8/common/entropymode.h +++ b/vp8/common/entropymode.h @@ -56,11 +56,10 @@ extern struct vp8_token_struct vp8_mv_ref_encoding_array [VP8_MVREFS]; extern struct vp8_token_struct vp8_sub_mv_ref_encoding_array [VP8_SUBMVREFS]; extern const vp8_tree_index vp8_small_mvtree[]; - -#if CONFIG_HIGH_PRECISION_MV -extern struct vp8_token_struct vp8_small_mvencodings [16]; -#else extern struct vp8_token_struct vp8_small_mvencodings [8]; +#if CONFIG_HIGH_PRECISION_MV +extern const vp8_tree_index vp8_small_mvtree_hp[]; +extern struct vp8_token_struct vp8_small_mvencodings_hp [16]; #endif void vp8_entropy_mode_init(void); diff --git a/vp8/common/entropymv.c b/vp8/common/entropymv.c index 4959fe92e94838e8271f89f856a9301a9e96edfd..90195f7bccdeb2c2de6413f5c10aa587ccca23f6 100644 --- a/vp8/common/entropymv.c +++ b/vp8/common/entropymv.c @@ -12,7 +12,7 @@ #include "entropymv.h" #if CONFIG_HIGH_PRECISION_MV -const MV_CONTEXT vp8_mv_update_probs[2] = +const MV_CONTEXT_HP vp8_mv_update_probs_hp[2] = { {{ 237, @@ -27,7 +27,7 @@ const MV_CONTEXT vp8_mv_update_probs[2] = 254, 254, 254, 254, 254, 251, 251, 254, 254, 254, 254 }} }; -const MV_CONTEXT vp8_default_mv_context[2] = +const MV_CONTEXT_HP vp8_default_mv_context_hp[2] = { {{ /* row */ @@ -44,7 +44,8 @@ const MV_CONTEXT vp8_default_mv_context[2] = 128, 130, 130, 74, 148, 180, 203, 236, 254, 254, 254 /* long bits */ }} }; -#else +#endif /* CONFIG_HIGH_PRECISION_MV */ + const MV_CONTEXT vp8_mv_update_probs[2] = { {{ @@ -77,4 +78,3 @@ const MV_CONTEXT vp8_default_mv_context[2] = 128, 130, 130, 74, 148, 180, 203, 236, 254, 254 /* long bits */ }} }; -#endif /* CONFIG_HIGH_PRECISION_MV */ diff --git a/vp8/common/entropymv.h b/vp8/common/entropymv.h index 390c4f4a28b52935e659272ed2b103d3cfd0ff5a..d97c12eab61caf883f746080ee83cab3b8ec9e77 100644 --- a/vp8/common/entropymv.h +++ b/vp8/common/entropymv.h @@ -15,27 +15,13 @@ #include "treecoder.h" #include "vpx_config.h" -#if CONFIG_HIGH_PRECISION_MV -#define MV_SHIFT 0 -#else -#define MV_SHIFT 1 -#endif - enum { -#if CONFIG_HIGH_PRECISION_MV - mv_max = 2047, /* max absolute value of a MV component */ - MVvals = (2 * mv_max) + 1, /* # possible values "" */ - mvlong_width = 11, /* Large MVs have 9 bit magnitudes */ - mvnum_short = 16, /* magnitudes 0 through 15 */ - mvnum_short_bits = 4, /* number of bits for short mvs */ -#else mv_max = 1023, /* max absolute value of a MV component */ MVvals = (2 * mv_max) + 1, /* # possible values "" */ mvlong_width = 10, /* Large MVs have 9 bit magnitudes */ mvnum_short = 8, /* magnitudes 0 through 7 */ mvnum_short_bits = 3, /* number of bits for short mvs */ -#endif mvfp_max = 255, /* max absolute value of a full pixel MV component */ MVfpvals = (2 * mvfp_max) + 1, /* # possible full pixel MV values */ @@ -57,4 +43,34 @@ typedef struct mv_context extern const MV_CONTEXT vp8_mv_update_probs[2], vp8_default_mv_context[2]; +#if CONFIG_HIGH_PRECISION_MV +enum +{ + mv_max_hp = 2047, /* max absolute value of a MV component */ + MVvals_hp = (2 * mv_max_hp) + 1, /* # possible values "" */ + mvlong_width_hp = 11, /* Large MVs have 9 bit magnitudes */ + mvnum_short_hp = 16, /* magnitudes 0 through 15 */ + mvnum_short_bits_hp = 4, /* number of bits for short mvs */ + + mvfp_max_hp = 255, /* max absolute value of a full pixel MV component */ + MVfpvals_hp = (2 * mvfp_max_hp) + 1, /* # possible full pixel MV values */ + + /* probability offsets for coding each MV component */ + + mvpis_short_hp = 0, /* short (<= 7) vs long (>= 8) */ + MVPsign_hp, /* sign for non-zero */ + MVPshort_hp, /* 8 short values = 7-position tree */ + + MVPbits_hp = MVPshort_hp + mvnum_short_hp - 1, /* mvlong_width long value bits */ + MVPcount_hp = MVPbits_hp + mvlong_width_hp /* (with independent probabilities) */ +}; + +typedef struct mv_context_hp +{ + vp8_prob prob[MVPcount_hp]; /* often come in row, col pairs */ +} MV_CONTEXT_HP; + +extern const MV_CONTEXT_HP vp8_mv_update_probs_hp[2], vp8_default_mv_context_hp[2]; +#endif /* CONFIG_HIGH_PRECISION_MV */ + #endif diff --git a/vp8/common/filter.c b/vp8/common/filter.c index 2e3acc29ceb492c8ebf9c5ba055af9cfbe9e79d7..d1ef79666df9c4ae5ed726df8c2184e94f4b28b6 100644 --- a/vp8/common/filter.c +++ b/vp8/common/filter.c @@ -45,7 +45,7 @@ DECLARE_ALIGNED(16, const short, vp8_bilinear_filters[SUBPEL_SHIFTS][2]) = }; #if CONFIG_ENHANCED_INTERP -#define FILTER_ALPHA 0 +#define FILTER_ALPHA 60 DECLARE_ALIGNED(16, const short, vp8_sub_pel_filters[SUBPEL_SHIFTS][2*INTERP_EXTEND]) = { /* Generated using MATLAB: diff --git a/vp8/common/findnearmv.c b/vp8/common/findnearmv.c index 2023a1910e7fe5a68322e2693353a2740ecd4dd7..a741471064dc630e92cfe2a07929fa7e31179d06 100644 --- a/vp8/common/findnearmv.c +++ b/vp8/common/findnearmv.c @@ -21,6 +21,7 @@ const unsigned char vp8_mbsplit_offset[4][16] = { /* Predict motion vectors using those from already-decoded nearby blocks. Note that we only consider one 4x4 subblock from each candidate 16x16 macroblock. */ + void vp8_find_near_mvs ( MACROBLOCKD *xd, @@ -145,6 +146,27 @@ void vp8_find_near_mvs nearest->as_int = near_mvs[CNT_NEAREST].as_int; nearby->as_int = near_mvs[CNT_NEAR].as_int; + /* 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 CONFIG_HIGH_PRECISION_MV + if (!xd->allow_high_precision_mv) + { + if (best_mv->as_mv.row & 1) + best_mv->as_mv.row += (best_mv->as_mv.row > 0 ? -1 : 1); + if (best_mv->as_mv.col & 1) + best_mv->as_mv.col += (best_mv->as_mv.col > 0 ? -1 : 1); + if (nearest->as_mv.row & 1) + nearest->as_mv.row += (nearest->as_mv.row > 0 ? -1 : 1); + if (nearest->as_mv.col & 1) + nearest->as_mv.col += (nearest->as_mv.col > 0 ? -1 : 1); + if (nearby->as_mv.row & 1) + nearby->as_mv.row += (nearby->as_mv.row > 0 ? -1 : 1); + if (nearby->as_mv.col & 1) + nearby->as_mv.col += (nearby->as_mv.col > 0 ? -1 : 1); + } +#endif + //TODO: move clamp outside findnearmv vp8_clamp_mv2(nearest, xd); vp8_clamp_mv2(nearby, xd); @@ -161,4 +183,3 @@ vp8_prob *vp8_mv_ref_probs(VP8_COMMON *pc, p[3] = pc->vp8_mode_contexts [near_mv_ref_ct[3]] [3]; return p; } - diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h index ba500cf160732fb4d758404151f398a1d6adf0ac..b7ce29e9a2abd45aa3ee1fa5a586e70e1f5b040a 100644 --- a/vp8/common/onyxc_int.h +++ b/vp8/common/onyxc_int.h @@ -58,6 +58,10 @@ typedef struct frame_contexts #endif MV_CONTEXT mvc[2]; MV_CONTEXT pre_mvc[2]; /* not to caculate the mvcost for the frame if mvc doesn't change. */ +#if CONFIG_HIGH_PRECISION_MV + MV_CONTEXT_HP mvc_hp[2]; + MV_CONTEXT_HP pre_mvc_hp[2]; /* not to caculate the mvcost for the frame if mvc doesn't change. */ +#endif } FRAME_CONTEXT; typedef enum diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c index d77340b0bcd533a16ee346fe5cf3ee065a82f535..fc1098a44dc92dccbcfd258b283cd3ddc7dd6cdd 100644 --- a/vp8/decoder/decodemv.c +++ b/vp8/decoder/decodemv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 The WebM project authors. All Rights Reserved. + Copyright (c) 2010 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -203,13 +203,13 @@ static int read_mvcomponent(vp8_reader *r, const MV_CONTEXT *mvc) static void read_mv(vp8_reader *r, MV *mv, const MV_CONTEXT *mvc) { - mv->row = (short)(read_mvcomponent(r, mvc) << MV_SHIFT); - mv->col = (short)(read_mvcomponent(r, ++mvc) << MV_SHIFT); + mv->row = (short)(read_mvcomponent(r, mvc) << 1); + mv->col = (short)(read_mvcomponent(r, ++mvc) << 1); #ifdef DEBUG_DEC_MV int i; - printf("%d: %d %d\n", dec_mvcount++, mv->row, mv->col); - for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[-1])->prob[i]); printf("\n"); - for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[0])->prob[i]); printf("\n"); + printf("%d (np): %d %d\n", dec_mvcount++, mv->row, mv->col); + //for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[-1])->prob[i]); printf("\n"); + //for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[0])->prob[i]); printf("\n"); #endif } @@ -238,6 +238,79 @@ static void read_mvcontexts(vp8_reader *bc, MV_CONTEXT *mvc) while (++i < 2); } +#if CONFIG_HIGH_PRECISION_MV +static int read_mvcomponent_hp(vp8_reader *r, const MV_CONTEXT_HP *mvc) +{ + const vp8_prob *const p = (const vp8_prob *) mvc; + int x = 0; + + if (vp8_read(r, p [mvpis_short_hp])) /* Large */ + { + int i = 0; + + do + { + x += vp8_read(r, p [MVPbits_hp + i]) << i; + } + while (++i < mvnum_short_bits_hp); + + i = mvlong_width_hp - 1; /* Skip bit 3, which is sometimes implicit */ + + do + { + x += vp8_read(r, p [MVPbits_hp + i]) << i; + } + while (--i > mvnum_short_bits_hp); + + if (!(x & ~((2<<mvnum_short_bits_hp)-1)) || vp8_read(r, p [MVPbits_hp + mvnum_short_bits_hp])) + x += (mvnum_short_hp); + } + else /* small */ + x = vp8_treed_read(r, vp8_small_mvtree_hp, p + MVPshort_hp); + + if (x && vp8_read(r, p [MVPsign_hp])) + x = -x; + + return x; +} + +static void read_mv_hp(vp8_reader *r, MV *mv, const MV_CONTEXT_HP *mvc) +{ + mv->row = (short)(read_mvcomponent_hp(r, mvc)); + mv->col = (short)(read_mvcomponent_hp(r, ++mvc)); +#ifdef DEBUG_DEC_MV + int i; + printf("%d (hp): %d %d\n", dec_mvcount++, mv->row, mv->col); + //for (i=0; i<MVPcount_hp;++i) printf(" %d", (&mvc[-1])->prob[i]); printf("\n"); + //for (i=0; i<MVPcount_hp;++i) printf(" %d", (&mvc[0])->prob[i]); printf("\n"); +#endif +} + +static void read_mvcontexts_hp(vp8_reader *bc, MV_CONTEXT_HP *mvc) +{ + int i = 0; + + do + { + const vp8_prob *up = vp8_mv_update_probs_hp[i].prob; + vp8_prob *p = (vp8_prob *)(mvc + i); + vp8_prob *const pstop = p + MVPcount_hp; + + do + { + if (vp8_read(bc, *up++)) + { + const vp8_prob x = (vp8_prob)vp8_read_literal(bc, 7); + + *p = x ? x << 1 : 1; + } + } + while (++p < pstop); + } + while (++i < 2); +} +#endif /* CONFIG_HIGH_PRECISION_MV */ + // Read the referncence frame static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, vp8_reader *const bc, @@ -406,6 +479,10 @@ static void mb_mode_mv_init(VP8D_COMP *pbi) VP8_COMMON *const cm = & pbi->common; vp8_reader *const bc = & pbi->bc; MV_CONTEXT *const mvc = pbi->common.fc.mvc; +#if CONFIG_HIGH_PRECISION_MV + MV_CONTEXT_HP *const mvc_hp = pbi->common.fc.mvc_hp; + MACROBLOCKD *const xd = & pbi->mb; +#endif pbi->prob_skip_false = 0; if (pbi->common.mb_no_coeff_skip) @@ -456,6 +533,11 @@ static void mb_mode_mv_init(VP8D_COMP *pbi) while (++i < VP8_UV_MODES-1); } #endif /* CONFIG_UVINTRA */ +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + read_mvcontexts_hp(bc, mvc_hp); + else +#endif read_mvcontexts(bc, mvc); } } @@ -529,6 +611,9 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, VP8_COMMON *const cm = & pbi->common; vp8_reader *const bc = & pbi->bc; MV_CONTEXT *const mvc = pbi->common.fc.mvc; +#if CONFIG_HIGH_PRECISION_MV + MV_CONTEXT_HP *const mvc_hp = pbi->common.fc.mvc_hp; +#endif const int mis = pbi->common.mode_info_stride; MACROBLOCKD *const xd = & pbi->mb; @@ -640,6 +725,11 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, switch (sub_mv_ref(bc, vp8_sub_mv_ref_prob2 [mv_contz])) /*pc->fc.sub_mv_ref_prob))*/ { case NEW4X4: +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + read_mv_hp(bc, &blockmv.as_mv, (const MV_CONTEXT_HP *) mvc_hp); + else +#endif read_mv(bc, &blockmv.as_mv, (const MV_CONTEXT *) mvc); blockmv.as_mv.row += best_mv.as_mv.row; blockmv.as_mv.col += best_mv.as_mv.col; @@ -717,6 +807,11 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, goto propagate_mv; case NEWMV: +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + read_mv_hp(bc, &mv->as_mv, (const MV_CONTEXT_HP *) mvc_hp); + else +#endif read_mv(bc, &mv->as_mv, (const MV_CONTEXT *) mvc); mv->as_mv.row += best_mv.as_mv.row; mv->as_mv.col += best_mv.as_mv.col; @@ -764,6 +859,12 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, mb_to_top_edge, mb_to_bottom_edge); break; case NEWMV: +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + read_mv_hp(bc, &mbmi->second_mv.as_mv, + (const MV_CONTEXT_HP *) mvc_hp); + else +#endif read_mv(bc, &mbmi->second_mv.as_mv, (const MV_CONTEXT *) mvc); mbmi->second_mv.as_mv.row += best_mv.as_mv.row; mbmi->second_mv.as_mv.col += best_mv.as_mv.col; diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index 0cb1d0e4881ee990a9d08b70967dcaa4d5a402d4..06673b4c2d3a599d26f1563fe62fa1a2209efc0a 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -738,6 +738,10 @@ static void init_frame(VP8D_COMP *pbi) { /* Various keyframe initializations */ vpx_memcpy(pc->fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context)); +#if CONFIG_HIGH_PRECISION_MV + vpx_memcpy(pc->fc.mvc_hp, vp8_default_mv_context_hp, + sizeof(vp8_default_mv_context_hp)); +#endif vp8_init_mbmode_probs(pc); diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index 2531e02735725293fa82732f13c663b6ed2e48d5..1a62e44ae6e1b84c82d6b93aedd657174aa48e99 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -46,7 +46,6 @@ extern unsigned int active_section; int count_mb_seg[4] = { 0, 0, 0, 0 }; #endif - static void update_mode( vp8_writer *const w, int n, @@ -389,6 +388,20 @@ static void write_mv vp8_encode_motion_vector(w, &e, mvc); } +#if CONFIG_HIGH_PRECISION_MV +static void write_mv_hp +( + vp8_writer *w, const MV *mv, const int_mv *ref, const MV_CONTEXT_HP *mvc +) +{ + MV e; + e.row = mv->row - ref->as_mv.row; + e.col = mv->col - ref->as_mv.col; + + vp8_encode_motion_vector_hp(w, &e, mvc); +} +#endif + // 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. static void write_mb_segid(vp8_writer *w, @@ -556,6 +569,9 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) VP8_COMMON *const pc = & cpi->common; vp8_writer *const w = & cpi->bc; const MV_CONTEXT *mvc = pc->fc.mvc; +#if CONFIG_HIGH_PRECISION_MV + const MV_CONTEXT_HP *mvc_hp = pc->fc.mvc_hp; +#endif MACROBLOCKD *xd = &cpi->mb.e_mbd; int i; @@ -643,6 +659,11 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) update_mbintra_mode_probs(cpi); +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + vp8_write_mvprobs_hp(cpi); + else +#endif vp8_write_mvprobs(cpi); mb_row = 0; @@ -806,6 +827,11 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) active_section = 5; #endif +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + write_mv_hp(w, &mi->mv.as_mv, &best_mv, mvc_hp); + else +#endif write_mv(w, &mi->mv.as_mv, &best_mv, mvc); if (cpi->common.dual_pred_mode == HYBRID_PREDICTION) @@ -824,7 +850,14 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) &n1, &n2, &best_mv, ct, second_rf, cpi->common.ref_frame_sign_bias); - write_mv(w, &mi->second_mv.as_mv, &best_mv, mvc); +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + write_mv_hp(w, &mi->second_mv.as_mv, + &best_mv, mvc_hp); + else +#endif + write_mv(w, &mi->second_mv.as_mv, &best_mv, + mvc); } break; @@ -867,7 +900,15 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) #ifdef ENTROPY_STATS active_section = 11; #endif - write_mv(w, &blockmv.as_mv, &best_mv, (const MV_CONTEXT *) mvc); +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + write_mv_hp(w, &blockmv.as_mv, &best_mv, + (const MV_CONTEXT_HP *) + mvc_hp); + else +#endif + write_mv(w, &blockmv.as_mv, &best_mv, + (const MV_CONTEXT *) mvc); } } while (++j < cpi->mb.partition_info->count); @@ -908,6 +949,9 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) VP8_COMMON *const pc = & cpi->common; vp8_writer *const w = & cpi->bc; const MV_CONTEXT *mvc = pc->fc.mvc; +#if CONFIG_HIGH_PRECISION_MV + const MV_CONTEXT_HP *mvc_hp = pc->fc.mvc_hp; +#endif MACROBLOCKD *xd = &cpi->mb.e_mbd; int i; @@ -992,6 +1036,11 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) update_mbintra_mode_probs(cpi); +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + vp8_write_mvprobs_hp(cpi); + else +#endif vp8_write_mvprobs(cpi); while (++mb_row < pc->mb_rows) @@ -1058,9 +1107,9 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) if (rf == INTRA_FRAME) { - #ifdef ENTROPY_STATS +#ifdef ENTROPY_STATS active_section = 6; - #endif +#endif if ( !segfeature_active( xd, segment_id, SEG_LVL_MODE ) ) write_ymode(w, mode, pc->fc.ymode_prob); @@ -1131,12 +1180,18 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) switch (mode) /* new, split require MVs */ { case NEWMV: - #ifdef ENTROPY_STATS +#ifdef ENTROPY_STATS active_section = 5; - #endif +#endif +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + write_mv_hp(w, &mi->mv.as_mv, &best_mv, mvc_hp); + else +#endif write_mv(w, &mi->mv.as_mv, &best_mv, mvc); + if (cpi->common.dual_pred_mode == HYBRID_PREDICTION) { vp8_write(w, mi->second_ref_frame != INTRA_FRAME, @@ -1152,6 +1207,11 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) &n1, &n2, &best_mv, ct, second_rf, cpi->common.ref_frame_sign_bias); +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + write_mv_hp(w, &mi->second_mv.as_mv, &best_mv, mvc_hp); + else +#endif write_mv(w, &mi->second_mv.as_mv, &best_mv, mvc); } break; @@ -1159,9 +1219,9 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) { int j = 0; - #ifdef MODE_STATS +#ifdef MODE_STATS ++count_mb_seg [mi->partitioning]; - #endif +#endif write_split(w, mi->partitioning); @@ -1176,13 +1236,13 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) blockmode = cpi->mb.partition_info->bmi[j].mode; blockmv = cpi->mb.partition_info->bmi[j].mv; - #if CONFIG_DEBUG +#if CONFIG_DEBUG while (j != L[++k]) if (k >= 16) assert(0); - #else +#else while (j != L[++k]); - #endif +#endif leftmv.as_int = left_block_mv(m, k); abovemv.as_int = above_block_mv(m, k, mis); mv_contz = vp8_mv_cont(&leftmv, &abovemv); @@ -1191,9 +1251,14 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) if (blockmode == NEW4X4) { - #ifdef ENTROPY_STATS +#ifdef ENTROPY_STATS active_section = 11; - #endif +#endif +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + write_mv_hp(w, &blockmv.as_mv, &best_mv, (const MV_CONTEXT_HP *) mvc_hp); + else +#endif write_mv(w, &blockmv.as_mv, &best_mv, (const MV_CONTEXT *) mvc); } } diff --git a/vp8/encoder/block.h b/vp8/encoder/block.h index e197490529029dfbd55275744189fa439386512a..54f38590c6cd046157d78c2b84c629b9f9d10f8d 100644 --- a/vp8/encoder/block.h +++ b/vp8/encoder/block.h @@ -97,6 +97,12 @@ typedef struct int *mvcost[2]; int mvsadcosts[2][MVfpvals+1]; int *mvsadcost[2]; +#if CONFIG_HIGH_PRECISION_MV + int mvcosts_hp[2][MVvals_hp+1]; + int *mvcost_hp[2]; + int mvsadcosts_hp[2][MVfpvals_hp+1]; + int *mvsadcost_hp[2]; +#endif int mbmode_cost[2][MB_MODE_COUNT]; int intra_uv_mode_cost[2][MB_MODE_COUNT]; unsigned int bmode_costs[10][10][10]; @@ -119,6 +125,9 @@ typedef struct unsigned char *active_ptr; MV_CONTEXT *mvc; +#if CONFIG_HIGH_PRECISION_MV + MV_CONTEXT_HP *mvc_hp; +#endif unsigned int token_costs[BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS][MAX_ENTROPY_TOKENS]; diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c index e33e6ce6219b5182fcddfc28f3e6757700c55d6f..6c9c4f0420c7dd267438ad40040e0fdcd2702fcc 100644 --- a/vp8/encoder/encodeframe.c +++ b/vp8/encoder/encodeframe.c @@ -605,7 +605,7 @@ void encode_sb_row (VP8_COMP *cpi, xd->mode_info_stride + col_delta[(i+1) & 0x3]; int offset_unextended = row_delta[(i+1) & 0x3] * cm->mb_cols + col_delta[(i+1) & 0x3]; - int dy = row_delta[i]; + int dy = row_delta[i]; int dx = col_delta[i]; mb_row += dy; @@ -1108,6 +1108,9 @@ static void encode_frame_internal(VP8_COMP *cpi) xd->prev_mode_info_context = cm->prev_mi; vp8_zero(cpi->MVcount); +#if CONFIG_HIGH_PRECISION_MV + vp8_zero(cpi->MVcount_hp); +#endif vp8_zero(cpi->coef_counts); vp8cx_frame_init_quantizer(cpi); diff --git a/vp8/encoder/encodemv.c b/vp8/encoder/encodemv.c index 4d5d8cb813202ecdf412693516cd4c744b6fbba2..e3ddc2d54c00c2090452da8364c976f9efb8fdd9 100644 --- a/vp8/encoder/encodemv.c +++ b/vp8/encoder/encodemv.c @@ -95,14 +95,17 @@ void vp8_encode_motion_vector(vp8_writer *w, const MV *mv, const MV_CONTEXT *mvc } } #endif - encode_mvcomponent(w, mv->row >> MV_SHIFT, &mvc[0]); - encode_mvcomponent(w, mv->col >> MV_SHIFT, &mvc[1]); + encode_mvcomponent(w, mv->row >> 1, &mvc[0]); + encode_mvcomponent(w, mv->col >> 1, &mvc[1]); #ifdef DEBUG_ENC_MV { int i; - printf("%d: %d %d\n", enc_mvcount++, mv->row, mv->col); - for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[0])->prob[i]); printf("\n"); - for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[1])->prob[i]); printf("\n"); + printf("%d (np): %d %d\n", enc_mvcount++, + (mv->row >> 1)<<1, (mv->col >> 1)<<1); + //for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[0])->prob[i]); + //printf("\n"); + //for (i=0; i<MVPcount;++i) printf(" %d", (&mvc[1])->prob[i]); + //printf("\n"); fflush(stdout); } #endif @@ -410,29 +413,362 @@ void vp8_write_mvprobs(VP8_COMP *cpi) vp8_writer *const w = & cpi->bc; MV_CONTEXT *mvc = cpi->common.fc.mvc; int flags[2] = {0, 0}; +#ifdef ENTROPY_STATS + active_section = 4; +#endif + write_component_probs( + w, &mvc[0], &vp8_default_mv_context[0], &vp8_mv_update_probs[0], cpi->MVcount[0], 0, &flags[0] + ); + write_component_probs( + w, &mvc[1], &vp8_default_mv_context[1], &vp8_mv_update_probs[1], cpi->MVcount[1], 1, &flags[1] + ); + + if (flags[0] || flags[1]) + vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) cpi->common.fc.mvc, flags); + +#ifdef ENTROPY_STATS + active_section = 5; +#endif +} + +#if CONFIG_HIGH_PRECISION_MV + +static void encode_mvcomponent_hp( + vp8_writer *const w, + const int v, + const struct mv_context_hp *mvc +) +{ + const vp8_prob *p = mvc->prob; + const int x = v < 0 ? -v : v; + + if (x < mvnum_short_hp) // Small + { + vp8_write(w, 0, p [mvpis_short_hp]); + vp8_treed_write(w, vp8_small_mvtree_hp, p + MVPshort_hp, x, + mvnum_short_bits_hp); + if (!x) + return; // no sign bit + } + else // Large + { + int i = 0; + + vp8_write(w, 1, p [mvpis_short_hp]); + + do + vp8_write(w, (x >> i) & 1, p [MVPbits_hp + i]); + + while (++i < mvnum_short_bits_hp); + + i = mvlong_width_hp - 1; /* Skip bit 3, which is sometimes implicit */ + + do + vp8_write(w, (x >> i) & 1, p [MVPbits_hp + i]); + + while (--i > mvnum_short_bits_hp); + + if (x & ~((2<<mvnum_short_bits_hp)-1)) + vp8_write(w, (x >> mvnum_short_bits_hp) & 1, + p [MVPbits_hp + mvnum_short_bits_hp]); + } + + vp8_write(w, v < 0, p [MVPsign_hp]); +} +#if 0 +static int max_mv_r = 0; +static int max_mv_c = 0; +#endif +void vp8_encode_motion_vector_hp(vp8_writer *w, const MV *mv, + const MV_CONTEXT_HP *mvc) +{ + +#if 0 + { + if (abs(mv->row >> 1) > max_mv_r) + { + FILE *f = fopen("maxmv.stt", "a"); + max_mv_r = abs(mv->row >> 1); + fprintf(f, "New Mv Row Max %6d\n", (mv->row >> 1)); + + if ((abs(mv->row) / 2) != max_mv_r) + fprintf(f, "MV Row conversion error %6d\n", abs(mv->row) / 2); + + fclose(f); + } + + if (abs(mv->col >> 1) > max_mv_c) + { + FILE *f = fopen("maxmv.stt", "a"); + fprintf(f, "New Mv Col Max %6d\n", (mv->col >> 1)); + max_mv_c = abs(mv->col >> 1); + fclose(f); + } + } +#endif + encode_mvcomponent_hp(w, mv->row, &mvc[0]); + encode_mvcomponent_hp(w, mv->col, &mvc[1]); #ifdef DEBUG_ENC_MV { int i; - printf("Writing probs\n"); - for (i=0; i<MVPcount;++i) printf(" %d", vp8_default_mv_context[0].prob[i]); printf("\n"); - for (i=0; i<MVPcount;++i) printf(" %d", vp8_default_mv_context[1].prob[i]); printf("\n"); + printf("%d (hp): %d %d\n", enc_mvcount++, mv->row, mv->col); + //for (i=0; i<MVPcount_hp;++i) printf(" %d", (&mvc[0])->prob[i]); + //printf("\n"); + //for (i=0; i<MVPcount_hp;++i) printf(" %d", (&mvc[1])->prob[i]); + //printf("\n"); fflush(stdout); } #endif +} + + +static unsigned int cost_mvcomponent_hp(const int v, + const struct mv_context_hp *mvc) +{ + const vp8_prob *p = mvc->prob; + const int x = v; //v<0? -v:v; + unsigned int cost; + + if (x < mvnum_short_hp) + { + cost = vp8_cost_zero(p [mvpis_short_hp]) + + vp8_treed_cost(vp8_small_mvtree_hp, p + MVPshort_hp, x, + mvnum_short_bits_hp); + + if (!x) + return cost; + } + else + { + int i = 0; + cost = vp8_cost_one(p [mvpis_short_hp]); + + do + cost += vp8_cost_bit(p [MVPbits_hp + i], (x >> i) & 1); + + while (++i < mvnum_short_bits_hp); + + i = mvlong_width_hp - 1; /* Skip bit 3, which is sometimes implicit */ + + do + cost += vp8_cost_bit(p [MVPbits_hp + i], (x >> i) & 1); + + while (--i > mvnum_short_bits_hp); + + if (x & ~((2<<mvnum_short_bits_hp)-1)) + cost += vp8_cost_bit(p [MVPbits_hp + mvnum_short_bits_hp], + (x >> mvnum_short_bits_hp) & 1); + } + + return cost; // + vp8_cost_bit( p [MVPsign], v < 0); +} + +void vp8_build_component_cost_table_hp(int *mvcost[2], + const MV_CONTEXT_HP *mvc, + int mvc_flag[2]) +{ + int i = 1; //-mv_max; + unsigned int cost0 = 0; + unsigned int cost1 = 0; + + vp8_clear_system_state(); + + i = 1; + + if (mvc_flag[0]) + { + mvcost [0] [0] = cost_mvcomponent_hp(0, &mvc[0]); + + do + { + //mvcost [0] [i] = cost_mvcomponent( i, &mvc[0]); + cost0 = cost_mvcomponent_hp(i, &mvc[0]); + + mvcost [0] [i] = cost0 + vp8_cost_zero(mvc[0].prob[MVPsign_hp]); + mvcost [0] [-i] = cost0 + vp8_cost_one(mvc[0].prob[MVPsign_hp]); + } + while (++i <= mv_max_hp); + } + + i = 1; + + if (mvc_flag[1]) + { + mvcost [1] [0] = cost_mvcomponent_hp(0, &mvc[1]); + + do + { + //mvcost [1] [i] = cost_mvcomponent( i, mvc[1]); + cost1 = cost_mvcomponent_hp(i, &mvc[1]); + + mvcost [1] [i] = cost1 + vp8_cost_zero(mvc[1].prob[MVPsign_hp]); + mvcost [1] [-i] = cost1 + vp8_cost_one(mvc[1].prob[MVPsign_hp]); + } + while (++i <= mv_max_hp); + } +} + + +static void write_component_probs_hp( + vp8_writer *const w, + struct mv_context_hp *cur_mvc, + const struct mv_context_hp *default_mvc_, + const struct mv_context_hp *update_mvc, + const unsigned int events [MVvals_hp], + unsigned int rc, + int *updated +) +{ + vp8_prob *Pcur = cur_mvc->prob; + const vp8_prob *default_mvc = default_mvc_->prob; + const vp8_prob *Pupdate = update_mvc->prob; + unsigned int is_short_ct[2], sign_ct[2]; + + unsigned int bit_ct [mvlong_width_hp] [2]; + + unsigned int short_ct [mvnum_short_hp]; + unsigned int short_bct [mvnum_short_hp-1] [2]; + + vp8_prob Pnew [MVPcount_hp]; + + (void) rc; + vp8_copy_array(Pnew, default_mvc, MVPcount_hp); + + vp8_zero(is_short_ct) + vp8_zero(sign_ct) + vp8_zero(bit_ct) + vp8_zero(short_ct) + vp8_zero(short_bct) + + + //j=0 + { + const int c = events [mv_max]; + + is_short_ct [0] += c; // Short vector + short_ct [0] += c; // Magnitude distribution + } + + //j: 1 ~ mv_max (1023) + { + int j = 1; + + do + { + const int c1 = events [mv_max_hp + j]; //positive + const int c2 = events [mv_max_hp - j]; //negative + const int c = c1 + c2; + int a = j; + + sign_ct [0] += c1; + sign_ct [1] += c2; + + if (a < mvnum_short_hp) + { + is_short_ct [0] += c; // Short vector + short_ct [a] += c; // Magnitude distribution + } + else + { + int k = mvlong_width_hp - 1; + is_short_ct [1] += c; // Long vector + + /* bit 3 not always encoded. */ + do + bit_ct [k] [(a >> k) & 1] += c; + + while (--k >= 0); + } + } + while (++j <= mv_max_hp); + } + + calc_prob(Pnew + mvpis_short_hp, is_short_ct); + + calc_prob(Pnew + MVPsign_hp, sign_ct); + + { + vp8_prob p [mvnum_short_hp - 1]; /* actually only need branch ct */ + int j = 0; + + vp8_tree_probs_from_distribution( + mvnum_short_hp, vp8_small_mvencodings_hp, vp8_small_mvtree_hp, + p, short_bct, short_ct, + 256, 1 + ); + + do + calc_prob(Pnew + MVPshort_hp + j, short_bct[j]); + + while (++j < mvnum_short_hp - 1); + } + + { + int j = 0; + + do + calc_prob(Pnew + MVPbits_hp + j, bit_ct[j]); + + while (++j < mvlong_width_hp); + } + + update(w, is_short_ct, Pcur + mvpis_short_hp, Pnew[mvpis_short_hp], + *Pupdate++, updated); + + update(w, sign_ct, Pcur + MVPsign_hp, Pnew[MVPsign_hp], *Pupdate++, + updated); + + { + const vp8_prob *const new_p = Pnew + MVPshort_hp; + vp8_prob *const cur_p = Pcur + MVPshort_hp; + + int j = 0; + + do + + update(w, short_bct[j], cur_p + j, new_p[j], *Pupdate++, updated); + + while (++j < mvnum_short_hp - 1); + } + + { + const vp8_prob *const new_p = Pnew + MVPbits_hp; + vp8_prob *const cur_p = Pcur + MVPbits_hp; + + int j = 0; + + do + + update(w, bit_ct[j], cur_p + j, new_p[j], *Pupdate++, updated); + + while (++j < mvlong_width_hp); + } +} + +void vp8_write_mvprobs_hp(VP8_COMP *cpi) +{ + vp8_writer *const w = & cpi->bc; + MV_CONTEXT_HP *mvc = cpi->common.fc.mvc_hp; + int flags[2] = {0, 0}; #ifdef ENTROPY_STATS active_section = 4; #endif - write_component_probs( - w, &mvc[0], &vp8_default_mv_context[0], &vp8_mv_update_probs[0], cpi->MVcount[0], 0, &flags[0] + write_component_probs_hp( + w, &mvc[0], &vp8_default_mv_context_hp[0], &vp8_mv_update_probs_hp[0], + cpi->MVcount_hp[0], 0, &flags[0] ); - write_component_probs( - w, &mvc[1], &vp8_default_mv_context[1], &vp8_mv_update_probs[1], cpi->MVcount[1], 1, &flags[1] + write_component_probs_hp( + w, &mvc[1], &vp8_default_mv_context_hp[1], &vp8_mv_update_probs_hp[1], + cpi->MVcount_hp[1], 1, &flags[1] ); if (flags[0] || flags[1]) - vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) cpi->common.fc.mvc, flags); + vp8_build_component_cost_table_hp(cpi->mb.mvcost_hp, + (const MV_CONTEXT_HP *) + cpi->common.fc.mvc_hp, flags); #ifdef ENTROPY_STATS active_section = 5; #endif } +#endif /* CONFIG_HIGH_PRECISION_MV */ diff --git a/vp8/encoder/encodemv.h b/vp8/encoder/encodemv.h index a6116c133d01a6dc36b4eb3046d48f2f4d8eb9bf..09b0935cbf493f272c0c876bcf19fb4dbed1e34b 100644 --- a/vp8/encoder/encodemv.h +++ b/vp8/encoder/encodemv.h @@ -17,5 +17,10 @@ void vp8_write_mvprobs(VP8_COMP *); void vp8_encode_motion_vector(vp8_writer *, const MV *, const MV_CONTEXT *); void vp8_build_component_cost_table(int *mvcost[2], const MV_CONTEXT *mvc, int mvc_flag[2]); +#if CONFIG_HIGH_PRECISION_MV +void vp8_write_mvprobs_hp(VP8_COMP *); +void vp8_encode_motion_vector_hp(vp8_writer *, const MV *, const MV_CONTEXT_HP *); +void vp8_build_component_cost_table_hp(int *mvcost[2], const MV_CONTEXT_HP *mvc, int mvc_flag[2]); +#endif /* CONFIG_HIGH_PRECISION_MV */ #endif diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c index 7d9c386655d68a01a42da9958a5bf9deca9a61b7..9cf875c4c7a6628b2a61e34c351518e9337f6af9 100644 --- a/vp8/encoder/firstpass.c +++ b/vp8/encoder/firstpass.c @@ -420,7 +420,12 @@ static void first_pass_motion_search(VP8_COMP *cpi, MACROBLOCK *x, ref_mv_full.as_mv.row = ref_mv->as_mv.row>>3; tmp_err = cpi->diamond_search_sad(x, b, d, &ref_mv_full, &tmp_mv, step_param, x->sadperbit16, &num00, &v_fn_ptr, - x->mvcost, ref_mv); +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost, +#else + x->mvcost, +#endif + ref_mv); if ( tmp_err < INT_MAX-new_mv_mode_penalty ) tmp_err += new_mv_mode_penalty; @@ -445,7 +450,12 @@ static void first_pass_motion_search(VP8_COMP *cpi, MACROBLOCK *x, { tmp_err = cpi->diamond_search_sad(x, b, d, &ref_mv_full, &tmp_mv, step_param + n, x->sadperbit16, - &num00, &v_fn_ptr, x->mvcost, + &num00, &v_fn_ptr, +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost, +#else + x->mvcost, +#endif ref_mv); if ( tmp_err < INT_MAX-new_mv_mode_penalty ) tmp_err += new_mv_mode_penalty; @@ -520,6 +530,10 @@ void vp8_first_pass(VP8_COMP *cpi) vp8_initialize_rd_consts(cpi, cm->base_qindex + cm->y1dc_delta_q); vpx_memcpy(cm->fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context)); vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) cm->fc.mvc, flag); +#if CONFIG_HIGH_PRECISION_MV + vpx_memcpy(cm->fc.mvc_hp, vp8_default_mv_context_hp, sizeof(vp8_default_mv_context_hp)); + vp8_build_component_cost_table_hp(cpi->mb.mvcost_hp, (const MV_CONTEXT_HP *) cm->fc.mvc_hp, flag); +#endif } // for each macroblock row in image diff --git a/vp8/encoder/mbgraph.c b/vp8/encoder/mbgraph.c index e0fed4a4741ff52f65d270c36839ae358d860bcc..3779f0622de0c7b29428f4ce7611dece470d2375 100644 --- a/vp8/encoder/mbgraph.c +++ b/vp8/encoder/mbgraph.c @@ -35,6 +35,11 @@ static unsigned int do_16x16_motion_iteration static int dummy_cost[2*mv_max+1]; int *mvcost[2] = { &dummy_cost[mv_max+1], &dummy_cost[mv_max+1] }; int *mvsadcost[2] = { &dummy_cost[mv_max+1], &dummy_cost[mv_max+1] }; +#if CONFIG_HIGH_PRECISION_MV + static int dummy_cost_hp[2*mv_max_hp+1]; + int *mvcost_hp[2] = { &dummy_cost_hp[mv_max_hp+1], &dummy_cost[mv_max_hp+1] }; + int *mvsadcost_hp[2] = { &dummy_cost_hp[mv_max_hp+1], &dummy_cost[mv_max_hp+1] }; +#endif int col_min = (ref_mv->as_mv.col>>3) - MAX_FULL_PEL_VAL + ((ref_mv->as_mv.col & 7)?1:0); int row_min = (ref_mv->as_mv.row>>3) - MAX_FULL_PEL_VAL + ((ref_mv->as_mv.row & 7)?1:0); int col_max = (ref_mv->as_mv.col>>3) + MAX_FULL_PEL_VAL; @@ -76,7 +81,12 @@ static unsigned int do_16x16_motion_iteration step_param, x->errorperbit, &v_fn_ptr, - mvsadcost, mvcost, ref_mv); +#if CONFIG_HIGH_PRECISION_MV + xd->allow_high_precision_mv?mvsadcost_hp:mvsadcost, xd->allow_high_precision_mv?mvcost_hp:mvcost, +#else + mvsadcost, mvcost, +#endif + ref_mv); // Try sub-pixel MC //if (bestsme > error_thresh && bestsme < INT_MAX) @@ -86,7 +96,12 @@ static unsigned int do_16x16_motion_iteration best_err = cpi->find_fractional_mv_step(x, b, d, dst_mv, ref_mv, x->errorperbit, &v_fn_ptr, - mvcost, &distortion, &sse); +#if CONFIG_HIGH_PRECISION_MV + xd->allow_high_precision_mv?mvcost_hp:mvcost, +#else + mvcost, +#endif + &distortion, &sse); } vp8_set_mbmode_and_mvs(x, NEWMV, dst_mv); diff --git a/vp8/encoder/mcomp.c b/vp8/encoder/mcomp.c index 093ac3354c6d7d29756263ca235c8c31ef5d93e6..9f522279fcbad0ead67a6e630e021170012f3561 100644 --- a/vp8/encoder/mcomp.c +++ b/vp8/encoder/mcomp.c @@ -28,15 +28,35 @@ int vp8_mv_bit_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight) // over state the cost of vectors. In addition coding a new vector can have a knock on effect on the // cost of subsequent vectors and the quality of prediction from NEAR and NEAREST for subsequent blocks. // The "Weight" parameter allows, to a limited extent, for some account to be taken of these factors. - return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> MV_SHIFT] + mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> MV_SHIFT]) * Weight) >> 7; + return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> 1] + mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> 1]) * Weight) >> 7; } +#if CONFIG_HIGH_PRECISION_MV +int vp8_mv_bit_cost_hp(int_mv *mv, int_mv *ref, int *mvcost[2], int Weight) +{ + // MV costing is based on the distribution of vectors in the previous frame and as such will tend to + // over state the cost of vectors. In addition coding a new vector can have a knock on effect on the + // cost of subsequent vectors and the quality of prediction from NEAR and NEAREST for subsequent blocks. + // The "Weight" parameter allows, to a limited extent, for some account to be taken of these factors. + return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row)] + mvcost[1][(mv->as_mv.col - ref->as_mv.col)]) * Weight) >> 7; +} +#endif +#if CONFIG_HIGH_PRECISION_MV +static int mv_err_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int error_per_bit, int ishp) +{ + return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> (ishp==0)] + + mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> (ishp==0)]) + * error_per_bit + 128) >> 8; +} +#else static int mv_err_cost(int_mv *mv, int_mv *ref, int *mvcost[2], int error_per_bit) { - return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> MV_SHIFT] + - mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> MV_SHIFT]) + return ((mvcost[0][(mv->as_mv.row - ref->as_mv.row) >> 1] + + mvcost[1][(mv->as_mv.col - ref->as_mv.col) >> 1]) * error_per_bit + 128) >> 8; } +#endif + static int mvsad_err_cost(int_mv *mv, int_mv *ref, int *mvsadcost[2], int error_per_bit) { @@ -46,6 +66,7 @@ static int mvsad_err_cost(int_mv *mv, int_mv *ref, int *mvsadcost[2], int error_ * error_per_bit + 128) >> 8; } + void vp8_init_dsmotion_compensation(MACROBLOCK *x, int stride) { int Len; @@ -176,31 +197,30 @@ void vp8_init3smotion_compensation(MACROBLOCK *x, int stride) * could reduce the area. */ -#if CONFIG_HIGH_PRECISION_MV - -#define PRE(r,c) (y + (((r)>>3) * y_stride + ((c)>>3) -(offset))) // pointer to predictor base of a motionvector -#if CONFIG_SIXTEENTH_SUBPEL_UV -#define SP(x) (((x)&7)<<1) // convert motion vector component to offset for svf calc -#else -#define SP(x) ((x)&7) // convert motion vector component to offset for svf calc -#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */ - -#else /* CONFIG_HIGH_PRECISION_MV */ - #define PRE(r,c) (y + (((r)>>2) * y_stride + ((c)>>2) -(offset))) // pointer to predictor base of a motionvector #if CONFIG_SIXTEENTH_SUBPEL_UV #define SP(x) (((x)&3)<<2) // convert motion vector component to offset for svf calc #else #define SP(x) (((x)&3)<<1) // convert motion vector component to offset for svf calc #endif /* CONFIG_SIXTEENTH_SUBPEL_UV */ - -#endif /* CONFIG_HIGH_PRECISION_MV */ - #define MVC(r,c) (((mvcost[0][(r)-rr] + mvcost[1][(c)-rc]) * error_per_bit + 128 )>>8 ) // estimated cost of a motion vector (r,c) #define DIST(r,c) vfp->svf( PRE(r,c), y_stride, SP(c),SP(r), z,b->src_stride,&sse) // returns subpixel variance error function. -#define IFMVCV(r,c,s,e) if ( c >= minc && c <= maxc && r >= minr && r <= maxr) s else e; #define ERR(r,c) (MVC(r,c)+DIST(r,c)) // returns distortion + motion vector cost +#define IFMVCV(r,c,s,e) if ( c >= minc && c <= maxc && r >= minr && r <= maxr) s else e; + +#if CONFIG_HIGH_PRECISION_MV +#define PREHP(r,c) (y + (((r)>>3) * y_stride + ((c)>>3) -(offset))) // pointer to predictor base of a motionvector +#if CONFIG_SIXTEENTH_SUBPEL_UV +#define SPHP(x) (((x)&7)<<1) // convert motion vector component to offset for svf calc +#else /* CONFIG_SIXTEENTH_SUBPEL_UV */ +#define SPHP(x) ((x)&7) // convert motion vector component to offset for svf calc +#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */ +#define DISTHP(r,c) vfp->svf( PREHP(r,c), y_stride, SPHP(c),SPHP(r), z,b->src_stride,&sse) // returns subpixel variance error function. +#define ERRHP(r,c) (MVC(r,c)+DISTHP(r,c)) // returns distortion + motion vector cost +#define CHECK_BETTER(v,r,c) IFMVCV(r,c,{thismse = ((xd->allow_high_precision_mv)?DISTHP(r,c):DIST(r,c)); if((v = (MVC(r,c)+thismse)) < besterr) { besterr = v; br=r; bc=c; *distortion = thismse; *sse1 = sse; }}, v=INT_MAX;)// checks if (r,c) has better score than previous best +#else #define CHECK_BETTER(v,r,c) IFMVCV(r,c,{thismse = DIST(r,c); if((v = (MVC(r,c)+thismse)) < besterr) { besterr = v; br=r; bc=c; *distortion = thismse; *sse1 = sse; }}, v=INT_MAX;)// checks if (r,c) has better score than previous best +#endif /* CONFIG_HIGH_PRECISION_MV */ #define MIN(x,y) (((x)<(y))?(x):(y)) #define MAX(x,y) (((x)>(y))?(x):(y)) @@ -213,17 +233,10 @@ int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d, unsigned int *sse1) { unsigned char *z = (*(b->base_src) + b->src); + MACROBLOCKD *xd = &x->e_mbd; -#if CONFIG_HIGH_PRECISION_MV - int rr = ref_mv->as_mv.row, rc = ref_mv->as_mv.col; - int br = bestmv->as_mv.row << 3, bc = bestmv->as_mv.col << 3; - int hstep = 4; -#else - int rr = ref_mv->as_mv.row >> 1, rc = ref_mv->as_mv.col >> 1; - int br = bestmv->as_mv.row << 2, bc = bestmv->as_mv.col << 2; - int hstep = 2; -#endif - int tr = br, tc = bc; + int rr, rc, br, bc, hstep; + int tr, tc; unsigned int besterr = INT_MAX; unsigned int left, right, up, down, diag; unsigned int sse; @@ -234,24 +247,37 @@ int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d, unsigned int eighthiters = 4; #endif int thismse; + int maxc, minc, maxr, minr; + int y_stride; + int offset; #if CONFIG_HIGH_PRECISION_MV - int minc = MAX(x->mv_col_min << 3, (ref_mv->as_mv.col) - ((1 << mvlong_width) - 1)); - int maxc = MIN(x->mv_col_max << 3, (ref_mv->as_mv.col) + ((1 << mvlong_width) - 1)); - int minr = MAX(x->mv_row_min << 3, (ref_mv->as_mv.row) - ((1 << mvlong_width) - 1)); - int maxr = MIN(x->mv_row_max << 3, (ref_mv->as_mv.row) + ((1 << mvlong_width) - 1)); -#else - int minc = MAX(x->mv_col_min << 2, (ref_mv->as_mv.col >> 1) - ((1 << mvlong_width) - 1)); - int maxc = MIN(x->mv_col_max << 2, (ref_mv->as_mv.col >> 1) + ((1 << mvlong_width) - 1)); - int minr = MAX(x->mv_row_min << 2, (ref_mv->as_mv.row >> 1) - ((1 << mvlong_width) - 1)); - int maxr = MIN(x->mv_row_max << 2, (ref_mv->as_mv.row >> 1) + ((1 << mvlong_width) - 1)); + if (xd->allow_high_precision_mv) + { + rr = ref_mv->as_mv.row; rc = ref_mv->as_mv.col; + br = bestmv->as_mv.row << 3; bc = bestmv->as_mv.col << 3; + hstep = 4; + minc = MAX(x->mv_col_min << 3, (ref_mv->as_mv.col) - ((1 << mvlong_width) - 1)); + maxc = MIN(x->mv_col_max << 3, (ref_mv->as_mv.col) + ((1 << mvlong_width) - 1)); + minr = MAX(x->mv_row_min << 3, (ref_mv->as_mv.row) - ((1 << mvlong_width) - 1)); + maxr = MIN(x->mv_row_max << 3, (ref_mv->as_mv.row) + ((1 << mvlong_width) - 1)); + } + else #endif + { + rr = ref_mv->as_mv.row >> 1; rc = ref_mv->as_mv.col >> 1; + br = bestmv->as_mv.row << 2; bc = bestmv->as_mv.col << 2; + hstep = 2; + minc = MAX(x->mv_col_min << 2, (ref_mv->as_mv.col >> 1) - ((1 << mvlong_width) - 1)); + maxc = MIN(x->mv_col_max << 2, (ref_mv->as_mv.col >> 1) + ((1 << mvlong_width) - 1)); + minr = MAX(x->mv_row_min << 2, (ref_mv->as_mv.row >> 1) - ((1 << mvlong_width) - 1)); + maxr = MIN(x->mv_row_max << 2, (ref_mv->as_mv.row >> 1) + ((1 << mvlong_width) - 1)); + } - int y_stride; - int offset; + tr = br; + tc = bc; #if ARCH_X86 || ARCH_X86_64 - MACROBLOCKD *xd = &x->e_mbd; unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col; unsigned char *y; int buf_r1, buf_r2, buf_c1, buf_c2; @@ -280,7 +306,11 @@ int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d, // calculate central point error besterr = vfp->vf(y, y_stride, z, b->src_stride, sse1); *distortion = besterr; +#if CONFIG_HIGH_PRECISION_MV + besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else besterr += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit); +#endif // TODO: Each subsequent iteration checks at least one point in common with the last iteration could be 2 ( if diag selected) while (--halfiters) @@ -390,12 +420,19 @@ int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d, tc = bc; } } - bestmv->as_mv.row = br; - bestmv->as_mv.col = bc; -#else - bestmv->as_mv.row = br << 1; - bestmv->as_mv.col = bc << 1; +#endif +#if CONFIG_HIGH_PRECISION_MV + if (x->e_mbd.allow_high_precision_mv) + { + bestmv->as_mv.row = br; + bestmv->as_mv.col = bc; + } + else #endif /* CONFIG_HIGH_PRECISION_MV */ + { + bestmv->as_mv.row = br << 1; + bestmv->as_mv.col = bc << 1; + } if ((abs(bestmv->as_mv.col - ref_mv->as_mv.col) > (MAX_FULL_PEL_VAL<<3)) || (abs(bestmv->as_mv.row - ref_mv->as_mv.row) > (MAX_FULL_PEL_VAL<<3))) @@ -413,11 +450,18 @@ int vp8_find_best_sub_pixel_step_iteratively(MACROBLOCK *x, BLOCK *b, BLOCKD *d, #undef MIN #undef MAX +#if CONFIG_HIGH_PRECISION_MV +#undef PREHP +#undef DPHP +#undef DISTHP +#undef ERRHP +#endif + #if CONFIG_SIXTEENTH_SUBPEL_UV #define SP(x) (((x)&7)<<1) // convert motion vector component to offset for svf calc #else #define SP(x) ((x)&7) // convert motion vector component to offset for svf calc -#endif /* CONFIG_HIGH_PRECISION_MV */ +#endif /* CONFIG_SIXTEENTH_SUBPEL_UV */ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *bestmv, int_mv *ref_mv, int error_per_bit, @@ -438,9 +482,9 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int whichdir ; int thismse; int y_stride; + MACROBLOCKD *xd = &x->e_mbd; #if ARCH_X86 || ARCH_X86_64 - MACROBLOCKD *xd = &x->e_mbd; unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col; unsigned char *y; @@ -464,13 +508,21 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, // calculate central point error bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1); *distortion = bestmse; +#if CONFIG_HIGH_PRECISION_MV + bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit); +#endif // go left then right and check error this_mv.as_mv.row = startmv.as_mv.row; this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4); thismse = vfp->svf_halfpix_h(y - 1, y_stride, z, b->src_stride, &sse); +#if CONFIG_HIGH_PRECISION_MV + left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (left < bestmse) { @@ -482,7 +534,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, this_mv.as_mv.col += 8; thismse = vfp->svf_halfpix_h(y, y_stride, z, b->src_stride, &sse); +#if CONFIG_HIGH_PRECISION_MV + right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (right < bestmse) { @@ -496,7 +552,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, this_mv.as_mv.col = startmv.as_mv.col; this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4); thismse = vfp->svf_halfpix_v(y - y_stride, y_stride, z, b->src_stride, &sse); +#if CONFIG_HIGH_PRECISION_MV + up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (up < bestmse) { @@ -508,7 +568,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, this_mv.as_mv.row += 8; thismse = vfp->svf_halfpix_v(y, y_stride, z, b->src_stride, &sse); +#if CONFIG_HIGH_PRECISION_MV + down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (down < bestmse) { @@ -550,7 +614,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, break; } +#if CONFIG_HIGH_PRECISION_MV + diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (diag < bestmse) { @@ -598,7 +666,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, thismse = vfp->svf(y - 1, y_stride, SP(6), SP(this_mv.as_mv.row), z, b->src_stride, &sse); } +#if CONFIG_HIGH_PRECISION_MV + left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (left < bestmse) { @@ -610,7 +682,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, this_mv.as_mv.col += 4; thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse); +#if CONFIG_HIGH_PRECISION_MV + right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (right < bestmse) { @@ -634,7 +710,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(6), z, b->src_stride, &sse); } +#if CONFIG_HIGH_PRECISION_MV + up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (up < bestmse) { @@ -646,7 +726,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, this_mv.as_mv.row += 4; thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse); +#if CONFIG_HIGH_PRECISION_MV + down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (down < bestmse) { @@ -737,7 +821,11 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, break; } +#if CONFIG_HIGH_PRECISION_MV + diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (diag < bestmse) { @@ -780,7 +868,7 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, thismse = vfp->svf(y - 1, y_stride, SP(7), SP(this_mv.as_mv.row), z, b->src_stride, &sse); } - left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); + left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); if (left < bestmse) { @@ -792,7 +880,7 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, this_mv.as_mv.col += 2; thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse); - right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); + right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); if (right < bestmse) { @@ -816,7 +904,7 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, thismse = vfp->svf(y - y_stride, y_stride, SP(this_mv.as_mv.col), SP(7), z, b->src_stride, &sse); } - up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); + up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); if (up < bestmse) { @@ -828,7 +916,7 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, this_mv.as_mv.row += 2; thismse = vfp->svf(y, y_stride, SP(this_mv.as_mv.col), SP(this_mv.as_mv.row), z, b->src_stride, &sse); - down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); + down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); if (down < bestmse) { @@ -919,7 +1007,7 @@ int vp8_find_best_sub_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, break; } - diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); + diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); if (diag < bestmse) { @@ -952,9 +1040,9 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int whichdir ; int thismse; int y_stride; + MACROBLOCKD *xd = &x->e_mbd; #if ARCH_X86 || ARCH_X86_64 - MACROBLOCKD *xd = &x->e_mbd; unsigned char *y0 = *(d->base_pre) + d->pre + (bestmv->as_mv.row) * d->pre_stride + bestmv->as_mv.col; unsigned char *y; @@ -975,13 +1063,21 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, // calculate central point error bestmse = vfp->vf(y, y_stride, z, b->src_stride, sse1); *distortion = bestmse; +#if CONFIG_HIGH_PRECISION_MV + bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else bestmse += mv_err_cost(bestmv, ref_mv, mvcost, error_per_bit); +#endif // go left then right and check error this_mv.as_mv.row = startmv.as_mv.row; this_mv.as_mv.col = ((startmv.as_mv.col - 8) | 4); thismse = vfp->svf_halfpix_h(y - 1, y_stride, z, b->src_stride, &sse); +#if CONFIG_HIGH_PRECISION_MV + left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else left = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (left < bestmse) { @@ -993,7 +1089,11 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, this_mv.as_mv.col += 8; thismse = vfp->svf_halfpix_h(y, y_stride, z, b->src_stride, &sse); +#if CONFIG_HIGH_PRECISION_MV + right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else right = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (right < bestmse) { @@ -1007,7 +1107,11 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, this_mv.as_mv.col = startmv.as_mv.col; this_mv.as_mv.row = ((startmv.as_mv.row - 8) | 4); thismse = vfp->svf_halfpix_v(y - y_stride, y_stride, z, b->src_stride, &sse); +#if CONFIG_HIGH_PRECISION_MV + up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else up = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (up < bestmse) { @@ -1019,7 +1123,11 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, this_mv.as_mv.row += 8; thismse = vfp->svf_halfpix_v(y, y_stride, z, b->src_stride, &sse); +#if CONFIG_HIGH_PRECISION_MV + down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else down = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (down < bestmse) { @@ -1058,7 +1166,11 @@ int vp8_find_best_half_pixel_step(MACROBLOCK *x, BLOCK *b, BLOCKD *d, break; } +#if CONFIG_HIGH_PRECISION_MV + diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit, xd->allow_high_precision_mv); +#else diag = thismse + mv_err_cost(&this_mv, ref_mv, mvcost, error_per_bit); +#endif if (diag < bestmse) { @@ -1142,6 +1254,7 @@ int vp8_hex_search int k = -1; int all_in; int best_site = -1; + MACROBLOCKD *xd = &x->e_mbd; int_mv fcenter_mv; fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; @@ -1323,8 +1436,16 @@ int vp8_diamond_search_sad unsigned char *check_here; int thissad; + MACROBLOCKD *xd = &x->e_mbd; int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]}; +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + { + mvsadcost[0] = x->mvsadcost_hp[0]; + mvsadcost[1] = x->mvsadcost_hp[1]; + } +#endif int_mv fcenter_mv; fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; @@ -1403,7 +1524,11 @@ int vp8_diamond_search_sad return INT_MAX; return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad)) +#if CONFIG_HIGH_PRECISION_MV + + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv); +#else + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit); +#endif } int vp8_diamond_search_sadx4 @@ -1444,8 +1569,16 @@ int vp8_diamond_search_sadx4 unsigned char *check_here; unsigned int thissad; + MACROBLOCKD *xd = &x->e_mbd; int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]}; +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + { + mvsadcost[0] = x->mvsadcost_hp[0]; + mvsadcost[1] = x->mvsadcost_hp[1]; + } +#endif int_mv fcenter_mv; fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; @@ -1565,7 +1698,11 @@ int vp8_diamond_search_sadx4 return INT_MAX; return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad)) +#if CONFIG_HIGH_PRECISION_MV + + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv); +#else + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit); +#endif } int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, @@ -1586,6 +1723,7 @@ int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, unsigned char *check_here; int thissad; + MACROBLOCKD *xd = &x->e_mbd; int ref_row = ref_mv->as_mv.row; int ref_col = ref_mv->as_mv.col; @@ -1596,6 +1734,13 @@ int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, int col_max = ref_col + distance; int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]}; +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + { + mvsadcost[0] = x->mvsadcost_hp[0]; + mvsadcost[1] = x->mvsadcost_hp[1]; + } +#endif int_mv fcenter_mv; fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; @@ -1655,7 +1800,11 @@ int vp8_full_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, if (bestsad < INT_MAX) return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad)) +#if CONFIG_HIGH_PRECISION_MV + + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv); +#else + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit); +#endif else return INT_MAX; } @@ -1678,6 +1827,7 @@ int vp8_full_search_sadx3(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, unsigned char *check_here; unsigned int thissad; + MACROBLOCKD *xd = &x->e_mbd; int ref_row = ref_mv->as_mv.row; int ref_col = ref_mv->as_mv.col; @@ -1690,6 +1840,13 @@ int vp8_full_search_sadx3(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, unsigned int sad_array[3]; int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]}; +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + { + mvsadcost[0] = x->mvsadcost_hp[0]; + mvsadcost[1] = x->mvsadcost_hp[1]; + } +#endif int_mv fcenter_mv; fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; @@ -1785,7 +1942,11 @@ int vp8_full_search_sadx3(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, if (bestsad < INT_MAX) return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad)) +#if CONFIG_HIGH_PRECISION_MV + + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv); +#else + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit); +#endif else return INT_MAX; } @@ -1808,6 +1969,7 @@ int vp8_full_search_sadx8(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, unsigned char *check_here; unsigned int thissad; + MACROBLOCKD *xd = &x->e_mbd; int ref_row = ref_mv->as_mv.row; int ref_col = ref_mv->as_mv.col; @@ -1821,6 +1983,13 @@ int vp8_full_search_sadx8(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, unsigned int sad_array[3]; int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]}; +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + { + mvsadcost[0] = x->mvsadcost_hp[0]; + mvsadcost[1] = x->mvsadcost_hp[1]; + } +#endif int_mv fcenter_mv; fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; fcenter_mv.as_mv.col = center_mv->as_mv.col >> 3; @@ -1945,7 +2114,11 @@ int vp8_full_search_sadx8(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, if (bestsad < INT_MAX) return fn_ptr->vf(what, what_stride, bestaddress, in_what_stride, (unsigned int *)(&thissad)) +#if CONFIG_HIGH_PRECISION_MV + + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv); +#else + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit); +#endif else return INT_MAX; } @@ -1968,8 +2141,16 @@ int vp8_refining_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, unsigned int thissad; int_mv this_mv; unsigned int bestsad = INT_MAX; + MACROBLOCKD *xd = &x->e_mbd; int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]}; +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + { + mvsadcost[0] = x->mvsadcost_hp[0]; + mvsadcost[1] = x->mvsadcost_hp[1]; + } +#endif int_mv fcenter_mv; fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; @@ -2022,7 +2203,11 @@ int vp8_refining_search_sad(MACROBLOCK *x, BLOCK *b, BLOCKD *d, int_mv *ref_mv, if (bestsad < INT_MAX) return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad)) +#if CONFIG_HIGH_PRECISION_MV + + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv); +#else + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit); +#endif else return INT_MAX; } @@ -2045,8 +2230,16 @@ int vp8_refining_search_sadx4(MACROBLOCK *x, BLOCK *b, BLOCKD *d, unsigned int thissad; int_mv this_mv; unsigned int bestsad = INT_MAX; + MACROBLOCKD *xd = &x->e_mbd; int *mvsadcost[2] = {x->mvsadcost[0], x->mvsadcost[1]}; +#if CONFIG_HIGH_PRECISION_MV + if (xd->allow_high_precision_mv) + { + mvsadcost[0] = x->mvsadcost_hp[0]; + mvsadcost[1] = x->mvsadcost_hp[1]; + } +#endif int_mv fcenter_mv; fcenter_mv.as_mv.row = center_mv->as_mv.row >> 3; @@ -2135,7 +2328,11 @@ int vp8_refining_search_sadx4(MACROBLOCK *x, BLOCK *b, BLOCKD *d, if (bestsad < INT_MAX) return fn_ptr->vf(what, what_stride, best_address, in_what_stride, (unsigned int *)(&thissad)) +#if CONFIG_HIGH_PRECISION_MV + + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit, xd->allow_high_precision_mv); +#else + mv_err_cost(&this_mv, center_mv, mvcost, x->errorperbit); +#endif else return INT_MAX; } diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 285a8a2a5ca4048522a88b76be0a822e5fb12509..dcae1196faee9a3d693f7a865f91f1f00e872508 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -79,6 +79,14 @@ static void set_default_lf_deltas(VP8_COMP *cpi); extern const int vp8_gf_interval_table[101]; +#if CONFIG_HIGH_PRECISION_MV +#define ALTREF_HIGH_PRECISION_MV 1 /* whether to use high precision mv for altref computation */ +#define HIGH_PRECISION_MV_QTHRESH 200 /* Q threshold for use of high precision mv */ + /* Choose a very high value for now so + * that HIGH_PRECISION is always chosen + */ +#endif + #if CONFIG_INTERNAL_STATS #include "math.h" @@ -1334,7 +1342,7 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf) setup_features(cpi); #if CONFIG_HIGH_PRECISION_MV - cpi->mb.e_mbd.allow_high_precision_mv = 1; // Default mv precision adaptation + cpi->mb.e_mbd.allow_high_precision_mv = 0; // Default mv precision adaptation #endif { @@ -1473,7 +1481,6 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf) cpi->alt_ref_source = NULL; cpi->is_src_frame_alt_ref = 0; - #if 0 // Experimental RD Code cpi->frame_distortion = 0; @@ -1502,6 +1509,26 @@ static void cal_mvsadcosts(int *mvsadcost[2]) while (++i <= mvfp_max); } +#if CONFIG_HIGH_PRECISION_MV +static void cal_mvsadcosts_hp(int *mvsadcost[2]) +{ + int i = 1; + + mvsadcost [0] [0] = 300; + mvsadcost [1] [0] = 300; + + do + { + double z = 256 * (2 * (log2f(8 * i) + .6)); + mvsadcost [0][i] = (int) z; + mvsadcost [1][i] = (int) z; + mvsadcost [0][-i] = (int) z; + mvsadcost [1][-i] = (int) z; + } + while (++i <= mvfp_max_hp); +} +#endif + VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf) { int i; @@ -1673,6 +1700,15 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf) cal_mvsadcosts(cpi->mb.mvsadcost); +#if CONFIG_HIGH_PRECISION_MV + cpi->mb.mvcost_hp[0] = &cpi->mb.mvcosts_hp[0][mv_max_hp+1]; + cpi->mb.mvcost_hp[1] = &cpi->mb.mvcosts_hp[1][mv_max_hp+1]; + cpi->mb.mvsadcost_hp[0] = &cpi->mb.mvsadcosts_hp[0][mvfp_max_hp+1]; + cpi->mb.mvsadcost_hp[1] = &cpi->mb.mvsadcosts_hp[1][mvfp_max_hp+1]; + + cal_mvsadcosts_hp(cpi->mb.mvsadcost_hp); +#endif + for (i = 0; i < KEY_FRAME_CONTEXT; i++) { cpi->prior_key_frame_distance[i] = (int)cpi->output_frame_rate; @@ -2861,9 +2897,6 @@ static void encode_frame_to_data_rate // Reset the loop filter deltas and segmentation map setup_features(cpi); -#if CONFIG_HIGH_PRECISION_MV - xd->allow_high_precision_mv = 1; // Default mv precision adaptation -#endif // If segmentation is enabled force a map update for key frames if (xd->segmentation_enabled) @@ -3024,6 +3057,14 @@ static void encode_frame_to_data_rate loop_count = 0; +#if CONFIG_HIGH_PRECISION_MV + /* Decide this based on various factors */ + if (cm->frame_type != KEY_FRAME) + { + xd->allow_high_precision_mv = (Q < HIGH_PRECISION_MV_QTHRESH); + } +#endif + #if CONFIG_POSTPROC if (cpi->oxcf.noise_sensitivity > 0) @@ -3460,6 +3501,7 @@ static void encode_frame_to_data_rate // build the bitstream vp8_pack_bitstream(cpi, dest, size); + /* Move storing frame_type out of the above loop since it is also * needed in motion search besides loopfilter */ cm->last_frame_type = cm->frame_type; @@ -3755,7 +3797,7 @@ static void encode_frame_to_data_rate fclose(recon_file); } #endif -#if OUTPUT_YUV_REC +#ifdef OUTPUT_YUV_REC vp8_write_yuv_rec_frame(cm); #endif @@ -3932,6 +3974,9 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon cpi->source = NULL; +#if CONFIG_HIGH_PRECISION_MV + cpi->mb.e_mbd.allow_high_precision_mv = ALTREF_HIGH_PRECISION_MV; +#endif // Should we code an alternate reference frame if (cpi->oxcf.play_alternate && cpi->source_alt_ref_pending) diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 8aa4f1ff9345aa5fc5ca16a2e1b4adc37db90868..47de2c80411b95720414bd125a9e0ff7238ecc4d 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -64,6 +64,10 @@ typedef struct MV_CONTEXT mvc[2]; int mvcosts[2][MVvals+1]; +#if CONFIG_HIGH_PRECISION_MV + MV_CONTEXT_HP mvc_hp[2]; + int mvcosts_hp[2][MVvals_hp+1]; +#endif #ifdef MODE_STATS // Stats @@ -440,6 +444,9 @@ typedef struct VP8_COMP int uv_mode_count[VP8_UV_MODES]; /* intra MB type cts this frame */ unsigned int MVcount [2] [MVvals]; /* (row,col) MV cts this frame */ +#if CONFIG_HIGH_PRECISION_MV + unsigned int MVcount_hp [2] [MVvals_hp]; /* (row,col) MV cts this frame */ +#endif unsigned int coef_counts [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS]; /* for this frame */ //DECLARE_ALIGNED(16, int, coef_counts_backup [BLOCK_TYPES] [COEF_BANDS] [PREV_COEF_CONTEXTS] [MAX_ENTROPY_TOKENS]); //not used any more diff --git a/vp8/encoder/quantize.c b/vp8/encoder/quantize.c index 7ea712f7f72f741e0007214f03951ebb7538d82f..b14f8c4cc657870144caeec5e691790def6243c4 100644 --- a/vp8/encoder/quantize.c +++ b/vp8/encoder/quantize.c @@ -75,7 +75,7 @@ void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d) void vp8_fast_quantize_b_c(BLOCK *b, BLOCKD *d) { - int i, rc, eob; + int i, rc, eob, nonzeros; int x, y, z, sz; short *coeff_ptr = b->coeff; short *round_ptr = b->round; @@ -1295,4 +1295,3 @@ void vp8_set_quantizer(struct VP8_COMP *cpi, int Q) //if(update) // vp8cx_init_quantizer(cpi); } - diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c index a501c3e5f526a0852aa5f79657a9a7ef913e6900..ad4a7e07ae86652cbadf62e3187b74b1b57f30b4 100644 --- a/vp8/encoder/ratectrl.c +++ b/vp8/encoder/ratectrl.c @@ -148,6 +148,10 @@ void vp8_save_coding_context(VP8_COMP *cpi) vp8_copy(cc->mvc, cpi->common.fc.mvc); vp8_copy(cc->mvcosts, cpi->mb.mvcosts); +#if CONFIG_HIGH_PRECISION_MV + vp8_copy(cc->mvc_hp, cpi->common.fc.mvc_hp); + vp8_copy(cc->mvcosts_hp, cpi->mb.mvcosts_hp); +#endif vp8_copy(cc->kf_ymode_prob, cpi->common.kf_ymode_prob); vp8_copy(cc->ymode_prob, cpi->common.fc.ymode_prob); @@ -187,6 +191,11 @@ void vp8_restore_coding_context(VP8_COMP *cpi) vp8_copy(cpi->common.fc.mvc, cc->mvc); vp8_copy(cpi->mb.mvcosts, cc->mvcosts); +#if CONFIG_HIGH_PRECISION_MV + vp8_copy(cpi->common.fc.mvc_hp, cc->mvc_hp); + + vp8_copy(cpi->mb.mvcosts_hp, cc->mvcosts_hp); +#endif vp8_copy(cpi->common.kf_ymode_prob, cc->kf_ymode_prob); vp8_copy(cpi->common.fc.ymode_prob, cc->ymode_prob); vp8_copy(cpi->common.kf_uv_mode_prob, cc->kf_uv_mode_prob); @@ -222,8 +231,16 @@ void vp8_setup_key_frame(VP8_COMP *cpi) int flag[2] = {1, 1}; vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) cpi->common.fc.mvc, flag); } - vpx_memset(cpi->common.fc.pre_mvc, 0, sizeof(cpi->common.fc.pre_mvc)); //initialize pre_mvc to all zero. +#if CONFIG_HIGH_PRECISION_MV + vpx_memcpy(cpi->common.fc.mvc_hp, vp8_default_mv_context_hp, sizeof(vp8_default_mv_context_hp)); + { + int flag[2] = {1, 1}; + vp8_build_component_cost_table_hp(cpi->mb.mvcost_hp, (const MV_CONTEXT_HP *) cpi->common.fc.mvc_hp, flag); + } + vpx_memset(cpi->common.fc.pre_mvc_hp, 0, sizeof(cpi->common.fc.pre_mvc_hp)); //initialize pre_mvc to all zero. +#endif + #if CONFIG_T8X8 cpi->common.txfm_mode = ONLY_4X4; diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c index c8b79615be15ae7a91e2c89b54977f9b4910f7a3..87e1d93da004b75e474d8553bb040d05f63b0e08 100644 --- a/vp8/encoder/rdopt.c +++ b/vp8/encoder/rdopt.c @@ -1601,7 +1601,12 @@ static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x, bestsme = cpi->diamond_search_sad(x, c, e, &mvp_full, &mode_mv[NEW4X4], step_param, sadpb, &num00, v_fn_ptr, - x->mvcost, bsi->ref_mv); +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost, +#else + x->mvcost, +#endif + bsi->ref_mv); n = num00; num00 = 0; @@ -1618,7 +1623,12 @@ static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x, &mvp_full, &temp_mv, step_param + n, sadpb, &num00, v_fn_ptr, - x->mvcost, bsi->ref_mv); +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost, +#else + x->mvcost, +#endif + bsi->ref_mv); if (thissme < bestsme) { @@ -1639,7 +1649,12 @@ static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x, thissme = cpi->full_search_sad(x, c, e, &mvp_full, sadpb, 16, v_fn_ptr, - x->mvcost, bsi->ref_mv); +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost, +#else + x->mvcost, +#endif + bsi->ref_mv); if (thissme < bestsme) { @@ -1659,7 +1674,12 @@ static void rd_check_segment(VP8_COMP *cpi, MACROBLOCK *x, int distortion; unsigned int sse; cpi->find_fractional_mv_step(x, c, e, &mode_mv[NEW4X4], - bsi->ref_mv, x->errorperbit, v_fn_ptr, x->mvcost, + bsi->ref_mv, x->errorperbit, v_fn_ptr, +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost, +#else + x->mvcost, +#endif &distortion, &sse); } } /* NEW4X4 */ @@ -2154,19 +2174,43 @@ static void rd_update_mvcount(VP8_COMP *cpi, MACROBLOCK *x, int_mv *best_ref_mv) { if (x->partition_info->bmi[i].mode == NEW4X4) { - cpi->MVcount[0][mv_max+((x->partition_info->bmi[i].mv.as_mv.row - - best_ref_mv->as_mv.row) >> MV_SHIFT)]++; - cpi->MVcount[1][mv_max+((x->partition_info->bmi[i].mv.as_mv.col - - best_ref_mv->as_mv.col) >> MV_SHIFT)]++; +#if CONFIG_HIGH_PRECISION_MV + if (x->e_mbd.allow_high_precision_mv) + { + cpi->MVcount_hp[0][mv_max_hp+(x->partition_info->bmi[i].mv.as_mv.row + - best_ref_mv->as_mv.row)]++; + cpi->MVcount_hp[1][mv_max_hp+(x->partition_info->bmi[i].mv.as_mv.col + - best_ref_mv->as_mv.col)]++; + } + else +#endif + { + cpi->MVcount[0][mv_max+((x->partition_info->bmi[i].mv.as_mv.row + - best_ref_mv->as_mv.row) >> 1)]++; + cpi->MVcount[1][mv_max+((x->partition_info->bmi[i].mv.as_mv.col + - best_ref_mv->as_mv.col) >> 1)]++; + } } } } else if (x->e_mbd.mode_info_context->mbmi.mode == NEWMV) { - cpi->MVcount[0][mv_max+((x->e_mbd.mode_info_context->mbmi.mv.as_mv.row - - best_ref_mv->as_mv.row) >> MV_SHIFT)]++; - cpi->MVcount[1][mv_max+((x->e_mbd.mode_info_context->mbmi.mv.as_mv.col - - best_ref_mv->as_mv.col) >> MV_SHIFT)]++; +#if CONFIG_HIGH_PRECISION_MV + if (x->e_mbd.allow_high_precision_mv) + { + cpi->MVcount_hp[0][mv_max_hp+(x->e_mbd.mode_info_context->mbmi.mv.as_mv.row + - best_ref_mv->as_mv.row)]++; + cpi->MVcount_hp[1][mv_max_hp+(x->e_mbd.mode_info_context->mbmi.mv.as_mv.col + - best_ref_mv->as_mv.col)]++; + } + else +#endif + { + cpi->MVcount[0][mv_max+((x->e_mbd.mode_info_context->mbmi.mv.as_mv.row + - best_ref_mv->as_mv.row) >> 1)]++; + cpi->MVcount[1][mv_max+((x->e_mbd.mode_info_context->mbmi.mv.as_mv.col + - best_ref_mv->as_mv.col) >> 1)]++; + } } } @@ -2640,7 +2684,12 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int bestsme = cpi->diamond_search_sad(x, b, d, &mvp_full, &d->bmi.mv, step_param, sadpb, &num00, &cpi->fn_ptr[BLOCK_16X16], - x->mvcost, &best_ref_mv); +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost, +#else + x->mvcost, +#endif + &best_ref_mv); mode_mv[NEWMV].as_int = d->bmi.mv.as_int; // Further step/diamond searches as necessary @@ -2664,7 +2713,12 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int { thissme = cpi->diamond_search_sad(x, b, d, &mvp_full, &d->bmi.mv, step_param + n, sadpb, &num00, - &cpi->fn_ptr[BLOCK_16X16], x->mvcost, + &cpi->fn_ptr[BLOCK_16X16], +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost, +#else + x->mvcost, +#endif &best_ref_mv); /* check to see if refining search is needed. */ @@ -2696,7 +2750,12 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int //thissme = cpi->full_search_sad(x, b, d, &d->bmi.mv.as_mv, sadpb, search_range, &cpi->fn_ptr[BLOCK_16X16], x->mvcost, &best_ref_mv); thissme = cpi->refining_search_sad(x, b, d, &d->bmi.mv, sadpb, search_range, &cpi->fn_ptr[BLOCK_16X16], - x->mvcost, &best_ref_mv); +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost, +#else + x->mvcost, +#endif + &best_ref_mv); if (thissme < bestsme) { @@ -2721,7 +2780,12 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int cpi->find_fractional_mv_step(x, b, d, &d->bmi.mv, &best_ref_mv, x->errorperbit, &cpi->fn_ptr[BLOCK_16X16], - x->mvcost, &dis, &sse); +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?x->mvcost_hp:x->mvcost, +#else + x->mvcost, +#endif + &dis, &sse); } mc_search_result[x->e_mbd.mode_info_context->mbmi.ref_frame].as_int = d->bmi.mv.as_int; diff --git a/vp8/encoder/temporal_filter.c b/vp8/encoder/temporal_filter.c index ede65d669c2e71fd4bdb22ad4cf53e5f8f3c1e43..6c8b45857e7cb8978ff49473468f8e3f48902249 100644 --- a/vp8/encoder/temporal_filter.c +++ b/vp8/encoder/temporal_filter.c @@ -36,6 +36,7 @@ #if VP8_TEMPORAL_ALT_REF + static void vp8_temporal_filter_predictors_mb_c ( MACROBLOCKD *x, @@ -154,6 +155,9 @@ void vp8_temporal_filter_apply_c #if ALT_REF_MC_ENABLED static int dummy_cost[2*mv_max+1]; +#if CONFIG_HIGH_PRECISION_MV +static int dummy_cost_hp[2*mv_max_hp+1]; +#endif static int vp8_temporal_filter_find_matching_mb_c ( @@ -177,6 +181,10 @@ static int vp8_temporal_filter_find_matching_mb_c int *mvcost[2] = { &dummy_cost[mv_max+1], &dummy_cost[mv_max+1] }; int *mvsadcost[2] = { &dummy_cost[mv_max+1], &dummy_cost[mv_max+1] }; +#if CONFIG_HIGH_PRECISION_MV + int *mvcost_hp[2] = { &dummy_cost_hp[mv_max_hp+1], &dummy_cost_hp[mv_max_hp+1] }; + int *mvsadcost_hp[2] = { &dummy_cost_hp[mv_max_hp+1], &dummy_cost_hp[mv_max_hp+1] }; +#endif // Save input state unsigned char **base_src = b->base_src; @@ -220,7 +228,13 @@ static int vp8_temporal_filter_find_matching_mb_c step_param, sadpb, &cpi->fn_ptr[BLOCK_16X16], - mvsadcost, mvcost, &best_ref_mv1); +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?mvsadcost_hp:mvsadcost, + x->e_mbd.allow_high_precision_mv?mvcost_hp:mvcost, +#else + mvsadcost, mvcost, +#endif + &best_ref_mv1); #if ALT_REF_SUBPEL_ENABLED // Try sub-pixel MC? @@ -231,7 +245,12 @@ static int vp8_temporal_filter_find_matching_mb_c bestsme = cpi->find_fractional_mv_step(x, b, d, &d->bmi.mv, &best_ref_mv1, x->errorperbit, &cpi->fn_ptr[BLOCK_16X16], - mvcost, &distortion, &sse); +#if CONFIG_HIGH_PRECISION_MV + x->e_mbd.allow_high_precision_mv?mvcost_hp:mvcost, +#else + mvcost, +#endif + &distortion, &sse); } #endif @@ -280,17 +299,17 @@ static void vp8_temporal_filter_iterate_c #if ALT_REF_MC_ENABLED // Source frames are extended to 16 pixels. This is different than // L/A/G reference frames that have a border of 32 (VP8BORDERINPIXELS) - // A 6 tap filter is used for motion search. This requires 2 pixels + // A 6/8 tap filter is used for motion search. This requires 2 pixels // before and 3 pixels after. So the largest Y mv on a border would - // then be 16 - 3. The UV blocks are half the size of the Y and + // then be 16 - INTERP_EXTEND. The UV blocks are half the size of the Y and // therefore only extended by 8. The largest mv that a UV block - // can support is 8 - 3. A UV mv is half of a Y mv. - // (16 - 3) >> 1 == 6 which is greater than 8 - 3. + // can support is 8 - INTERP_EXTEND. A UV mv is half of a Y mv. + // (16 - INTERP_EXTEND) >> 1 which is greater than 8 - INTERP_EXTEND. // To keep the mv in play for both Y and UV planes the max that it - // can be on a border is therefore 16 - 5. - cpi->mb.mv_row_min = -((mb_row * 16) + (16 - 5)); + // can be on a border is therefore 16 - (2*INTERP_EXTEND+1). + cpi->mb.mv_row_min = -((mb_row * 16) + (17 - 2*INTERP_EXTEND)); cpi->mb.mv_row_max = ((cpi->common.mb_rows - 1 - mb_row) * 16) - + (16 - 5); + + (17 - 2*INTERP_EXTEND); #endif for (mb_col = 0; mb_col < mb_cols; mb_col++) @@ -302,9 +321,9 @@ static void vp8_temporal_filter_iterate_c vpx_memset(count, 0, 384*sizeof(unsigned short)); #if ALT_REF_MC_ENABLED - cpi->mb.mv_col_min = -((mb_col * 16) + (16 - 5)); + cpi->mb.mv_col_min = -((mb_col * 16) + (17 - 2*INTERP_EXTEND)); cpi->mb.mv_col_max = ((cpi->common.mb_cols - 1 - mb_col) * 16) - + (16 - 5); + + (17 - 2*INTERP_EXTEND); #endif for (frame = 0; frame < frame_count; frame++)