/src/libvpx/vp9/common/vp9_reconinter.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2010 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 <assert.h> |
12 | | |
13 | | #include "./vpx_scale_rtcd.h" |
14 | | #include "./vpx_config.h" |
15 | | |
16 | | #include "vp9/common/vp9_blockd.h" |
17 | | #include "vp9/common/vp9_reconinter.h" |
18 | | #include "vp9/common/vp9_reconintra.h" |
19 | | |
20 | | #include "vpx/vpx_integer.h" |
21 | | #include "vpx_scale/yv12config.h" |
22 | | |
23 | | #if CONFIG_VP9_HIGHBITDEPTH |
24 | | void vp9_highbd_build_inter_predictor( |
25 | | const uint16_t *src, int src_stride, uint16_t *dst, int dst_stride, |
26 | | const MV *src_mv, const struct scale_factors *sf, int w, int h, int ref, |
27 | | const InterpKernel *kernel, enum mv_precision precision, int x, int y, |
28 | 0 | int bd) { |
29 | 0 | const int is_q4 = precision == MV_PRECISION_Q4; |
30 | 0 | const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2, |
31 | 0 | is_q4 ? src_mv->col : src_mv->col * 2 }; |
32 | 0 | MV32 mv = vp9_scale_mv(&mv_q4, x, y, sf); |
33 | 0 | const int subpel_x = mv.col & SUBPEL_MASK; |
34 | 0 | const int subpel_y = mv.row & SUBPEL_MASK; |
35 | |
|
36 | 0 | src += (mv.row >> SUBPEL_BITS) * src_stride + (mv.col >> SUBPEL_BITS); |
37 | |
|
38 | 0 | highbd_inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y, |
39 | 0 | sf, w, h, ref, kernel, sf->x_step_q4, sf->y_step_q4, |
40 | 0 | bd); |
41 | 0 | } |
42 | | #endif // CONFIG_VP9_HIGHBITDEPTH |
43 | | |
44 | | void vp9_build_inter_predictor(const uint8_t *src, int src_stride, uint8_t *dst, |
45 | | int dst_stride, const MV *src_mv, |
46 | | const struct scale_factors *sf, int w, int h, |
47 | | int ref, const InterpKernel *kernel, |
48 | 168M | enum mv_precision precision, int x, int y) { |
49 | 168M | const int is_q4 = precision == MV_PRECISION_Q4; |
50 | 168M | const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2, |
51 | 168M | is_q4 ? src_mv->col : src_mv->col * 2 }; |
52 | 168M | MV32 mv = vp9_scale_mv(&mv_q4, x, y, sf); |
53 | 168M | const int subpel_x = mv.col & SUBPEL_MASK; |
54 | 168M | const int subpel_y = mv.row & SUBPEL_MASK; |
55 | | |
56 | 168M | src += (mv.row >> SUBPEL_BITS) * src_stride + (mv.col >> SUBPEL_BITS); |
57 | | |
58 | 168M | inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y, sf, w, |
59 | 168M | h, ref, kernel, sf->x_step_q4, sf->y_step_q4); |
60 | 168M | } |
61 | | |
62 | 18.6M | static INLINE int round_mv_comp_q4(int value) { |
63 | 18.6M | return (value < 0 ? value - 2 : value + 2) / 4; |
64 | 18.6M | } |
65 | | |
66 | 9.34M | static MV mi_mv_pred_q4(const MODE_INFO *mi, int idx) { |
67 | 9.34M | MV res = { round_mv_comp_q4(mi->bmi[0].as_mv[idx].as_mv.row + |
68 | 9.34M | mi->bmi[1].as_mv[idx].as_mv.row + |
69 | 9.34M | mi->bmi[2].as_mv[idx].as_mv.row + |
70 | 9.34M | mi->bmi[3].as_mv[idx].as_mv.row), |
71 | 9.34M | round_mv_comp_q4(mi->bmi[0].as_mv[idx].as_mv.col + |
72 | 9.34M | mi->bmi[1].as_mv[idx].as_mv.col + |
73 | 9.34M | mi->bmi[2].as_mv[idx].as_mv.col + |
74 | 9.34M | mi->bmi[3].as_mv[idx].as_mv.col) }; |
75 | 9.34M | return res; |
76 | 9.34M | } |
77 | | |
78 | 0 | static INLINE int round_mv_comp_q2(int value) { |
79 | 0 | return (value < 0 ? value - 1 : value + 1) / 2; |
80 | 0 | } |
81 | | |
82 | 0 | static MV mi_mv_pred_q2(const MODE_INFO *mi, int idx, int block0, int block1) { |
83 | 0 | MV res = { round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.row + |
84 | 0 | mi->bmi[block1].as_mv[idx].as_mv.row), |
85 | 0 | round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.col + |
86 | 0 | mi->bmi[block1].as_mv[idx].as_mv.col) }; |
87 | 0 | return res; |
88 | 0 | } |
89 | | |
90 | | // TODO(jkoleszar): yet another mv clamping function :-( |
91 | | MV clamp_mv_to_umv_border_sb(const MACROBLOCKD *xd, const MV *src_mv, int bw, |
92 | 104M | int bh, int ss_x, int ss_y) { |
93 | | // If the MV points so far into the UMV border that no visible pixels |
94 | | // are used for reconstruction, the subpel part of the MV can be |
95 | | // discarded and the MV limited to 16 pixels with equivalent results. |
96 | 104M | const int spel_left = (VP9_INTERP_EXTEND + bw) << SUBPEL_BITS; |
97 | 104M | const int spel_right = spel_left - SUBPEL_SHIFTS; |
98 | 104M | const int spel_top = (VP9_INTERP_EXTEND + bh) << SUBPEL_BITS; |
99 | 104M | const int spel_bottom = spel_top - SUBPEL_SHIFTS; |
100 | 104M | MV clamped_mv = { (short)(src_mv->row * (1 << (1 - ss_y))), |
101 | 104M | (short)(src_mv->col * (1 << (1 - ss_x))) }; |
102 | 104M | assert(ss_x <= 1); |
103 | 104M | assert(ss_y <= 1); |
104 | | |
105 | 104M | clamp_mv(&clamped_mv, xd->mb_to_left_edge * (1 << (1 - ss_x)) - spel_left, |
106 | 104M | xd->mb_to_right_edge * (1 << (1 - ss_x)) + spel_right, |
107 | 104M | xd->mb_to_top_edge * (1 << (1 - ss_y)) - spel_top, |
108 | 104M | xd->mb_to_bottom_edge * (1 << (1 - ss_y)) + spel_bottom); |
109 | | |
110 | 104M | return clamped_mv; |
111 | 104M | } |
112 | | |
113 | | MV average_split_mvs(const struct macroblockd_plane *pd, const MODE_INFO *mi, |
114 | 13.1M | int ref, int block) { |
115 | 13.1M | const int ss_idx = ((pd->subsampling_x > 0) << 1) | (pd->subsampling_y > 0); |
116 | 13.1M | MV res = { 0, 0 }; |
117 | 13.1M | switch (ss_idx) { |
118 | 3.78M | case 0: res = mi->bmi[block].as_mv[ref].as_mv; break; |
119 | 0 | case 1: res = mi_mv_pred_q2(mi, ref, block, block + 2); break; |
120 | 0 | case 2: res = mi_mv_pred_q2(mi, ref, block, block + 1); break; |
121 | 9.34M | case 3: res = mi_mv_pred_q4(mi, ref); break; |
122 | 0 | default: assert(ss_idx <= 3 && ss_idx >= 0); |
123 | 13.1M | } |
124 | 13.1M | return res; |
125 | 13.1M | } |
126 | | |
127 | | static void build_inter_predictors(MACROBLOCKD *xd, int plane, int block, |
128 | | int bw, int bh, int x, int y, int w, int h, |
129 | 104M | int mi_x, int mi_y) { |
130 | 104M | struct macroblockd_plane *const pd = &xd->plane[plane]; |
131 | 104M | const MODE_INFO *mi = xd->mi[0]; |
132 | 104M | const int is_compound = has_second_ref(mi); |
133 | 104M | const InterpKernel *kernel = vp9_filter_kernels[mi->interp_filter]; |
134 | 104M | int ref; |
135 | | |
136 | 208M | for (ref = 0; ref < 1 + is_compound; ++ref) { |
137 | 104M | const struct scale_factors *const sf = &xd->block_refs[ref]->sf; |
138 | 104M | struct buf_2d *const pre_buf = &pd->pre[ref]; |
139 | 104M | struct buf_2d *const dst_buf = &pd->dst; |
140 | 104M | uint8_t *const dst = dst_buf->buf + (int64_t)dst_buf->stride * y + x; |
141 | 104M | const MV mv = mi->sb_type < BLOCK_8X8 |
142 | 104M | ? average_split_mvs(pd, mi, ref, block) |
143 | 104M | : mi->mv[ref].as_mv; |
144 | | |
145 | | // TODO(jkoleszar): This clamping is done in the incorrect place for the |
146 | | // scaling case. It needs to be done on the scaled MV, not the pre-scaling |
147 | | // MV. Note however that it performs the subsampling aware scaling so |
148 | | // that the result is always q4. |
149 | | // mv_precision precision is MV_PRECISION_Q4. |
150 | 104M | const MV mv_q4 = clamp_mv_to_umv_border_sb( |
151 | 104M | xd, &mv, bw, bh, pd->subsampling_x, pd->subsampling_y); |
152 | | |
153 | 104M | uint8_t *pre; |
154 | 104M | MV32 scaled_mv; |
155 | 104M | int xs, ys, subpel_x, subpel_y; |
156 | 104M | const int is_scaled = vp9_is_scaled(sf); |
157 | | |
158 | 104M | if (is_scaled) { |
159 | | // Co-ordinate of containing block to pixel precision. |
160 | 0 | const int x_start = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)); |
161 | 0 | const int y_start = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)); |
162 | 0 | const YV12_BUFFER_CONFIG *ref_buf = xd->block_refs[ref]->buf; |
163 | 0 | uint8_t *buf_array[] = { ref_buf->y_buffer, ref_buf->u_buffer, |
164 | 0 | ref_buf->v_buffer }; |
165 | 0 | const int stride_array[] = { ref_buf->y_stride, ref_buf->uv_stride, |
166 | 0 | ref_buf->uv_stride }; |
167 | | #if 0 // CONFIG_BETTER_HW_COMPATIBILITY |
168 | | assert(xd->mi[0]->sb_type != BLOCK_4X8 && |
169 | | xd->mi[0]->sb_type != BLOCK_8X4); |
170 | | assert(mv_q4.row == mv.row * (1 << (1 - pd->subsampling_y)) && |
171 | | mv_q4.col == mv.col * (1 << (1 - pd->subsampling_x))); |
172 | | #endif |
173 | 0 | pre_buf->buf = buf_array[plane]; |
174 | 0 | pre_buf->stride = stride_array[plane]; |
175 | |
|
176 | 0 | pre_buf->buf += |
177 | 0 | scaled_buffer_offset(x_start + x, y_start + y, pre_buf->stride, sf); |
178 | 0 | pre = pre_buf->buf; |
179 | 0 | scaled_mv = vp9_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf); |
180 | 0 | xs = sf->x_step_q4; |
181 | 0 | ys = sf->y_step_q4; |
182 | 104M | } else { |
183 | 104M | pre = pre_buf->buf + ((int64_t)y * pre_buf->stride + x); |
184 | 104M | scaled_mv.row = mv_q4.row; |
185 | 104M | scaled_mv.col = mv_q4.col; |
186 | 104M | xs = ys = 16; |
187 | 104M | } |
188 | 104M | subpel_x = scaled_mv.col & SUBPEL_MASK; |
189 | 104M | subpel_y = scaled_mv.row & SUBPEL_MASK; |
190 | 104M | pre += (scaled_mv.row >> SUBPEL_BITS) * pre_buf->stride + |
191 | 104M | (scaled_mv.col >> SUBPEL_BITS); |
192 | | |
193 | 104M | #if CONFIG_VP9_HIGHBITDEPTH |
194 | 104M | if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { |
195 | 0 | highbd_inter_predictor(CONVERT_TO_SHORTPTR(pre), pre_buf->stride, |
196 | 0 | CONVERT_TO_SHORTPTR(dst), dst_buf->stride, |
197 | 0 | subpel_x, subpel_y, sf, w, h, ref, kernel, xs, ys, |
198 | 0 | xd->bd); |
199 | 104M | } else { |
200 | 104M | inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride, subpel_x, |
201 | 104M | subpel_y, sf, w, h, ref, kernel, xs, ys); |
202 | 104M | } |
203 | | #else |
204 | | inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride, subpel_x, |
205 | | subpel_y, sf, w, h, ref, kernel, xs, ys); |
206 | | #endif // CONFIG_VP9_HIGHBITDEPTH |
207 | 104M | } |
208 | 104M | } |
209 | | |
210 | | static void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize, |
211 | | int mi_row, int mi_col, |
212 | 95.2M | int plane_from, int plane_to) { |
213 | 95.2M | int plane; |
214 | 95.2M | const int mi_x = mi_col * MI_SIZE; |
215 | 95.2M | const int mi_y = mi_row * MI_SIZE; |
216 | 196M | for (plane = plane_from; plane <= plane_to; ++plane) { |
217 | 101M | const BLOCK_SIZE plane_bsize = |
218 | 101M | get_plane_block_size(bsize, &xd->plane[plane]); |
219 | 101M | const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize]; |
220 | 101M | const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize]; |
221 | 101M | const int bw = 4 * num_4x4_w; |
222 | 101M | const int bh = 4 * num_4x4_h; |
223 | | |
224 | 101M | if (xd->mi[0]->sb_type < BLOCK_8X8) { |
225 | 10.2M | int i = 0, x, y; |
226 | 10.2M | assert(bsize == BLOCK_8X8); |
227 | 21.5M | for (y = 0; y < num_4x4_h; ++y) |
228 | 24.3M | for (x = 0; x < num_4x4_w; ++x) |
229 | 13.1M | build_inter_predictors(xd, plane, i++, bw, bh, 4 * x, 4 * y, 4, 4, |
230 | 13.1M | mi_x, mi_y); |
231 | 90.9M | } else { |
232 | 90.9M | build_inter_predictors(xd, plane, 0, bw, bh, 0, 0, bw, bh, mi_x, mi_y); |
233 | 90.9M | } |
234 | 101M | } |
235 | 95.2M | } |
236 | | |
237 | | void vp9_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col, |
238 | 3.43M | BLOCK_SIZE bsize) { |
239 | 3.43M | build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0); |
240 | 3.43M | } |
241 | | |
242 | | void vp9_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col, |
243 | 85.7M | BLOCK_SIZE bsize, int plane) { |
244 | 85.7M | build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, plane, plane); |
245 | 85.7M | } |
246 | | |
247 | | void vp9_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col, |
248 | 6.02M | BLOCK_SIZE bsize) { |
249 | 6.02M | build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1, |
250 | 6.02M | MAX_MB_PLANE - 1); |
251 | 6.02M | } |
252 | | |
253 | | void vp9_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col, |
254 | 0 | BLOCK_SIZE bsize) { |
255 | 0 | build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, |
256 | 0 | MAX_MB_PLANE - 1); |
257 | 0 | } |
258 | | |
259 | | void vp9_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE], |
260 | | const YV12_BUFFER_CONFIG *src, int mi_row, |
261 | 19.5M | int mi_col) { |
262 | 19.5M | uint8_t *const buffers[MAX_MB_PLANE] = { src->y_buffer, src->u_buffer, |
263 | 19.5M | src->v_buffer }; |
264 | 19.5M | const int strides[MAX_MB_PLANE] = { src->y_stride, src->uv_stride, |
265 | 19.5M | src->uv_stride }; |
266 | 19.5M | int i; |
267 | | |
268 | 78.3M | for (i = 0; i < MAX_MB_PLANE; ++i) { |
269 | 58.7M | struct macroblockd_plane *const pd = &planes[i]; |
270 | 58.7M | setup_pred_plane(&pd->dst, buffers[i], strides[i], mi_row, mi_col, NULL, |
271 | 58.7M | pd->subsampling_x, pd->subsampling_y); |
272 | 58.7M | } |
273 | 19.5M | } |
274 | | |
275 | | void vp9_setup_pre_planes(MACROBLOCKD *xd, int idx, |
276 | | const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col, |
277 | 3.43M | const struct scale_factors *sf) { |
278 | 3.43M | if (src != NULL) { |
279 | 3.43M | int i; |
280 | 3.43M | uint8_t *const buffers[MAX_MB_PLANE] = { src->y_buffer, src->u_buffer, |
281 | 3.43M | src->v_buffer }; |
282 | 3.43M | const int strides[MAX_MB_PLANE] = { src->y_stride, src->uv_stride, |
283 | 3.43M | src->uv_stride }; |
284 | 13.7M | for (i = 0; i < MAX_MB_PLANE; ++i) { |
285 | 10.3M | struct macroblockd_plane *const pd = &xd->plane[i]; |
286 | 10.3M | setup_pred_plane(&pd->pre[idx], buffers[i], strides[i], mi_row, mi_col, |
287 | 10.3M | sf, pd->subsampling_x, pd->subsampling_y); |
288 | 10.3M | } |
289 | 3.43M | } |
290 | 3.43M | } |