Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: source/libvpx/vp9/common/vp9_mvref_common.c

Issue 11555023: libvpx: Add VP9 decoder. (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 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 "vp9/common/vp9_mvref_common.h"
12
13 #define MVREF_NEIGHBOURS 8
14 static int mb_mv_ref_search[MVREF_NEIGHBOURS][2] = {
15 {0, -1}, {-1, 0}, {-1, -1}, {0, -2},
16 {-2, 0}, {-1, -2}, {-2, -1}, {-2, -2}
17 };
18 static int mb_ref_distance_weight[MVREF_NEIGHBOURS] =
19 { 3, 3, 2, 1, 1, 1, 1, 1 };
20 #if CONFIG_SUPERBLOCKS
21 static int sb_mv_ref_search[MVREF_NEIGHBOURS][2] = {
22 {0, -1}, {-1, 0}, {1, -1}, {-1, 1},
23 {-1, -1}, {0, -2}, {-2, 0}, {-1, -2}
24 };
25 static int sb_ref_distance_weight[MVREF_NEIGHBOURS] =
26 { 3, 3, 2, 2, 2, 1, 1, 1 };
27 #endif
28 // clamp_mv
29 #define MV_BORDER (16 << 3) // Allow 16 pels in 1/8th pel units
30 static void clamp_mv(const MACROBLOCKD *xd, int_mv *mv) {
31
32 if (mv->as_mv.col < (xd->mb_to_left_edge - MV_BORDER))
33 mv->as_mv.col = xd->mb_to_left_edge - MV_BORDER;
34 else if (mv->as_mv.col > xd->mb_to_right_edge + MV_BORDER)
35 mv->as_mv.col = xd->mb_to_right_edge + MV_BORDER;
36
37 if (mv->as_mv.row < (xd->mb_to_top_edge - MV_BORDER))
38 mv->as_mv.row = xd->mb_to_top_edge - MV_BORDER;
39 else if (mv->as_mv.row > xd->mb_to_bottom_edge + MV_BORDER)
40 mv->as_mv.row = xd->mb_to_bottom_edge + MV_BORDER;
41 }
42
43
44 // Gets a best matching candidate refenence motion vector
45 // from the given mode info structure (if available)
46 static int get_candidate_mvref(
47 const MODE_INFO *candidate_mi,
48 MV_REFERENCE_FRAME ref_frame,
49 MV_REFERENCE_FRAME *c_ref_frame,
50 int_mv *c_mv,
51 MV_REFERENCE_FRAME *c2_ref_frame,
52 int_mv *c2_mv
53 ) {
54
55 int ret_val = FALSE;
56 c2_mv->as_int = 0;
57 *c2_ref_frame = INTRA_FRAME;
58
59 // Target ref frame matches candidate first ref frame
60 if (ref_frame == candidate_mi->mbmi.ref_frame) {
61 c_mv->as_int = candidate_mi->mbmi.mv[0].as_int;
62 *c_ref_frame = ref_frame;
63 ret_val = TRUE;
64
65 // Is there a second non zero vector we can use.
66 if ((candidate_mi->mbmi.second_ref_frame > INTRA_FRAME) &&
67 (candidate_mi->mbmi.mv[1].as_int != 0) &&
68 (candidate_mi->mbmi.mv[1].as_int != c_mv->as_int)) {
69 c2_mv->as_int = candidate_mi->mbmi.mv[1].as_int;
70 *c2_ref_frame = candidate_mi->mbmi.second_ref_frame;
71 }
72
73 // Target ref frame matches candidate second ref frame
74 } else if (ref_frame == candidate_mi->mbmi.second_ref_frame) {
75 c_mv->as_int = candidate_mi->mbmi.mv[1].as_int;
76 *c_ref_frame = ref_frame;
77 ret_val = TRUE;
78
79 // Is there a second non zero vector we can use.
80 if ((candidate_mi->mbmi.ref_frame > INTRA_FRAME) &&
81 (candidate_mi->mbmi.mv[0].as_int != 0) &&
82 (candidate_mi->mbmi.mv[0].as_int != c_mv->as_int)) {
83 c2_mv->as_int = candidate_mi->mbmi.mv[0].as_int;
84 *c2_ref_frame = candidate_mi->mbmi.ref_frame;
85 }
86
87 // No ref frame matches so use first ref mv as first choice
88 } else if (candidate_mi->mbmi.ref_frame > INTRA_FRAME) {
89 c_mv->as_int = candidate_mi->mbmi.mv[0].as_int;
90 *c_ref_frame = candidate_mi->mbmi.ref_frame;
91 ret_val = TRUE;
92
93 // Is there a second non zero vector we can use.
94 if ((candidate_mi->mbmi.second_ref_frame > INTRA_FRAME) &&
95 (candidate_mi->mbmi.mv[1].as_int != 0) &&
96 (candidate_mi->mbmi.mv[1].as_int != c_mv->as_int)) {
97 c2_mv->as_int = candidate_mi->mbmi.mv[1].as_int;
98 *c2_ref_frame = candidate_mi->mbmi.second_ref_frame;
99 }
100
101 // If only the second ref mv is valid:- (Should not trigger in current code
102 // base given current possible compound prediction options).
103 } else if (candidate_mi->mbmi.second_ref_frame > INTRA_FRAME) {
104 c_mv->as_int = candidate_mi->mbmi.mv[1].as_int;
105 *c_ref_frame = candidate_mi->mbmi.second_ref_frame;
106 ret_val = TRUE;
107 }
108
109 return ret_val;
110 }
111
112 // Performs mv adjustment based on reference frame and clamps the MV
113 // if it goes off the edge of the buffer.
114 static void scale_mv(
115 MACROBLOCKD *xd,
116 MV_REFERENCE_FRAME this_ref_frame,
117 MV_REFERENCE_FRAME candidate_ref_frame,
118 int_mv *candidate_mv,
119 int *ref_sign_bias
120 ) {
121
122 if (candidate_ref_frame != this_ref_frame) {
123
124 //int frame_distances[MAX_REF_FRAMES];
125 //int last_distance = 1;
126 //int gf_distance = xd->frames_since_golden;
127 //int arf_distance = xd->frames_till_alt_ref_frame;
128
129 // Sign inversion where appropriate.
130 if (ref_sign_bias[candidate_ref_frame] != ref_sign_bias[this_ref_frame]) {
131 candidate_mv->as_mv.row = -candidate_mv->as_mv.row;
132 candidate_mv->as_mv.col = -candidate_mv->as_mv.col;
133 }
134
135 // Scale based on frame distance if the reference frames not the same.
136 /*frame_distances[INTRA_FRAME] = 1; // should never be used
137 frame_distances[LAST_FRAME] = 1;
138 frame_distances[GOLDEN_FRAME] =
139 (xd->frames_since_golden) ? xd->frames_since_golden : 1;
140 frame_distances[ALTREF_FRAME] =
141 (xd->frames_till_alt_ref_frame) ? xd->frames_till_alt_ref_frame : 1;
142
143 if (frame_distances[this_ref_frame] &&
144 frame_distances[candidate_ref_frame]) {
145 candidate_mv->as_mv.row =
146 (short)(((int)(candidate_mv->as_mv.row) *
147 frame_distances[this_ref_frame]) /
148 frame_distances[candidate_ref_frame]);
149
150 candidate_mv->as_mv.col =
151 (short)(((int)(candidate_mv->as_mv.col) *
152 frame_distances[this_ref_frame]) /
153 frame_distances[candidate_ref_frame]);
154 }
155 */
156 }
157
158 // Clamp the MV so it does not point out of the frame buffer
159 clamp_mv(xd, candidate_mv);
160 }
161
162 // Adds a new candidate reference vector to the list if indeed it is new.
163 // If it is not new then the score of the existing candidate that it matches
164 // is increased and the list is resorted.
165 static void addmv_and_shuffle(
166 int_mv *mv_list,
167 int *mv_scores,
168 int *index,
169 int_mv candidate_mv,
170 int weight
171 ) {
172
173 int i = *index;
174 int duplicate_found = FALSE;
175
176 // Check for duplicates. If there is one increment its score.
177 // Duplicate defined as being the same full pel vector with rounding.
178 while (i > 0) {
179 i--;
180
181 if (candidate_mv.as_int == mv_list[i].as_int) {
182 duplicate_found = TRUE;
183 mv_scores[i] += weight;
184 break;
185 }
186 }
187
188 // If no duplicate was found add the new vector and give it a weight
189 if (!duplicate_found) {
190 mv_list[*index].as_int = candidate_mv.as_int;
191 mv_scores[*index] = weight;
192 i = *index;
193 (*index)++;
194 }
195
196 // Reshuffle the list so that highest scoring mvs at the top.
197 while (i > 0) {
198 if (mv_scores[i] > mv_scores[i-1]) {
199 int tmp_score = mv_scores[i-1];
200 int_mv tmp_mv = mv_list[i-1];
201
202 mv_scores[i-1] = mv_scores[i];
203 mv_list[i-1] = mv_list[i];
204 mv_scores[i] = tmp_score;
205 mv_list[i] = tmp_mv;
206 i--;
207 } else
208 break;
209 }
210 }
211
212 // This function searches the neighbourhood of a given MB/SB and populates a
213 // list of candidate reference vectors.
214 //
215 void vp9_find_mv_refs(
216 MACROBLOCKD *xd,
217 MODE_INFO *here,
218 MODE_INFO *lf_here,
219 MV_REFERENCE_FRAME ref_frame,
220 int_mv *mv_ref_list,
221 int *ref_sign_bias
222 ) {
223
224 int i;
225 MODE_INFO *candidate_mi;
226 MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
227 int_mv candidate_mvs[MAX_MV_REFS];
228 int_mv c_refmv;
229 MV_REFERENCE_FRAME c_ref_frame;
230 int_mv c2_refmv;
231 MV_REFERENCE_FRAME c2_ref_frame;
232 int candidate_scores[MAX_MV_REFS];
233 int index = 0;
234 int split_count = 0;
235 int ref_weight = 0;
236 int valid_mv_ref;
237 int (*mv_ref_search)[2];
238 int *ref_distance_weight;
239
240 // Blank the reference vector lists and other local structures.
241 vpx_memset(mv_ref_list, 0, sizeof(int_mv) * MAX_MV_REFS);
242 vpx_memset(candidate_mvs, 0, sizeof(int_mv) * MAX_MV_REFS);
243 vpx_memset(candidate_scores, 0, sizeof(candidate_scores));
244
245 #if CONFIG_SUPERBLOCKS
246 if (mbmi->encoded_as_sb) {
247 mv_ref_search = sb_mv_ref_search;
248 ref_distance_weight = sb_ref_distance_weight;
249 } else {
250 mv_ref_search = mb_mv_ref_search;
251 ref_distance_weight = mb_ref_distance_weight;
252 }
253 #else
254 mv_ref_search = mb_mv_ref_search;
255 ref_distance_weight = mb_ref_distance_weight;
256 #endif
257 // Populate a list with candidate reference vectors from the
258 // spatial neighbours.
259 for (i = 0; i < 2; ++i) {
260 if (((mv_ref_search[i][0] << 7) >= xd->mb_to_left_edge) &&
261 ((mv_ref_search[i][1] << 7) >= xd->mb_to_top_edge)) {
262
263 candidate_mi = here + mv_ref_search[i][0] +
264 (mv_ref_search[i][1] * xd->mode_info_stride);
265
266 valid_mv_ref = get_candidate_mvref(candidate_mi, ref_frame,
267 &c_ref_frame, &c_refmv,
268 &c2_ref_frame, &c2_refmv);
269
270 // If there is a valid MV candidate then add it to the list
271 if (valid_mv_ref) {
272 scale_mv(xd, ref_frame, c_ref_frame, &c_refmv, ref_sign_bias );
273 ref_weight = ref_distance_weight[i] +
274 ((c_ref_frame == ref_frame) << 4);
275 split_count += (candidate_mi->mbmi.mode == SPLITMV);
276
277 addmv_and_shuffle(candidate_mvs, candidate_scores,
278 &index, c_refmv, ref_weight);
279
280 // If there is a second valid mv then add it as well.
281 if (c2_ref_frame > INTRA_FRAME) {
282 scale_mv(xd, ref_frame, c2_ref_frame, &c2_refmv, ref_sign_bias );
283 ref_weight = ref_distance_weight[i] +
284 ((c2_ref_frame == ref_frame) << 4);
285
286 addmv_and_shuffle(candidate_mvs, candidate_scores,
287 &index, c2_refmv, ref_weight);
288 }
289 }
290 }
291 }
292
293 // Look at the corresponding vector in the last frame
294 candidate_mi = lf_here;
295 valid_mv_ref = get_candidate_mvref(candidate_mi, ref_frame,
296 &c_ref_frame, &c_refmv,
297 &c2_ref_frame, &c2_refmv);
298
299 // If there is a valid MV candidate then add it to the list
300 if (valid_mv_ref) {
301 scale_mv(xd, ref_frame, c_ref_frame, &c_refmv, ref_sign_bias );
302 ref_weight = 2 + ((c_ref_frame == ref_frame) << 4);
303 addmv_and_shuffle(candidate_mvs, candidate_scores,
304 &index, c_refmv, ref_weight);
305
306 // If there is a second valid mv then add it as well.
307 if (c2_ref_frame > INTRA_FRAME) {
308 scale_mv(xd, ref_frame, c2_ref_frame, &c2_refmv, ref_sign_bias );
309 ref_weight = ref_distance_weight[i] +
310 ((c2_ref_frame == ref_frame) << 4);
311
312 addmv_and_shuffle(candidate_mvs, candidate_scores,
313 &index, c2_refmv, ref_weight);
314 }
315 }
316
317 // Populate a list with candidate reference vectors from the
318 // spatial neighbours.
319 for (i = 2; (i < MVREF_NEIGHBOURS) && (index < (MAX_MV_REFS - 2)); ++i) {
320 if (((mv_ref_search[i][0] << 7) >= xd->mb_to_left_edge) &&
321 ((mv_ref_search[i][1] << 7) >= xd->mb_to_top_edge)) {
322
323 candidate_mi = here + mv_ref_search[i][0] +
324 (mv_ref_search[i][1] * xd->mode_info_stride);
325
326 valid_mv_ref = get_candidate_mvref(candidate_mi, ref_frame,
327 &c_ref_frame, &c_refmv,
328 &c2_ref_frame, &c2_refmv);
329
330 // If there is a valid MV candidate then add it to the list
331 if (valid_mv_ref) {
332 scale_mv(xd, ref_frame, c_ref_frame, &c_refmv, ref_sign_bias );
333 ref_weight = ref_distance_weight[i] +
334 ((c_ref_frame == ref_frame) << 4);
335
336 addmv_and_shuffle(candidate_mvs, candidate_scores,
337 &index, c_refmv, ref_weight);
338
339 // If there is a second valid mv then add it as well.
340 if (c2_ref_frame > INTRA_FRAME) {
341 scale_mv(xd, ref_frame, c2_ref_frame, &c2_refmv, ref_sign_bias );
342 ref_weight = ref_distance_weight[i] +
343 ((c2_ref_frame == ref_frame) << 4);
344
345 addmv_and_shuffle(candidate_mvs, candidate_scores,
346 &index, c2_refmv, ref_weight);
347 }
348 }
349 }
350 }
351
352 // Make sure we are able to add 0,0
353 if (index > (MAX_MV_REFS - 1)) {
354 index = (MAX_MV_REFS - 1);
355 }
356
357 // Define inter mode coding context.
358 // 0,0 was best
359 if (candidate_mvs[0].as_int == 0) {
360 // 0,0 is only candidate
361 if (index <= 1) {
362 mbmi->mb_mode_context[ref_frame] = 0;
363 // non zero candidates candidates available
364 } else if (split_count == 0) {
365 mbmi->mb_mode_context[ref_frame] = 1;
366 } else {
367 mbmi->mb_mode_context[ref_frame] = 2;
368 }
369 // Non zero best, No Split MV cases
370 } else if (split_count == 0) {
371 if (candidate_scores[0] >= 32) {
372 mbmi->mb_mode_context[ref_frame] = 3;
373 } else {
374 mbmi->mb_mode_context[ref_frame] = 4;
375 }
376 // Non zero best, some split mv
377 } else {
378 if (candidate_scores[0] >= 32) {
379 mbmi->mb_mode_context[ref_frame] = 5;
380 } else {
381 mbmi->mb_mode_context[ref_frame] = 6;
382 }
383 }
384
385 // 0,0 is always a valid reference.
386 for (i = 0; i < index; ++i) {
387 if (candidate_mvs[i].as_int == 0)
388 break;
389 }
390 if (i == index) {
391 c_refmv.as_int = 0;
392 addmv_and_shuffle(candidate_mvs, candidate_scores,
393 &index, c_refmv, candidate_scores[3]+1 );
394 }
395
396 // Copy over the candidate list.
397 vpx_memcpy(mv_ref_list, candidate_mvs, sizeof(candidate_mvs));
398 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698