1/*
2 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "findnearmv.h"
12
13const unsigned char vp8_mbsplit_offset[4][16] = {
14  { 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
15  { 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
16  { 0, 2, 8, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
17  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }
18};
19
20/* Predict motion vectors using those from already-decoded nearby blocks.
21   Note that we only consider one 4x4 subblock from each candidate 16x16
22   macroblock.   */
23void vp8_find_near_mvs(MACROBLOCKD *xd, const MODE_INFO *here, int_mv *nearest,
24                       int_mv *nearby, int_mv *best_mv, int cnt[4],
25                       int refframe, int *ref_frame_sign_bias) {
26  const MODE_INFO *above = here - xd->mode_info_stride;
27  const MODE_INFO *left = here - 1;
28  const MODE_INFO *aboveleft = above - 1;
29  int_mv near_mvs[4];
30  int_mv *mv = near_mvs;
31  int *cntx = cnt;
32  enum { CNT_INTRA, CNT_NEAREST, CNT_NEAR, CNT_SPLITMV };
33
34  /* Zero accumulators */
35  mv[0].as_int = mv[1].as_int = mv[2].as_int = 0;
36  cnt[0] = cnt[1] = cnt[2] = cnt[3] = 0;
37
38  /* Process above */
39  if (above->mbmi.ref_frame != INTRA_FRAME) {
40    if (above->mbmi.mv.as_int) {
41      (++mv)->as_int = above->mbmi.mv.as_int;
42      mv_bias(ref_frame_sign_bias[above->mbmi.ref_frame], refframe, mv,
43              ref_frame_sign_bias);
44      ++cntx;
45    }
46
47    *cntx += 2;
48  }
49
50  /* Process left */
51  if (left->mbmi.ref_frame != INTRA_FRAME) {
52    if (left->mbmi.mv.as_int) {
53      int_mv this_mv;
54
55      this_mv.as_int = left->mbmi.mv.as_int;
56      mv_bias(ref_frame_sign_bias[left->mbmi.ref_frame], refframe, &this_mv,
57              ref_frame_sign_bias);
58
59      if (this_mv.as_int != mv->as_int) {
60        (++mv)->as_int = this_mv.as_int;
61        ++cntx;
62      }
63
64      *cntx += 2;
65    } else {
66      cnt[CNT_INTRA] += 2;
67    }
68  }
69
70  /* Process above left */
71  if (aboveleft->mbmi.ref_frame != INTRA_FRAME) {
72    if (aboveleft->mbmi.mv.as_int) {
73      int_mv this_mv;
74
75      this_mv.as_int = aboveleft->mbmi.mv.as_int;
76      mv_bias(ref_frame_sign_bias[aboveleft->mbmi.ref_frame], refframe,
77              &this_mv, ref_frame_sign_bias);
78
79      if (this_mv.as_int != mv->as_int) {
80        (++mv)->as_int = this_mv.as_int;
81        ++cntx;
82      }
83
84      *cntx += 1;
85    } else {
86      cnt[CNT_INTRA] += 1;
87    }
88  }
89
90  /* If we have three distinct MV's ... */
91  if (cnt[CNT_SPLITMV]) {
92    /* See if above-left MV can be merged with NEAREST */
93    if (mv->as_int == near_mvs[CNT_NEAREST].as_int) cnt[CNT_NEAREST] += 1;
94  }
95
96  cnt[CNT_SPLITMV] =
97      ((above->mbmi.mode == SPLITMV) + (left->mbmi.mode == SPLITMV)) * 2 +
98      (aboveleft->mbmi.mode == SPLITMV);
99
100  /* Swap near and nearest if necessary */
101  if (cnt[CNT_NEAR] > cnt[CNT_NEAREST]) {
102    int tmp;
103    tmp = cnt[CNT_NEAREST];
104    cnt[CNT_NEAREST] = cnt[CNT_NEAR];
105    cnt[CNT_NEAR] = tmp;
106    tmp = near_mvs[CNT_NEAREST].as_int;
107    near_mvs[CNT_NEAREST].as_int = near_mvs[CNT_NEAR].as_int;
108    near_mvs[CNT_NEAR].as_int = tmp;
109  }
110
111  /* Use near_mvs[0] to store the "best" MV */
112  if (cnt[CNT_NEAREST] >= cnt[CNT_INTRA]) {
113    near_mvs[CNT_INTRA] = near_mvs[CNT_NEAREST];
114  }
115
116  /* Set up return values */
117  best_mv->as_int = near_mvs[0].as_int;
118  nearest->as_int = near_mvs[CNT_NEAREST].as_int;
119  nearby->as_int = near_mvs[CNT_NEAR].as_int;
120}
121
122static void invert_and_clamp_mvs(int_mv *inv, int_mv *src, MACROBLOCKD *xd) {
123  inv->as_mv.row = src->as_mv.row * -1;
124  inv->as_mv.col = src->as_mv.col * -1;
125  vp8_clamp_mv2(inv, xd);
126  vp8_clamp_mv2(src, xd);
127}
128
129int vp8_find_near_mvs_bias(MACROBLOCKD *xd, const MODE_INFO *here,
130                           int_mv mode_mv_sb[2][MB_MODE_COUNT],
131                           int_mv best_mv_sb[2], int cnt[4], int refframe,
132                           int *ref_frame_sign_bias) {
133  int sign_bias = ref_frame_sign_bias[refframe];
134
135  vp8_find_near_mvs(xd, here, &mode_mv_sb[sign_bias][NEARESTMV],
136                    &mode_mv_sb[sign_bias][NEARMV], &best_mv_sb[sign_bias], cnt,
137                    refframe, ref_frame_sign_bias);
138
139  invert_and_clamp_mvs(&mode_mv_sb[!sign_bias][NEARESTMV],
140                       &mode_mv_sb[sign_bias][NEARESTMV], xd);
141  invert_and_clamp_mvs(&mode_mv_sb[!sign_bias][NEARMV],
142                       &mode_mv_sb[sign_bias][NEARMV], xd);
143  invert_and_clamp_mvs(&best_mv_sb[!sign_bias], &best_mv_sb[sign_bias], xd);
144
145  return sign_bias;
146}
147
148vp8_prob *vp8_mv_ref_probs(vp8_prob p[VP8_MVREFS - 1],
149                           const int near_mv_ref_ct[4]) {
150  p[0] = vp8_mode_contexts[near_mv_ref_ct[0]][0];
151  p[1] = vp8_mode_contexts[near_mv_ref_ct[1]][1];
152  p[2] = vp8_mode_contexts[near_mv_ref_ct[2]][2];
153  p[3] = vp8_mode_contexts[near_mv_ref_ct[3]][3];
154  /* p[3] = vp8_mode_contexts[near_mv_ref_ct[1] + near_mv_ref_ct[2] +
155                           near_mv_ref_ct[3]][3]; */
156  return p;
157}
158