Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 */
12 #include "vp9/common/vp9_mvref_common.h"
14 #define MVREF_NEIGHBOURS 8
16 typedef enum {
17 BOTH_ZERO = 0,
18 ZERO_PLUS_PREDICTED = 1,
19 BOTH_PREDICTED = 2,
20 NEW_PLUS_NON_INTRA = 3,
21 BOTH_NEW = 4,
22 INTRA_PLUS_NON_INTRA = 5,
23 BOTH_INTRA = 6,
24 INVALID_CASE = 9
25 } motion_vector_context;
27 // This is used to figure out a context for the ref blocks. The code flattens
28 // an array that would have 3 possible counts (0, 1 & 2) for 3 choices by
29 // adding 9 for each intra block, 3 for each zero mv and 1 for each new
30 // motion vector. This single number is then converted into a context
31 // with a single lookup ( counter_to_context ).
32 static const int mode_2_counter[MB_MODE_COUNT] = {
33 9, // DC_PRED
34 9, // V_PRED
35 9, // H_PRED
36 9, // D45_PRED
37 9, // D135_PRED
38 9, // D117_PRED
39 9, // D153_PRED
40 9, // D207_PRED
41 9, // D63_PRED
42 9, // TM_PRED
43 0, // NEARESTMV
44 0, // NEARMV
45 3, // ZEROMV
46 1, // NEWMV
47 };
49 // There are 3^3 different combinations of 3 counts that can be either 0,1 or
50 // 2. However the actual count can never be greater than 2 so the highest
51 // counter we need is 18. 9 is an invalid counter that's never used.
52 static const int counter_to_context[19] = {
53 BOTH_PREDICTED, // 0
54 NEW_PLUS_NON_INTRA, // 1
55 BOTH_NEW, // 2
56 ZERO_PLUS_PREDICTED, // 3
57 NEW_PLUS_NON_INTRA, // 4
58 INVALID_CASE, // 5
59 BOTH_ZERO, // 6
60 INVALID_CASE, // 7
61 INVALID_CASE, // 8
62 INTRA_PLUS_NON_INTRA, // 9
63 INTRA_PLUS_NON_INTRA, // 10
64 INVALID_CASE, // 11
65 INTRA_PLUS_NON_INTRA, // 12
66 INVALID_CASE, // 13
67 INVALID_CASE, // 14
68 INVALID_CASE, // 15
69 INVALID_CASE, // 16
70 INVALID_CASE, // 17
71 BOTH_INTRA // 18
72 };
74 static const MV mv_ref_blocks[BLOCK_SIZES][MVREF_NEIGHBOURS] = {
75 // 4X4
76 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
77 // 4X8
78 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
79 // 8X4
80 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
81 // 8X8
82 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}},
83 // 8X16
84 {{0, -1}, {-1, 0}, {1, -1}, {-1, -1}, {0, -2}, {-2, 0}, {-2, -1}, {-1, -2}},
85 // 16X8
86 {{-1, 0}, {0, -1}, {-1, 1}, {-1, -1}, {-2, 0}, {0, -2}, {-1, -2}, {-2, -1}},
87 // 16X16
88 {{-1, 0}, {0, -1}, {-1, 1}, {1, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
89 // 16X32
90 {{0, -1}, {-1, 0}, {2, -1}, {-1, -1}, {-1, 1}, {0, -3}, {-3, 0}, {-3, -3}},
91 // 32X16
92 {{-1, 0}, {0, -1}, {-1, 2}, {-1, -1}, {1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
93 // 32X32
94 {{-1, 1}, {1, -1}, {-1, 2}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
95 // 32X64
96 {{0, -1}, {-1, 0}, {4, -1}, {-1, 2}, {-1, -1}, {0, -3}, {-3, 0}, {2, -1}},
97 // 64X32
98 {{-1, 0}, {0, -1}, {-1, 4}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-1, 2}},
99 // 64X64
100 {{-1, 3}, {3, -1}, {-1, 4}, {4, -1}, {-1, -1}, {-1, 0}, {0, -1}, {-1, 6}}
101 };
103 static const int idx_n_column_to_subblock[4][2] = {
104 {1, 2},
105 {1, 3},
106 {3, 2},
107 {3, 3}
108 };
110 // clamp_mv_ref
111 #define MV_BORDER (16 << 3) // Allow 16 pels in 1/8th pel units
113 static void clamp_mv_ref(MV *mv, const MACROBLOCKD *xd) {
114 clamp_mv(mv, xd->mb_to_left_edge - MV_BORDER,
115 xd->mb_to_right_edge + MV_BORDER,
116 xd->mb_to_top_edge - MV_BORDER,
117 xd->mb_to_bottom_edge + MV_BORDER);
118 }
120 // This function returns either the appropriate sub block or block's mv
121 // on whether the block_size < 8x8 and we have check_sub_blocks set.
122 static INLINE int_mv get_sub_block_mv(const MODE_INFO *candidate, int which_mv,
123 int search_col, int block_idx) {
124 return block_idx >= 0 && candidate->mbmi.sb_type < BLOCK_8X8
125 ? candidate->bmi[idx_n_column_to_subblock[block_idx][search_col == 0]]
126 .as_mv[which_mv]
127 : candidate->mbmi.mv[which_mv];
128 }
131 // Performs mv sign inversion if indicated by the reference frame combination.
132 static INLINE int_mv scale_mv(const MB_MODE_INFO *mbmi, int ref,
133 const MV_REFERENCE_FRAME this_ref_frame,
134 const int *ref_sign_bias) {
135 int_mv mv = mbmi->mv[ref];
136 if (ref_sign_bias[mbmi->ref_frame[ref]] != ref_sign_bias[this_ref_frame]) {
137 mv.as_mv.row *= -1;
138 mv.as_mv.col *= -1;
139 }
140 return mv;
141 }
143 // This macro is used to add a motion vector mv_ref list if it isn't
144 // already in the list. If it's the second motion vector it will also
145 // skip all additional processing and jump to done!
146 #define ADD_MV_REF_LIST(MV) \
147 do { \
148 if (refmv_count) { \
149 if ((MV).as_int != mv_ref_list[0].as_int) { \
150 mv_ref_list[refmv_count] = (MV); \
151 goto Done; \
152 } \
153 } else { \
154 mv_ref_list[refmv_count++] = (MV); \
155 } \
156 } while (0)
158 // If either reference frame is different, not INTRA, and they
159 // are different from each other scale and add the mv to our list.
160 #define IF_DIFF_REF_FRAME_ADD_MV(CANDIDATE) \
161 do { \
162 if ((CANDIDATE)->ref_frame[0] != ref_frame) \
163 ADD_MV_REF_LIST(scale_mv((CANDIDATE), 0, ref_frame, ref_sign_bias)); \
164 if ((CANDIDATE)->ref_frame[1] != ref_frame && \
165 has_second_ref(CANDIDATE) && \
166 (CANDIDATE)->mv[1].as_int != (CANDIDATE)->mv[0].as_int) \
167 ADD_MV_REF_LIST(scale_mv((CANDIDATE), 1, ref_frame, ref_sign_bias)); \
168 } while (0)
171 // Checks that the given mi_row, mi_col and search point
172 // are inside the borders of the tile.
173 static INLINE int is_inside(const TileInfo *const tile,
174 int mi_col, int mi_row, int mi_rows,
175 const MV *mv) {
176 return !(mi_row + mv->row < 0 ||
177 mi_col + mv->col < tile->mi_col_start ||
178 mi_row + mv->row >= mi_rows ||
179 mi_col + mv->col >= tile->mi_col_end);
180 }
182 // This function searches the neighbourhood of a given MB/SB
183 // to try and find candidate reference vectors.
184 void vp9_find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd,
185 const TileInfo *const tile,
186 MODE_INFO *mi, const MODE_INFO *prev_mi,
187 MV_REFERENCE_FRAME ref_frame,
188 int_mv *mv_ref_list,
189 int block_idx,
190 int mi_row, int mi_col) {
191 const int *ref_sign_bias = cm->ref_frame_sign_bias;
192 int i, refmv_count = 0;
193 const MV *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
194 const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->mbmi : NULL;
195 int different_ref_found = 0;
196 int context_counter = 0;
198 // Blank the reference vector list
199 vpx_memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
201 // The nearest 2 blocks are treated differently
202 // if the size < 8x8 we get the mv from the bmi substructure,
203 // and we also need to keep a mode count.
204 for (i = 0; i < 2; ++i) {
205 const MV *const mv_ref = &mv_ref_search[i];
206 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
207 const MODE_INFO *const candidate_mi = xd->mi_8x8[mv_ref->col + mv_ref->row
208 * xd->mode_info_stride];
209 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
210 // Keep counts for entropy encoding.
211 context_counter += mode_2_counter[candidate->mode];
213 // Check if the candidate comes from the same reference frame.
214 if (candidate->ref_frame[0] == ref_frame) {
215 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0,
216 mv_ref->col, block_idx));
217 different_ref_found = candidate->ref_frame[1] != ref_frame;
218 } else {
219 if (candidate->ref_frame[1] == ref_frame)
220 // Add second motion vector if it has the same ref_frame.
221 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1,
222 mv_ref->col, block_idx));
223 different_ref_found = 1;
224 }
225 }
226 }
228 // Check the rest of the neighbors in much the same way
229 // as before except we don't need to keep track of sub blocks or
230 // mode counts.
231 for (; i < MVREF_NEIGHBOURS; ++i) {
232 const MV *const mv_ref = &mv_ref_search[i];
233 if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
234 const MB_MODE_INFO *const candidate = &xd->mi_8x8[mv_ref->col +
235 mv_ref->row
236 * xd->mode_info_stride]->mbmi;
238 if (candidate->ref_frame[0] == ref_frame) {
239 ADD_MV_REF_LIST(candidate->mv[0]);
240 different_ref_found = candidate->ref_frame[1] != ref_frame;
241 } else {
242 if (candidate->ref_frame[1] == ref_frame)
243 ADD_MV_REF_LIST(candidate->mv[1]);
244 different_ref_found = 1;
245 }
246 }
247 }
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 }
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 MV *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_8x8[mv_ref->col +
265 mv_ref->row
266 * xd->mode_info_stride]->mbmi;
268 // If the candidate is INTRA we don't want to consider its mv.
269 if (is_inter_block(candidate))
270 IF_DIFF_REF_FRAME_ADD_MV(candidate);
271 }
272 }
273 }
275 // Since we still don't have a candidate we'll try the last frame.
276 if (prev_mbmi && is_inter_block(prev_mbmi))
277 IF_DIFF_REF_FRAME_ADD_MV(prev_mbmi);
279 Done:
281 mi->mbmi.mode_context[ref_frame] = counter_to_context[context_counter];
283 // Clamp vectors
284 for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i)
285 clamp_mv_ref(&mv_ref_list[i].as_mv, xd);
286 }