OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "vp9/common/vp9_mvref_common.h" | 11 #include "vp9/common/vp9_mvref_common.h" |
12 | 12 |
13 #define MVREF_NEIGHBOURS 8 | 13 #define MVREF_NEIGHBOURS 8 |
14 static const int mv_ref_blocks[BLOCK_SIZE_TYPES][MVREF_NEIGHBOURS][2] = { | 14 |
15 // SB4X4 | 15 typedef enum { |
16 {{0, -1}, {-1, 0}, {-1, -1}, {0, -2}, {-2, 0}, {-1, -2}, {-2, -1}, {-2, -2}}, | 16 BOTH_ZERO = 0, |
17 // SB4X8 | 17 ZERO_PLUS_PREDICTED = 1, |
18 {{0, -1}, {-1, 0}, {-1, -1}, {0, -2}, {-2, 0}, {-1, -2}, {-2, -1}, {-2, -2}}, | 18 BOTH_PREDICTED = 2, |
19 // SB8X4 | 19 NEW_PLUS_NON_INTRA = 3, |
20 {{0, -1}, {-1, 0}, {-1, -1}, {0, -2}, {-2, 0}, {-1, -2}, {-2, -1}, {-2, -2}}, | 20 BOTH_NEW = 4, |
21 // SB8X8 | 21 INTRA_PLUS_NON_INTRA = 5, |
22 {{0, -1}, {-1, 0}, {-1, -1}, {0, -2}, {-2, 0}, {-1, -2}, {-2, -1}, {-2, -2}}, | 22 BOTH_INTRA = 6, |
23 // SB8X16 | 23 INVALID_CASE = 9 |
| 24 } motion_vector_context; |
| 25 |
| 26 // This is used to figure out a context for the ref blocks. The code flattens |
| 27 // an array that would have 3 possible counts (0, 1 & 2) for 3 choices by |
| 28 // adding 9 for each intra block, 3 for each zero mv and 1 for each new |
| 29 // motion vector. This single number is then converted into a context |
| 30 // with a single lookup ( counter_to_context ). |
| 31 static const int mode_2_counter[MB_MODE_COUNT] = { |
| 32 9, // DC_PRED |
| 33 9, // V_PRED |
| 34 9, // H_PRED |
| 35 9, // D45_PRED |
| 36 9, // D135_PRED |
| 37 9, // D117_PRED |
| 38 9, // D153_PRED |
| 39 9, // D207_PRED |
| 40 9, // D63_PRED |
| 41 9, // TM_PRED |
| 42 0, // NEARESTMV |
| 43 0, // NEARMV |
| 44 3, // ZEROMV |
| 45 1, // NEWMV |
| 46 }; |
| 47 |
| 48 // There are 3^3 different combinations of 3 counts that can be either 0,1 or |
| 49 // 2. However the actual count can never be greater than 2 so the highest |
| 50 // counter we need is 18. 9 is an invalid counter that's never used. |
| 51 static const int counter_to_context[19] = { |
| 52 BOTH_PREDICTED, // 0 |
| 53 NEW_PLUS_NON_INTRA, // 1 |
| 54 BOTH_NEW, // 2 |
| 55 ZERO_PLUS_PREDICTED, // 3 |
| 56 NEW_PLUS_NON_INTRA, // 4 |
| 57 INVALID_CASE, // 5 |
| 58 BOTH_ZERO, // 6 |
| 59 INVALID_CASE, // 7 |
| 60 INVALID_CASE, // 8 |
| 61 INTRA_PLUS_NON_INTRA, // 9 |
| 62 INTRA_PLUS_NON_INTRA, // 10 |
| 63 INVALID_CASE, // 11 |
| 64 INTRA_PLUS_NON_INTRA, // 12 |
| 65 INVALID_CASE, // 13 |
| 66 INVALID_CASE, // 14 |
| 67 INVALID_CASE, // 15 |
| 68 INVALID_CASE, // 16 |
| 69 INVALID_CASE, // 17 |
| 70 BOTH_INTRA // 18 |
| 71 }; |
| 72 |
| 73 static const MV mv_ref_blocks[BLOCK_SIZES][MVREF_NEIGHBOURS] = { |
| 74 // 4X4 |
| 75 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}}, |
| 76 // 4X8 |
| 77 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}}, |
| 78 // 8X4 |
| 79 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}}, |
| 80 // 8X8 |
| 81 {{-1, 0}, {0, -1}, {-1, -1}, {-2, 0}, {0, -2}, {-2, -1}, {-1, -2}, {-2, -2}}, |
| 82 // 8X16 |
| 83 {{0, -1}, {-1, 0}, {1, -1}, {-1, -1}, {0, -2}, {-2, 0}, {-2, -1}, {-1, -2}}, |
| 84 // 16X8 |
24 {{-1, 0}, {0, -1}, {-1, 1}, {-1, -1}, {-2, 0}, {0, -2}, {-1, -2}, {-2, -1}}, | 85 {{-1, 0}, {0, -1}, {-1, 1}, {-1, -1}, {-2, 0}, {0, -2}, {-1, -2}, {-2, -1}}, |
25 // SB16X8 | 86 // 16X16 |
26 {{0, -1}, {-1, 0}, {1, -1}, {-1, -1}, {0, -2}, {-2, 0}, {-2, -1}, {-1, -2}}, | 87 {{-1, 0}, {0, -1}, {-1, 1}, {1, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}}, |
27 // SB16X16 | 88 // 16X32 |
28 {{0, -1}, {-1, 0}, {1, -1}, {-1, 1}, {-1, -1}, {0, -3}, {-3, 0}, {-3, -3}}, | 89 {{0, -1}, {-1, 0}, {2, -1}, {-1, -1}, {-1, 1}, {0, -3}, {-3, 0}, {-3, -3}}, |
29 // SB16X32 | 90 // 32X16 |
30 {{-1, 0}, {0, -1}, {-1, 2}, {-1, -1}, {1, -1}, {-3, 0}, {0, -3}, {-3, -3}}, | 91 {{-1, 0}, {0, -1}, {-1, 2}, {-1, -1}, {1, -1}, {-3, 0}, {0, -3}, {-3, -3}}, |
31 // SB32X16 | 92 // 32X32 |
32 {{0, -1}, {-1, 0}, {2, -1}, {-1, -1}, {-1, 1}, {0, -3}, {-3, 0}, {-3, -3}}, | 93 {{-1, 1}, {1, -1}, {-1, 2}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-3, -3}}, |
33 // SB32X32 | 94 // 32X64 |
34 {{1, -1}, {-1, 1}, {2, -1}, {-1, 2}, {-1, -1}, {0, -3}, {-3, 0}, {-3, -3}}, | 95 {{0, -1}, {-1, 0}, {4, -1}, {-1, 2}, {-1, -1}, {0, -3}, {-3, 0}, {2, -1}}, |
35 // SB32X64 | 96 // 64X32 |
36 {{-1, 0}, {0, -1}, {-1, 4}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-1, 2}}, | 97 {{-1, 0}, {0, -1}, {-1, 4}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-1, 2}}, |
37 // SB64X32 | 98 // 64X64 |
38 {{0, -1}, {-1, 0}, {4, -1}, {-1, 2}, {-1, -1}, {0, -3}, {-3, 0}, {2, -1}}, | 99 {{-1, 3}, {3, -1}, {-1, 4}, {4, -1}, {-1, -1}, {-1, 0}, {0, -1}, {-1, 6}} |
39 // SB64X64 | 100 }; |
40 {{3, -1}, {-1, 3}, {4, -1}, {-1, 4}, {-1, -1}, {0, -1}, {-1, 0}, {6, -1}} | 101 |
41 }; | 102 static const int idx_n_column_to_subblock[4][2] = { |
| 103 {1, 2}, |
| 104 {1, 3}, |
| 105 {3, 2}, |
| 106 {3, 3} |
| 107 }; |
| 108 |
42 // clamp_mv_ref | 109 // clamp_mv_ref |
43 #define MV_BORDER (16 << 3) // Allow 16 pels in 1/8th pel units | 110 #define MV_BORDER (16 << 3) // Allow 16 pels in 1/8th pel units |
44 | 111 |
45 static void clamp_mv_ref(const MACROBLOCKD *xd, int_mv *mv) { | 112 static void clamp_mv_ref(MV *mv, const MACROBLOCKD *xd) { |
46 mv->as_mv.col = clamp(mv->as_mv.col, xd->mb_to_left_edge - MV_BORDER, | 113 clamp_mv(mv, xd->mb_to_left_edge - MV_BORDER, |
47 xd->mb_to_right_edge + MV_BORDER); | 114 xd->mb_to_right_edge + MV_BORDER, |
48 mv->as_mv.row = clamp(mv->as_mv.row, xd->mb_to_top_edge - MV_BORDER, | 115 xd->mb_to_top_edge - MV_BORDER, |
49 xd->mb_to_bottom_edge + MV_BORDER); | 116 xd->mb_to_bottom_edge + MV_BORDER); |
50 } | 117 } |
51 | 118 |
52 // Gets a candidate reference motion vector from the given mode info | 119 // This function returns either the appropriate sub block or block's mv |
53 // structure if one exists that matches the given reference frame. | 120 // on whether the block_size < 8x8 and we have check_sub_blocks set. |
54 static int get_matching_candidate(const MODE_INFO *candidate_mi, | 121 static INLINE int_mv get_sub_block_mv(const MODE_INFO *candidate, |
55 MV_REFERENCE_FRAME ref_frame, | 122 int check_sub_blocks, int which_mv, |
56 int_mv *c_mv, int block_idx) { | 123 int search_col, int block_idx) { |
57 if (ref_frame == candidate_mi->mbmi.ref_frame[0]) { | 124 return check_sub_blocks && candidate->mbmi.sb_type < BLOCK_8X8 |
58 if (block_idx >= 0 && candidate_mi->mbmi.sb_type < BLOCK_SIZE_SB8X8) | 125 ? candidate->bmi[idx_n_column_to_subblock[block_idx][search_col == 0]] |
59 c_mv->as_int = candidate_mi->bmi[block_idx].as_mv[0].as_int; | 126 .as_mv[which_mv] |
60 else | 127 : candidate->mbmi.mv[which_mv]; |
61 c_mv->as_int = candidate_mi->mbmi.mv[0].as_int; | |
62 } else if (ref_frame == candidate_mi->mbmi.ref_frame[1]) { | |
63 if (block_idx >= 0 && candidate_mi->mbmi.sb_type < BLOCK_SIZE_SB8X8) | |
64 c_mv->as_int = candidate_mi->bmi[block_idx].as_mv[1].as_int; | |
65 else | |
66 c_mv->as_int = candidate_mi->mbmi.mv[1].as_int; | |
67 } else { | |
68 return 0; | |
69 } | |
70 | |
71 return 1; | |
72 } | |
73 | |
74 // Gets candidate reference motion vector(s) from the given mode info | |
75 // structure if they exists and do NOT match the given reference frame. | |
76 static void get_non_matching_candidates(const MODE_INFO *candidate_mi, | |
77 MV_REFERENCE_FRAME ref_frame, | |
78 MV_REFERENCE_FRAME *c_ref_frame, | |
79 int_mv *c_mv, | |
80 MV_REFERENCE_FRAME *c2_ref_frame, | |
81 int_mv *c2_mv) { | |
82 | |
83 c_mv->as_int = 0; | |
84 c2_mv->as_int = 0; | |
85 *c_ref_frame = INTRA_FRAME; | |
86 *c2_ref_frame = INTRA_FRAME; | |
87 | |
88 // If first candidate not valid neither will be. | |
89 if (candidate_mi->mbmi.ref_frame[0] > INTRA_FRAME) { | |
90 // First candidate | |
91 if (candidate_mi->mbmi.ref_frame[0] != ref_frame) { | |
92 *c_ref_frame = candidate_mi->mbmi.ref_frame[0]; | |
93 c_mv->as_int = candidate_mi->mbmi.mv[0].as_int; | |
94 } | |
95 | |
96 // Second candidate | |
97 if ((candidate_mi->mbmi.ref_frame[1] > INTRA_FRAME) && | |
98 (candidate_mi->mbmi.ref_frame[1] != ref_frame) && | |
99 (candidate_mi->mbmi.mv[1].as_int != candidate_mi->mbmi.mv[0].as_int)) { | |
100 *c2_ref_frame = candidate_mi->mbmi.ref_frame[1]; | |
101 c2_mv->as_int = candidate_mi->mbmi.mv[1].as_int; | |
102 } | |
103 } | |
104 } | 128 } |
105 | 129 |
106 | 130 |
107 // Performs mv sign inversion if indicated by the reference frame combination. | 131 // Performs mv sign inversion if indicated by the reference frame combination. |
108 static void scale_mv(MACROBLOCKD *xd, MV_REFERENCE_FRAME this_ref_frame, | 132 static INLINE int_mv scale_mv(const MB_MODE_INFO *mbmi, int ref, |
109 MV_REFERENCE_FRAME candidate_ref_frame, | 133 const MV_REFERENCE_FRAME this_ref_frame, |
110 int_mv *candidate_mv, int *ref_sign_bias) { | 134 const int *ref_sign_bias) { |
111 | 135 int_mv mv = mbmi->mv[ref]; |
112 // Sign inversion where appropriate. | 136 if (ref_sign_bias[mbmi->ref_frame[ref]] != ref_sign_bias[this_ref_frame]) { |
113 if (ref_sign_bias[candidate_ref_frame] != ref_sign_bias[this_ref_frame]) { | 137 mv.as_mv.row *= -1; |
114 candidate_mv->as_mv.row = -candidate_mv->as_mv.row; | 138 mv.as_mv.col *= -1; |
115 candidate_mv->as_mv.col = -candidate_mv->as_mv.col; | 139 } |
116 } | 140 return mv; |
117 } | 141 } |
118 | 142 |
119 // Add a candidate mv. | 143 // This macro is used to add a motion vector mv_ref list if it isn't |
120 // Discard if it has already been seen. | 144 // already in the list. If it's the second motion vector it will also |
121 static void add_candidate_mv(int_mv *mv_list, int *mv_scores, | 145 // skip all additional processing and jump to done! |
122 int *candidate_count, int_mv candidate_mv, | 146 #define ADD_MV_REF_LIST(MV) \ |
123 int weight) { | 147 do { \ |
124 if (*candidate_count == 0) { | 148 if (refmv_count) { \ |
125 mv_list[0].as_int = candidate_mv.as_int; | 149 if ((MV).as_int != mv_ref_list[0].as_int) { \ |
126 mv_scores[0] = weight; | 150 mv_ref_list[refmv_count] = (MV); \ |
127 *candidate_count += 1; | 151 goto Done; \ |
128 } else if ((*candidate_count == 1) && | 152 } \ |
129 (candidate_mv.as_int != mv_list[0].as_int)) { | 153 } else { \ |
130 mv_list[1].as_int = candidate_mv.as_int; | 154 mv_ref_list[refmv_count++] = (MV); \ |
131 mv_scores[1] = weight; | 155 } \ |
132 *candidate_count += 1; | 156 } while (0) |
133 } | 157 |
| 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) |
| 169 |
| 170 |
| 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 VP9_COMMON *cm, int mi_col, int mi_row, |
| 174 const MV *mv) { |
| 175 return !(mi_row + mv->row < 0 || |
| 176 mi_col + mv->col < cm->cur_tile_mi_col_start || |
| 177 mi_row + mv->row >= cm->mi_rows || |
| 178 mi_col + mv->col >= cm->cur_tile_mi_col_end); |
134 } | 179 } |
135 | 180 |
136 // This function searches the neighbourhood of a given MB/SB | 181 // This function searches the neighbourhood of a given MB/SB |
137 // to try and find candidate reference vectors. | 182 // to try and find candidate reference vectors. |
138 // | 183 void vp9_find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd, |
139 void vp9_find_mv_refs_idx(VP9_COMMON *cm, MACROBLOCKD *xd, MODE_INFO *here, | 184 MODE_INFO *mi, const MODE_INFO *prev_mi, |
140 MODE_INFO *lf_here, MV_REFERENCE_FRAME ref_frame, | 185 MV_REFERENCE_FRAME ref_frame, |
141 int_mv *mv_ref_list, int *ref_sign_bias, | 186 int_mv *mv_ref_list, |
142 int block_idx) { | 187 int block_idx, |
143 int i; | 188 int mi_row, int mi_col) { |
144 MODE_INFO *candidate_mi; | 189 const int *ref_sign_bias = cm->ref_frame_sign_bias; |
145 MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi; | 190 int i, refmv_count = 0; |
146 int_mv c_refmv; | 191 const MV *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type]; |
147 int_mv c2_refmv; | 192 const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->mbmi : NULL; |
148 MV_REFERENCE_FRAME c_ref_frame; | 193 int different_ref_found = 0; |
149 MV_REFERENCE_FRAME c2_ref_frame; | 194 int context_counter = 0; |
150 int candidate_scores[MAX_MV_REF_CANDIDATES] = { 0 }; | 195 |
151 int refmv_count = 0; | 196 // Blank the reference vector list |
152 const int (*mv_ref_search)[2] = mv_ref_blocks[mbmi->sb_type]; | 197 vpx_memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES); |
153 const int mi_col = get_mi_col(xd); | 198 |
154 const int mi_row = get_mi_row(xd); | 199 // The nearest 2 blocks are treated differently |
155 int intra_count = 0; | 200 // if the size < 8x8 we get the mv from the bmi substructure, |
156 int zero_count = 0; | 201 // and we also need to keep a mode count. |
157 int newmv_count = 0; | |
158 int x_idx = 0, y_idx = 0; | |
159 | |
160 // Blank the reference vector lists and other local structures. | |
161 vpx_memset(mv_ref_list, 0, sizeof(int_mv) * MAX_MV_REF_CANDIDATES); | |
162 | |
163 if (mbmi->sb_type < BLOCK_SIZE_SB8X8) { | |
164 x_idx = block_idx & 1; | |
165 y_idx = block_idx >> 1; | |
166 } | |
167 | |
168 // We first scan for candidate vectors that match the current reference frame | |
169 // Look at nearest neigbours | |
170 for (i = 0; i < 2; ++i) { | 202 for (i = 0; i < 2; ++i) { |
171 const int mi_search_col = mi_col + mv_ref_search[i][0]; | 203 const MV *const mv_ref = &mv_ref_search[i]; |
172 const int mi_search_row = mi_row + mv_ref_search[i][1]; | 204 if (is_inside(cm, mi_col, mi_row, mv_ref)) { |
173 if ((mi_search_col >= cm->cur_tile_mi_col_start) && | 205 const int check_sub_blocks = block_idx >= 0; |
174 (mi_search_col < cm->cur_tile_mi_col_end) && | 206 const MODE_INFO *const candidate_mi = &mi[mv_ref->col + mv_ref->row |
175 (mi_search_row >= 0) && (mi_search_row < cm->mi_rows)) { | 207 * xd->mode_info_stride]; |
176 int b; | 208 const MB_MODE_INFO *const candidate = &candidate_mi->mbmi; |
177 | 209 // Keep counts for entropy encoding. |
178 candidate_mi = here + mv_ref_search[i][0] + | 210 context_counter += mode_2_counter[candidate->mode]; |
179 (mv_ref_search[i][1] * xd->mode_info_stride); | 211 |
180 | 212 // Check if the candidate comes from the same reference frame. |
181 if (block_idx >= 0) { | 213 if (candidate->ref_frame[0] == ref_frame) { |
182 if (mv_ref_search[i][0]) | 214 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, check_sub_blocks, 0, |
183 b = 1 + y_idx * 2; | 215 mv_ref->col, block_idx)); |
184 else | 216 different_ref_found = candidate->ref_frame[1] != ref_frame; |
185 b = 2 + x_idx; | |
186 } else { | 217 } else { |
187 b = -1; | 218 if (candidate->ref_frame[1] == ref_frame) |
188 } | 219 // Add second motion vector if it has the same ref_frame. |
189 if (get_matching_candidate(candidate_mi, ref_frame, &c_refmv, b)) { | 220 ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, check_sub_blocks, 1, |
190 add_candidate_mv(mv_ref_list, candidate_scores, | 221 mv_ref->col, block_idx)); |
191 &refmv_count, c_refmv, 16); | 222 different_ref_found = 1; |
192 } | |
193 | |
194 // Count number of neihgbours coded intra and zeromv | |
195 intra_count += (candidate_mi->mbmi.mode < NEARESTMV); | |
196 zero_count += (candidate_mi->mbmi.mode == ZEROMV); | |
197 newmv_count += (candidate_mi->mbmi.mode >= NEWMV); | |
198 } | |
199 } | |
200 | |
201 // More distant neigbours | |
202 for (i = 2; (i < MVREF_NEIGHBOURS) && | |
203 (refmv_count < MAX_MV_REF_CANDIDATES); ++i) { | |
204 const int mi_search_col = mi_col + mv_ref_search[i][0]; | |
205 const int mi_search_row = mi_row + mv_ref_search[i][1]; | |
206 if ((mi_search_col >= cm->cur_tile_mi_col_start) && | |
207 (mi_search_col < cm->cur_tile_mi_col_end) && | |
208 (mi_search_row >= 0) && (mi_search_row < cm->mi_rows)) { | |
209 candidate_mi = here + mv_ref_search[i][0] + | |
210 (mv_ref_search[i][1] * xd->mode_info_stride); | |
211 | |
212 if (get_matching_candidate(candidate_mi, ref_frame, &c_refmv, -1)) { | |
213 add_candidate_mv(mv_ref_list, candidate_scores, | |
214 &refmv_count, c_refmv, 16); | |
215 } | 223 } |
216 } | 224 } |
217 } | 225 } |
218 | 226 |
219 // Look in the last frame if it exists | 227 // Check the rest of the neighbors in much the same way |
220 if (lf_here && (refmv_count < MAX_MV_REF_CANDIDATES)) { | 228 // as before except we don't need to keep track of sub blocks or |
221 candidate_mi = lf_here; | 229 // mode counts. |
222 if (get_matching_candidate(candidate_mi, ref_frame, &c_refmv, -1)) { | 230 for (; i < MVREF_NEIGHBOURS; ++i) { |
223 add_candidate_mv(mv_ref_list, candidate_scores, | 231 const MV *const mv_ref = &mv_ref_search[i]; |
224 &refmv_count, c_refmv, 16); | 232 if (is_inside(cm, mi_col, mi_row, mv_ref)) { |
225 } | 233 const MB_MODE_INFO *const candidate = &mi[mv_ref->col + mv_ref->row |
226 } | 234 * xd->mode_info_stride].mbmi; |
227 | 235 |
228 // If we have not found enough candidates consider ones where the | 236 if (candidate->ref_frame[0] == ref_frame) { |
229 // reference frame does not match. Break out when we have | 237 ADD_MV_REF_LIST(candidate->mv[0]); |
230 // MAX_MV_REF_CANDIDATES candidates. | 238 different_ref_found = candidate->ref_frame[1] != ref_frame; |
231 // Look first at spatial neighbours | 239 } else { |
232 for (i = 0; (i < MVREF_NEIGHBOURS) && | 240 if (candidate->ref_frame[1] == ref_frame) |
233 (refmv_count < MAX_MV_REF_CANDIDATES); ++i) { | 241 ADD_MV_REF_LIST(candidate->mv[1]); |
234 const int mi_search_col = mi_col + mv_ref_search[i][0]; | 242 different_ref_found = 1; |
235 const int mi_search_row = mi_row + mv_ref_search[i][1]; | |
236 if ((mi_search_col >= cm->cur_tile_mi_col_start) && | |
237 (mi_search_col < cm->cur_tile_mi_col_end) && | |
238 (mi_search_row >= 0) && (mi_search_row < cm->mi_rows)) { | |
239 candidate_mi = here + mv_ref_search[i][0] + | |
240 (mv_ref_search[i][1] * xd->mode_info_stride); | |
241 | |
242 get_non_matching_candidates(candidate_mi, ref_frame, | |
243 &c_ref_frame, &c_refmv, | |
244 &c2_ref_frame, &c2_refmv); | |
245 | |
246 if (c_ref_frame != INTRA_FRAME) { | |
247 scale_mv(xd, ref_frame, c_ref_frame, &c_refmv, ref_sign_bias); | |
248 add_candidate_mv(mv_ref_list, candidate_scores, | |
249 &refmv_count, c_refmv, 1); | |
250 } | |
251 | |
252 if (c2_ref_frame != INTRA_FRAME) { | |
253 scale_mv(xd, ref_frame, c2_ref_frame, &c2_refmv, ref_sign_bias); | |
254 add_candidate_mv(mv_ref_list, candidate_scores, | |
255 &refmv_count, c2_refmv, 1); | |
256 } | 243 } |
257 } | 244 } |
258 } | 245 } |
259 | 246 |
260 // Look at the last frame if it exists | 247 // Check the last frame's mode and mv info. |
261 if (lf_here && (refmv_count < MAX_MV_REF_CANDIDATES)) { | 248 if (prev_mbmi) { |
262 candidate_mi = lf_here; | 249 if (prev_mbmi->ref_frame[0] == ref_frame) |
263 get_non_matching_candidates(candidate_mi, ref_frame, | 250 ADD_MV_REF_LIST(prev_mbmi->mv[0]); |
264 &c_ref_frame, &c_refmv, | 251 else if (prev_mbmi->ref_frame[1] == ref_frame) |
265 &c2_ref_frame, &c2_refmv); | 252 ADD_MV_REF_LIST(prev_mbmi->mv[1]); |
266 | 253 } |
267 if (c_ref_frame != INTRA_FRAME) { | 254 |
268 scale_mv(xd, ref_frame, c_ref_frame, &c_refmv, ref_sign_bias); | 255 // Since we couldn't find 2 mvs from the same reference frame |
269 add_candidate_mv(mv_ref_list, candidate_scores, | 256 // go back through the neighbors and find motion vectors from |
270 &refmv_count, c_refmv, 1); | 257 // different reference frames. |
| 258 if (different_ref_found) { |
| 259 for (i = 0; i < MVREF_NEIGHBOURS; ++i) { |
| 260 const MV *mv_ref = &mv_ref_search[i]; |
| 261 if (is_inside(cm, mi_col, mi_row, mv_ref)) { |
| 262 const MB_MODE_INFO *const candidate = &mi[mv_ref->col + mv_ref->row |
| 263 * xd->mode_info_stride].mbmi; |
| 264 |
| 265 // If the candidate is INTRA we don't want to consider its mv. |
| 266 if (is_inter_block(candidate)) |
| 267 IF_DIFF_REF_FRAME_ADD_MV(candidate); |
| 268 } |
271 } | 269 } |
272 | 270 } |
273 if (c2_ref_frame != INTRA_FRAME) { | 271 |
274 scale_mv(xd, ref_frame, c2_ref_frame, &c2_refmv, ref_sign_bias); | 272 // Since we still don't have a candidate we'll try the last frame. |
275 add_candidate_mv(mv_ref_list, candidate_scores, | 273 if (prev_mbmi && is_inter_block(prev_mbmi)) |
276 &refmv_count, c2_refmv, 1); | 274 IF_DIFF_REF_FRAME_ADD_MV(prev_mbmi); |
277 } | 275 |
278 } | 276 Done: |
279 | 277 |
280 if (!intra_count) { | 278 mi->mbmi.mode_context[ref_frame] = counter_to_context[context_counter]; |
281 if (!newmv_count) { | |
282 // 0 = both zero mv | |
283 // 1 = one zero mv + one a predicted mv | |
284 // 2 = two predicted mvs | |
285 mbmi->mb_mode_context[ref_frame] = 2 - zero_count; | |
286 } else { | |
287 // 3 = one predicted/zero and one new mv | |
288 // 4 = two new mvs | |
289 mbmi->mb_mode_context[ref_frame] = 2 + newmv_count; | |
290 } | |
291 } else { | |
292 // 5 = one intra neighbour + x | |
293 // 6 = two intra neighbours | |
294 mbmi->mb_mode_context[ref_frame] = 4 + intra_count; | |
295 } | |
296 | 279 |
297 // Clamp vectors | 280 // Clamp vectors |
298 for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) { | 281 for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) |
299 clamp_mv_ref(xd, &mv_ref_list[i]); | 282 clamp_mv_ref(&mv_ref_list[i].as_mv, xd); |
300 } | 283 } |
301 } | |
OLD | NEW |