/src/libvpx/vp9/common/vp9_mvref_common.c
Line | Count | Source (jump to first uncovered line) |
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 | | // This function searches the neighborhood of a given MB/SB |
15 | | // to try and find candidate reference vectors. |
16 | | static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd, |
17 | | MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame, |
18 | | int_mv *mv_ref_list, int block, int mi_row, |
19 | 32.2M | int mi_col, uint8_t *mode_context) { |
20 | 32.2M | const int *ref_sign_bias = cm->ref_frame_sign_bias; |
21 | 32.2M | int i, refmv_count = 0; |
22 | 32.2M | const POSITION *const mv_ref_search = mv_ref_blocks[mi->sb_type]; |
23 | 32.2M | int different_ref_found = 0; |
24 | 32.2M | int context_counter = 0; |
25 | 32.2M | const MV_REF *const prev_frame_mvs = |
26 | 32.2M | cm->use_prev_frame_mvs |
27 | 32.2M | ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col |
28 | 32.2M | : NULL; |
29 | 32.2M | const TileInfo *const tile = &xd->tile; |
30 | | |
31 | | // Blank the reference vector list |
32 | 32.2M | memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES); |
33 | | |
34 | | // The nearest 2 blocks are treated differently |
35 | | // if the size < 8x8 we get the mv from the bmi substructure, |
36 | | // and we also need to keep a mode count. |
37 | 95.2M | for (i = 0; i < 2; ++i) { |
38 | 64.4M | const POSITION *const mv_ref = &mv_ref_search[i]; |
39 | 64.4M | if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) { |
40 | 55.1M | const MODE_INFO *const candidate_mi = |
41 | 55.1M | xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]; |
42 | | // Keep counts for entropy encoding. |
43 | 55.1M | context_counter += mode_2_counter[candidate_mi->mode]; |
44 | 55.1M | different_ref_found = 1; |
45 | | |
46 | 55.1M | if (candidate_mi->ref_frame[0] == ref_frame) |
47 | 10.8M | ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block), |
48 | 55.1M | refmv_count, mv_ref_list, Done); |
49 | 44.2M | else if (candidate_mi->ref_frame[1] == ref_frame) |
50 | 0 | ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block), |
51 | 55.1M | refmv_count, mv_ref_list, Done); |
52 | 55.1M | } |
53 | 64.4M | } |
54 | | |
55 | | // Check the rest of the neighbors in much the same way |
56 | | // as before except we don't need to keep track of sub blocks or |
57 | | // mode counts. |
58 | 204M | for (; i < MVREF_NEIGHBOURS; ++i) { |
59 | 176M | const POSITION *const mv_ref = &mv_ref_search[i]; |
60 | 176M | if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) { |
61 | 117M | const MODE_INFO *const candidate_mi = |
62 | 117M | xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]; |
63 | 117M | different_ref_found = 1; |
64 | | |
65 | 117M | if (candidate_mi->ref_frame[0] == ref_frame) |
66 | 16.2M | ADD_MV_REF_LIST(candidate_mi->mv[0], refmv_count, mv_ref_list, Done); |
67 | 100M | else if (candidate_mi->ref_frame[1] == ref_frame) |
68 | 0 | ADD_MV_REF_LIST(candidate_mi->mv[1], refmv_count, mv_ref_list, Done); |
69 | 117M | } |
70 | 176M | } |
71 | | |
72 | | // Check the last frame's mode and mv info. |
73 | 27.9M | if (cm->use_prev_frame_mvs) { |
74 | 27.9M | if (prev_frame_mvs->ref_frame[0] == ref_frame) { |
75 | 4.22M | ADD_MV_REF_LIST(prev_frame_mvs->mv[0], refmv_count, mv_ref_list, Done); |
76 | 23.7M | } else if (prev_frame_mvs->ref_frame[1] == ref_frame) { |
77 | 0 | ADD_MV_REF_LIST(prev_frame_mvs->mv[1], refmv_count, mv_ref_list, Done); |
78 | 0 | } |
79 | 27.9M | } |
80 | | |
81 | | // Since we couldn't find 2 mvs from the same reference frame |
82 | | // go back through the neighbors and find motion vectors from |
83 | | // different reference frames. |
84 | 26.4M | if (different_ref_found) { |
85 | 192M | for (i = 0; i < MVREF_NEIGHBOURS; ++i) { |
86 | 173M | const POSITION *mv_ref = &mv_ref_search[i]; |
87 | 173M | if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) { |
88 | 123M | const MODE_INFO *const candidate_mi = |
89 | 123M | xd->mi[mv_ref->col + mv_ref->row * xd->mi_stride]; |
90 | | |
91 | | // If the candidate is INTRA we don't want to consider its mv. |
92 | 123M | IF_DIFF_REF_FRAME_ADD_MV(candidate_mi, ref_frame, ref_sign_bias, |
93 | 123M | refmv_count, mv_ref_list, Done); |
94 | 123M | } |
95 | 173M | } |
96 | 25.5M | } |
97 | | |
98 | | // Since we still don't have a candidate we'll try the last frame. |
99 | 20.3M | if (cm->use_prev_frame_mvs) { |
100 | 20.3M | if (prev_frame_mvs->ref_frame[0] != ref_frame && |
101 | 20.3M | prev_frame_mvs->ref_frame[0] > INTRA_FRAME) { |
102 | 4.25M | int_mv mv = prev_frame_mvs->mv[0]; |
103 | 4.25M | if (ref_sign_bias[prev_frame_mvs->ref_frame[0]] != |
104 | 4.25M | ref_sign_bias[ref_frame]) { |
105 | 0 | mv.as_mv.row *= -1; |
106 | 0 | mv.as_mv.col *= -1; |
107 | 0 | } |
108 | 4.25M | ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done); |
109 | 4.25M | } |
110 | | |
111 | 18.3M | if (prev_frame_mvs->ref_frame[1] > INTRA_FRAME && |
112 | 18.3M | prev_frame_mvs->ref_frame[1] != ref_frame && |
113 | 18.3M | prev_frame_mvs->mv[1].as_int != prev_frame_mvs->mv[0].as_int) { |
114 | 0 | int_mv mv = prev_frame_mvs->mv[1]; |
115 | 0 | if (ref_sign_bias[prev_frame_mvs->ref_frame[1]] != |
116 | 0 | ref_sign_bias[ref_frame]) { |
117 | 0 | mv.as_mv.row *= -1; |
118 | 0 | mv.as_mv.col *= -1; |
119 | 0 | } |
120 | 0 | ADD_MV_REF_LIST(mv, refmv_count, mv_ref_list, Done); |
121 | 0 | } |
122 | 18.3M | } |
123 | | |
124 | 32.2M | Done: |
125 | | |
126 | 32.2M | mode_context[ref_frame] = counter_to_context[context_counter]; |
127 | | |
128 | | // Clamp vectors |
129 | 96.6M | for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) |
130 | 64.4M | clamp_mv_ref(&mv_ref_list[i].as_mv, xd); |
131 | 32.2M | } |
132 | | |
133 | | void vp9_find_mv_refs(const VP9_COMMON *cm, const MACROBLOCKD *xd, |
134 | | MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame, |
135 | | int_mv *mv_ref_list, int mi_row, int mi_col, |
136 | 13.3M | uint8_t *mode_context) { |
137 | 13.3M | find_mv_refs_idx(cm, xd, mi, ref_frame, mv_ref_list, -1, mi_row, mi_col, |
138 | 13.3M | mode_context); |
139 | 13.3M | } |
140 | | |
141 | | void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp, int_mv *mvlist, |
142 | 13.3M | int_mv *nearest_mv, int_mv *near_mv) { |
143 | 13.3M | int i; |
144 | | // Make sure all the candidates are properly clamped etc |
145 | 40.0M | for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) { |
146 | 26.7M | lower_mv_precision(&mvlist[i].as_mv, allow_hp); |
147 | 26.7M | clamp_mv2(&mvlist[i].as_mv, xd); |
148 | 26.7M | } |
149 | 13.3M | *nearest_mv = mvlist[0]; |
150 | 13.3M | *near_mv = mvlist[1]; |
151 | 13.3M | } |
152 | | |
153 | | void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd, int block, |
154 | | int ref, int mi_row, int mi_col, |
155 | | int_mv *nearest_mv, int_mv *near_mv, |
156 | 18.8M | uint8_t *mode_context) { |
157 | 18.8M | int_mv mv_list[MAX_MV_REF_CANDIDATES]; |
158 | 18.8M | MODE_INFO *const mi = xd->mi[0]; |
159 | 18.8M | b_mode_info *bmi = mi->bmi; |
160 | 18.8M | int n; |
161 | | |
162 | 18.8M | assert(MAX_MV_REF_CANDIDATES == 2); |
163 | | |
164 | 18.8M | find_mv_refs_idx(cm, xd, mi, mi->ref_frame[ref], mv_list, block, mi_row, |
165 | 18.8M | mi_col, mode_context); |
166 | | |
167 | 18.8M | near_mv->as_int = 0; |
168 | 18.8M | switch (block) { |
169 | 6.16M | case 0: |
170 | 6.16M | nearest_mv->as_int = mv_list[0].as_int; |
171 | 6.16M | near_mv->as_int = mv_list[1].as_int; |
172 | 6.16M | break; |
173 | 4.80M | case 1: |
174 | 9.41M | case 2: |
175 | 9.41M | nearest_mv->as_int = bmi[0].as_mv[ref].as_int; |
176 | 15.5M | for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n) |
177 | 13.8M | if (nearest_mv->as_int != mv_list[n].as_int) { |
178 | 7.77M | near_mv->as_int = mv_list[n].as_int; |
179 | 7.77M | break; |
180 | 7.77M | } |
181 | 9.41M | break; |
182 | 3.27M | case 3: { |
183 | 3.27M | int_mv candidates[2 + MAX_MV_REF_CANDIDATES]; |
184 | 3.27M | candidates[0] = bmi[1].as_mv[ref]; |
185 | 3.27M | candidates[1] = bmi[0].as_mv[ref]; |
186 | 3.27M | candidates[2] = mv_list[0]; |
187 | 3.27M | candidates[3] = mv_list[1]; |
188 | | |
189 | 3.27M | nearest_mv->as_int = bmi[2].as_mv[ref].as_int; |
190 | 7.85M | for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n) |
191 | 7.48M | if (nearest_mv->as_int != candidates[n].as_int) { |
192 | 2.91M | near_mv->as_int = candidates[n].as_int; |
193 | 2.91M | break; |
194 | 2.91M | } |
195 | 3.27M | break; |
196 | 4.80M | } |
197 | 0 | default: assert(0 && "Invalid block index."); |
198 | 18.8M | } |
199 | 18.8M | } |