1
2 /*
3 * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
4 *
5 * Use of this source code is governed by a BSD-style license
6 * that can be found in the LICENSE file in the root of the source
7 * tree. An additional intellectual property rights grant can be found
8 * in the file PATENTS. All contributing project authors may
9 * be found in the AUTHORS file in the root of the source tree.
10 */
11
12 #include "vp9/common/vp9_mvref_common.h"
13
14 #define MVREF_NEIGHBOURS 8
15
16 typedef struct position {
17 int row;
18 int col;
19 } POSITION;
20
21 typedef enum {
22 BOTH_ZERO = 0,
23 ZERO_PLUS_PREDICTED = 1,
24 BOTH_PREDICTED = 2,
25 NEW_PLUS_NON_INTRA = 3,
26 BOTH_NEW = 4,
27 INTRA_PLUS_NON_INTRA = 5,
28 BOTH_INTRA = 6,
29 INVALID_CASE = 9
30 } motion_vector_context;
31
32 // This is used to figure out a context for the ref blocks. The code flattens
33 // an array that would have 3 possible counts (0, 1 & 2) for 3 choices by
34 // adding 9 for each intra block, 3 for each zero mv and 1 for each new
35 // motion vector. This single number is then converted into a context
36 // with a single lookup ( counter_to_context ).
37 static const int mode_2_counter[MB_MODE_COUNT] = {
38 9, // DC_PRED
39 9, // V_PRED
40 9, // H_PRED
41 9, // D45_PRED
42 9, // D135_PRED
43 9, // D117_PRED
44 9, // D153_PRED
45 9, // D207_PRED
46 9, // D63_PRED
47 9, // TM_PRED
48 0, // NEARESTMV
49 0, // NEARMV
50 3, // ZEROMV
51 1, // NEWMV
52 };
53
54 // There are 3^3 different combinations of 3 counts that can be either 0,1 or
55 // 2. However the actual count can never be greater than 2 so the highest
56 // counter we need is 18. 9 is an invalid counter that's never used.
57 static const int counter_to_context[19] = {
58 BOTH_PREDICTED, // 0
59 NEW_PLUS_NON_INTRA, // 1
60 BOTH_NEW, // 2
61 ZERO_PLUS_PREDICTED, // 3
62 NEW_PLUS_NON_INTRA, // 4
63 INVALID_CASE, // 5
64 BOTH_ZERO, // 6
65 INVALID_CASE, // 7
66 INVALID_CASE, // 8
67 INTRA_PLUS_NON_INTRA, // 9
68 INTRA_PLUS_NON_INTRA, // 10
69 INVALID_CASE, // 11
70 INTRA_PLUS_NON_INTRA, // 12
71 INVALID_CASE, // 13
72 INVALID_CASE, // 14
73 INVALID_CASE, // 15
74 INVALID_CASE, // 16
75 INVALID_CASE, // 17
76 BOTH_INTRA // 18
77 };
78
79 static const POSITION mv_ref_blocks[BLOCK_SIZES][MVREF_NEIGHBOURS] = {
80 // 4X4
81 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
82 // 4X8
83 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
84 // 8X4
85 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
86 // 8X8
87 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
88 // 8X16
89 {{0, -1}, {-1, 0}, {1, -1}, {-1, -1}, {0, -2}, {-2, 0}, {-2, -1}, {-1, -2}},
90 // 16X8
91 {{-1, 0}, {0, -1}, {-1, 1}, {-1, -1}, {-2, 0}, {0, -2}, {-1, -2}, {-2, -1}},
92 // 16X16
93 {{-1, 0}, {0, -1}, {-1, 1}, {1, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
94 // 16X32
95 {{0, -1}, {-1, 0}, {2, -1}, {-1, -1}, {-1, 1}, {0, -3}, {-3, 0}, {-3, -3}},
96 // 32X16
97 {{-1, 0}, {0, -1}, {-1, 2}, {-1, -1}, {1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
98 // 32X32
99 {{-1, 1}, {1, -1}, {-1, 2}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
100 // 32X64
101 {{0, -1}, {-1, 0}, {4, -1}, {-1, 2}, {-1, -1}, {0, -3}, {-3, 0}, {2, -1}},
102 // 64X32
103 {{-1, 0}, {0, -1}, {-1, 4}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-1, 2}},
104 // 64X64
105 {{-1, 3}, {3, -1}, {-1, 4}, {4, -1}, {-1, -1}, {-1, 0}, {0, -1}, {-1, 6}}
106 };
107
108 static const int idx_n_column_to_subblock[4][2] = {
109 {1, 2},
110 {1, 3},
111 {3, 2},
112 {3, 3}
113 };
114
115 // clamp_mv_ref
116 #define MV_BORDER (16 << 3) // Allow 16 pels in 1/8th pel units
117
clamp_mv_ref(MV * mv,const MACROBLOCKD * xd)118 static void clamp_mv_ref(MV *mv, const MACROBLOCKD *xd) {
119 clamp_mv(mv, xd->mb_to_left_edge - MV_BORDER,
120 xd->mb_to_right_edge + MV_BORDER,
121 xd->mb_to_top_edge - MV_BORDER,
122 xd->mb_to_bottom_edge + MV_BORDER);
123 }
124
125 // This function returns either the appropriate sub block or block's mv
126 // on whether the block_size < 8x8 and we have check_sub_blocks set.
get_sub_block_mv(const MODE_INFO * candidate,int which_mv,int search_col,int block_idx)127 static INLINE int_mv get_sub_block_mv(const MODE_INFO *candidate, int which_mv,
128 int search_col, int block_idx) {
129 return block_idx >= 0 && candidate->mbmi.sb_type < BLOCK_8X8
130 ? candidate->bmi[idx_n_column_to_subblock[block_idx][search_col == 0]]
131 .as_mv[which_mv]
132 : candidate->mbmi.mv[which_mv];
133 }
134
135
136 // Performs mv sign inversion if indicated by the reference frame combination.
scale_mv(const MB_MODE_INFO * mbmi,int ref,const MV_REFERENCE_FRAME this_ref_frame,const int * ref_sign_bias)137 static INLINE int_mv scale_mv(const MB_MODE_INFO *mbmi, int ref,
138 const MV_REFERENCE_FRAME this_ref_frame,
139 const int *ref_sign_bias) {
140 int_mv mv = mbmi->mv[ref];
141 if (ref_sign_bias[mbmi->ref_frame[ref]] != ref_sign_bias[this_ref_frame]) {
142 mv.as_mv.row *= -1;
143 mv.as_mv.col *= -1;
144 }
145 return mv;
146 }
147
148 // This macro is used to add a motion vector mv_ref list if it isn't
149 // already in the list. If it's the second motion vector it will also
150 // skip all additional processing and jump to done!
151 #define ADD_MV_REF_LIST(mv) \
152 do { \
153 if (refmv_count) { \
154 if ((mv).as_int != mv_ref_list[0].as_int) { \
155 mv_ref_list[refmv_count] = (mv); \
156 goto Done; \
157 } \
158 } else { \
159 mv_ref_list[refmv_count++] = (mv); \
160 } \
161 } while (0)
162
163 // If either reference frame is different, not INTRA, and they
164 // are different from each other scale and add the mv to our list.
165 #define IF_DIFF_REF_FRAME_ADD_MV(mbmi) \
166 do { \
167 if (is_inter_block(mbmi)) { \
168 if ((mbmi)->ref_frame[0] != ref_frame) \
169 ADD_MV_REF_LIST(scale_mv((mbmi), 0, ref_frame, ref_sign_bias)); \
170 if (has_second_ref(mbmi) && \
171 (mbmi)->ref_frame[1] != ref_frame && \
172 (mbmi)->mv[1].as_int != (mbmi)->mv[0].as_int) \
173 ADD_MV_REF_LIST(scale_mv((mbmi), 1, ref_frame, ref_sign_bias)); \
174 } \
175 } while (0)
176
177
178 // Checks that the given mi_row, mi_col and search point
179 // are inside the borders of the tile.
is_inside(const TileInfo * const tile,int mi_col,int mi_row,int mi_rows,const POSITION * mi_pos)180 static INLINE int is_inside(const TileInfo *const tile,
181 int mi_col, int mi_row, int mi_rows,
182 const POSITION *mi_pos) {
183 return !(mi_row + mi_pos->row < 0 ||
184 mi_col + mi_pos->col < tile->mi_col_start ||
185 mi_row + mi_pos->row >= mi_rows ||
186 mi_col + mi_pos->col >= tile->mi_col_end);
187 }
188
189 // This function searches the neighbourhood of a given MB/SB
190 // to try and find candidate reference vectors.
find_mv_refs_idx(const VP9_COMMON * cm,const MACROBLOCKD * xd,const TileInfo * const tile,MODE_INFO * mi,MV_REFERENCE_FRAME ref_frame,int_mv * mv_ref_list,int block,int mi_row,int mi_col)191 static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd,
192 const TileInfo *const tile,
193 MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
194 int_mv *mv_ref_list,
195 int block, int mi_row, int mi_col) {
196 const int *ref_sign_bias = cm->ref_frame_sign_bias;
197 int i, refmv_count = 0;
198 const MODE_INFO *prev_mi = cm->coding_use_prev_mi && cm->prev_mi
199 ? cm->prev_mi_grid_visible[mi_row * xd->mi_stride + mi_col]
200 : NULL;
201 const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->mbmi : NULL;
202
203
204 const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
205
206 int different_ref_found = 0;
207 int context_counter = 0;
208
209 // Blank the reference vector list
210 vpx_memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
211
212 // The nearest 2 blocks are treated differently
213 // if the size < 8x8 we get the mv from the bmi substructure,
214 // and we also need to keep a mode count.
215 for (i = 0; i < 2; ++i) {
216 const POSITION *const mv_ref = &mv_ref_search[i];
217 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
218 const MODE_INFO *const candidate_mi = xd->mi[mv_ref->col + mv_ref->row *
219 xd->mi_stride];
220 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
221 // Keep counts for entropy encoding.
222 context_counter += mode_2_counter[candidate->mode];
223 different_ref_found = 1;
224
225 if (candidate->ref_frame[0] == ref_frame)
226 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block));
227 else if (candidate->ref_frame[1] == ref_frame)
228 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block));
229 }
230 }
231
232 // Check the rest of the neighbors in much the same way
233 // as before except we don't need to keep track of sub blocks or
234 // mode counts.
235 for (; i < MVREF_NEIGHBOURS; ++i) {
236 const POSITION *const mv_ref = &mv_ref_search[i];
237 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
238 const MB_MODE_INFO *const candidate = &xd->mi[mv_ref->col + mv_ref->row *
239 xd->mi_stride]->mbmi;
240 different_ref_found = 1;
241
242 if (candidate->ref_frame[0] == ref_frame)
243 ADD_MV_REF_LIST(candidate->mv[0]);
244 else if (candidate->ref_frame[1] == ref_frame)
245 ADD_MV_REF_LIST(candidate->mv[1]);
246 }
247 }
248
249 // Check the last frame's mode and mv info.
250 if (prev_mbmi) {
251 if (prev_mbmi->ref_frame[0] == ref_frame)
252 ADD_MV_REF_LIST(prev_mbmi->mv[0]);
253 else if (prev_mbmi->ref_frame[1] == ref_frame)
254 ADD_MV_REF_LIST(prev_mbmi->mv[1]);
255 }
256
257 // Since we couldn't find 2 mvs from the same reference frame
258 // go back through the neighbors and find motion vectors from
259 // different reference frames.
260 if (different_ref_found) {
261 for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
262 const POSITION *mv_ref = &mv_ref_search[i];
263 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
264 const MB_MODE_INFO *const candidate = &xd->mi[mv_ref->col + mv_ref->row
265 * xd->mi_stride]->mbmi;
266
267 // If the candidate is INTRA we don't want to consider its mv.
268 IF_DIFF_REF_FRAME_ADD_MV(candidate);
269 }
270 }
271 }
272
273 // Since we still don't have a candidate we'll try the last frame.
274 if (prev_mbmi)
275 IF_DIFF_REF_FRAME_ADD_MV(prev_mbmi);
276
277 Done:
278
279 mi->mbmi.mode_context[ref_frame] = counter_to_context[context_counter];
280
281 // Clamp vectors
282 for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i)
283 clamp_mv_ref(&mv_ref_list[i].as_mv, xd);
284 }
285
vp9_find_mv_refs(const VP9_COMMON * cm,const MACROBLOCKD * xd,const TileInfo * const tile,MODE_INFO * mi,MV_REFERENCE_FRAME ref_frame,int_mv * mv_ref_list,int mi_row,int mi_col)286 void vp9_find_mv_refs(const VP9_COMMON *cm, const MACROBLOCKD *xd,
287 const TileInfo *const tile,
288 MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
289 int_mv *mv_ref_list,
290 int mi_row, int mi_col) {
291 find_mv_refs_idx(cm, xd, tile, mi, ref_frame, mv_ref_list, -1,
292 mi_row, mi_col);
293 }
294
lower_mv_precision(MV * mv,int allow_hp)295 static void lower_mv_precision(MV *mv, int allow_hp) {
296 const int use_hp = allow_hp && vp9_use_mv_hp(mv);
297 if (!use_hp) {
298 if (mv->row & 1)
299 mv->row += (mv->row > 0 ? -1 : 1);
300 if (mv->col & 1)
301 mv->col += (mv->col > 0 ? -1 : 1);
302 }
303 }
304
305
vp9_find_best_ref_mvs(MACROBLOCKD * xd,int allow_hp,int_mv * mvlist,int_mv * nearest,int_mv * near)306 void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
307 int_mv *mvlist, int_mv *nearest, int_mv *near) {
308 int i;
309 // Make sure all the candidates are properly clamped etc
310 for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
311 lower_mv_precision(&mvlist[i].as_mv, allow_hp);
312 clamp_mv2(&mvlist[i].as_mv, xd);
313 }
314 *nearest = mvlist[0];
315 *near = mvlist[1];
316 }
317
vp9_append_sub8x8_mvs_for_idx(VP9_COMMON * cm,MACROBLOCKD * xd,const TileInfo * const tile,int block,int ref,int mi_row,int mi_col,int_mv * nearest,int_mv * near)318 void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
319 const TileInfo *const tile,
320 int block, int ref, int mi_row, int mi_col,
321 int_mv *nearest, int_mv *near) {
322 int_mv mv_list[MAX_MV_REF_CANDIDATES];
323 MODE_INFO *const mi = xd->mi[0];
324 b_mode_info *bmi = mi->bmi;
325 int n;
326
327 assert(MAX_MV_REF_CANDIDATES == 2);
328
329 find_mv_refs_idx(cm, xd, tile, mi, mi->mbmi.ref_frame[ref], mv_list, block,
330 mi_row, mi_col);
331
332 near->as_int = 0;
333 switch (block) {
334 case 0:
335 nearest->as_int = mv_list[0].as_int;
336 near->as_int = mv_list[1].as_int;
337 break;
338 case 1:
339 case 2:
340 nearest->as_int = bmi[0].as_mv[ref].as_int;
341 for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n)
342 if (nearest->as_int != mv_list[n].as_int) {
343 near->as_int = mv_list[n].as_int;
344 break;
345 }
346 break;
347 case 3: {
348 int_mv candidates[2 + MAX_MV_REF_CANDIDATES];
349 candidates[0] = bmi[1].as_mv[ref];
350 candidates[1] = bmi[0].as_mv[ref];
351 candidates[2] = mv_list[0];
352 candidates[3] = mv_list[1];
353
354 nearest->as_int = bmi[2].as_mv[ref].as_int;
355 for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n)
356 if (nearest->as_int != candidates[n].as_int) {
357 near->as_int = candidates[n].as_int;
358 break;
359 }
360 break;
361 }
362 default:
363 assert("Invalid block index.");
364 }
365 }
366