michael@0: /* michael@0: * Copyright (c) 2010 The WebM project authors. All Rights Reserved. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license michael@0: * that can be found in the LICENSE file in the root of the source michael@0: * tree. An additional intellectual property rights grant can be found michael@0: * in the file PATENTS. All contributing project authors may michael@0: * be found in the AUTHORS file in the root of the source tree. michael@0: */ michael@0: michael@0: michael@0: #include "findnearmv.h" michael@0: michael@0: const unsigned char vp8_mbsplit_offset[4][16] = { michael@0: { 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, michael@0: { 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, michael@0: { 0, 2, 8, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, michael@0: { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} michael@0: }; michael@0: michael@0: /* Predict motion vectors using those from already-decoded nearby blocks. michael@0: Note that we only consider one 4x4 subblock from each candidate 16x16 michael@0: macroblock. */ michael@0: void vp8_find_near_mvs michael@0: ( michael@0: MACROBLOCKD *xd, michael@0: const MODE_INFO *here, michael@0: int_mv *nearest, michael@0: int_mv *nearby, michael@0: int_mv *best_mv, michael@0: int cnt[4], michael@0: int refframe, michael@0: int *ref_frame_sign_bias michael@0: ) michael@0: { michael@0: const MODE_INFO *above = here - xd->mode_info_stride; michael@0: const MODE_INFO *left = here - 1; michael@0: const MODE_INFO *aboveleft = above - 1; michael@0: int_mv near_mvs[4]; michael@0: int_mv *mv = near_mvs; michael@0: int *cntx = cnt; michael@0: enum {CNT_INTRA, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV}; michael@0: michael@0: /* Zero accumulators */ michael@0: mv[0].as_int = mv[1].as_int = mv[2].as_int = 0; michael@0: cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0; michael@0: michael@0: /* Process above */ michael@0: if (above->mbmi.ref_frame != INTRA_FRAME) michael@0: { michael@0: if (above->mbmi.mv.as_int) michael@0: { michael@0: (++mv)->as_int = above->mbmi.mv.as_int; michael@0: mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame], refframe, mv, ref_frame_sign_bias); michael@0: ++cntx; michael@0: } michael@0: michael@0: *cntx += 2; michael@0: } michael@0: michael@0: /* Process left */ michael@0: if (left->mbmi.ref_frame != INTRA_FRAME) michael@0: { michael@0: if (left->mbmi.mv.as_int) michael@0: { michael@0: int_mv this_mv; michael@0: michael@0: this_mv.as_int = left->mbmi.mv.as_int; michael@0: mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame], refframe, &this_mv, ref_frame_sign_bias); michael@0: michael@0: if (this_mv.as_int != mv->as_int) michael@0: { michael@0: (++mv)->as_int = this_mv.as_int; michael@0: ++cntx; michael@0: } michael@0: michael@0: *cntx += 2; michael@0: } michael@0: else michael@0: cnt[CNT_INTRA] += 2; michael@0: } michael@0: michael@0: /* Process above left */ michael@0: if (aboveleft->mbmi.ref_frame != INTRA_FRAME) michael@0: { michael@0: if (aboveleft->mbmi.mv.as_int) michael@0: { michael@0: int_mv this_mv; michael@0: michael@0: this_mv.as_int = aboveleft->mbmi.mv.as_int; michael@0: mv_bias(ref_frame_sign_bias[aboveleft->mbmi.ref_frame], refframe, &this_mv, ref_frame_sign_bias); michael@0: michael@0: if (this_mv.as_int != mv->as_int) michael@0: { michael@0: (++mv)->as_int = this_mv.as_int; michael@0: ++cntx; michael@0: } michael@0: michael@0: *cntx += 1; michael@0: } michael@0: else michael@0: cnt[CNT_INTRA] += 1; michael@0: } michael@0: michael@0: /* If we have three distinct MV's ... */ michael@0: if (cnt[CNT_SPLITMV]) michael@0: { michael@0: /* See if above-left MV can be merged with NEAREST */ michael@0: if (mv->as_int == near_mvs[CNT_NEAREST].as_int) michael@0: cnt[CNT_NEAREST] += 1; michael@0: } michael@0: michael@0: cnt[CNT_SPLITMV] = ((above->mbmi.mode == SPLITMV) michael@0: + (left->mbmi.mode == SPLITMV)) * 2 michael@0: + (aboveleft->mbmi.mode == SPLITMV); michael@0: michael@0: /* Swap near and nearest if necessary */ michael@0: if (cnt[CNT_NEAR] > cnt[CNT_NEAREST]) michael@0: { michael@0: int tmp; michael@0: tmp = cnt[CNT_NEAREST]; michael@0: cnt[CNT_NEAREST] = cnt[CNT_NEAR]; michael@0: cnt[CNT_NEAR] = tmp; michael@0: tmp = near_mvs[CNT_NEAREST].as_int; michael@0: near_mvs[CNT_NEAREST].as_int = near_mvs[CNT_NEAR].as_int; michael@0: near_mvs[CNT_NEAR].as_int = tmp; michael@0: } michael@0: michael@0: /* Use near_mvs[0] to store the "best" MV */ michael@0: if (cnt[CNT_NEAREST] >= cnt[CNT_INTRA]) michael@0: near_mvs[CNT_INTRA] = near_mvs[CNT_NEAREST]; michael@0: michael@0: /* Set up return values */ michael@0: best_mv->as_int = near_mvs[0].as_int; michael@0: nearest->as_int = near_mvs[CNT_NEAREST].as_int; michael@0: nearby->as_int = near_mvs[CNT_NEAR].as_int; michael@0: } michael@0: michael@0: michael@0: static void invert_and_clamp_mvs(int_mv *inv, int_mv *src, MACROBLOCKD *xd) michael@0: { michael@0: inv->as_mv.row = src->as_mv.row * -1; michael@0: inv->as_mv.col = src->as_mv.col * -1; michael@0: vp8_clamp_mv2(inv, xd); michael@0: vp8_clamp_mv2(src, xd); michael@0: } michael@0: michael@0: michael@0: int vp8_find_near_mvs_bias michael@0: ( michael@0: MACROBLOCKD *xd, michael@0: const MODE_INFO *here, michael@0: int_mv mode_mv_sb[2][MB_MODE_COUNT], michael@0: int_mv best_mv_sb[2], michael@0: int cnt[4], michael@0: int refframe, michael@0: int *ref_frame_sign_bias michael@0: ) michael@0: { michael@0: int sign_bias = ref_frame_sign_bias[refframe]; michael@0: michael@0: vp8_find_near_mvs(xd, michael@0: here, michael@0: &mode_mv_sb[sign_bias][NEARESTMV], michael@0: &mode_mv_sb[sign_bias][NEARMV], michael@0: &best_mv_sb[sign_bias], michael@0: cnt, michael@0: refframe, michael@0: ref_frame_sign_bias); michael@0: michael@0: invert_and_clamp_mvs(&mode_mv_sb[!sign_bias][NEARESTMV], michael@0: &mode_mv_sb[sign_bias][NEARESTMV], xd); michael@0: invert_and_clamp_mvs(&mode_mv_sb[!sign_bias][NEARMV], michael@0: &mode_mv_sb[sign_bias][NEARMV], xd); michael@0: invert_and_clamp_mvs(&best_mv_sb[!sign_bias], michael@0: &best_mv_sb[sign_bias], xd); michael@0: michael@0: return sign_bias; michael@0: } michael@0: michael@0: michael@0: vp8_prob *vp8_mv_ref_probs( michael@0: vp8_prob p[VP8_MVREFS-1], const int near_mv_ref_ct[4] michael@0: ) michael@0: { michael@0: p[0] = vp8_mode_contexts [near_mv_ref_ct[0]] [0]; michael@0: p[1] = vp8_mode_contexts [near_mv_ref_ct[1]] [1]; michael@0: p[2] = vp8_mode_contexts [near_mv_ref_ct[2]] [2]; michael@0: p[3] = vp8_mode_contexts [near_mv_ref_ct[3]] [3]; michael@0: /*p[3] = vp8_mode_contexts [near_mv_ref_ct[1] + near_mv_ref_ct[2] + near_mv_ref_ct[3]] [3];*/ michael@0: return p; michael@0: } michael@0: