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 "./vpx_config.h"
12
13#include "vpx_mem/vpx_mem.h"
14#include "vpx_ports/vpx_once.h"
15
16#include "./vp9_rtcd.h"
17
18#include "vp9/common/vp9_reconintra.h"
19#include "vp9/common/vp9_onyxc_int.h"
20
21const TX_TYPE intra_mode_to_tx_type_lookup[INTRA_MODES] = {
22  DCT_DCT,    // DC
23  ADST_DCT,   // V
24  DCT_ADST,   // H
25  DCT_DCT,    // D45
26  ADST_ADST,  // D135
27  ADST_DCT,   // D117
28  DCT_ADST,   // D153
29  DCT_ADST,   // D207
30  ADST_DCT,   // D63
31  ADST_ADST,  // TM
32};
33
34#define intra_pred_sized(type, size) \
35  void vp9_##type##_predictor_##size##x##size##_c(uint8_t *dst, \
36                                                  ptrdiff_t stride, \
37                                                  const uint8_t *above, \
38                                                  const uint8_t *left) { \
39    type##_predictor(dst, stride, size, above, left); \
40  }
41
42#define intra_pred_allsizes(type) \
43  intra_pred_sized(type, 4) \
44  intra_pred_sized(type, 8) \
45  intra_pred_sized(type, 16) \
46  intra_pred_sized(type, 32)
47
48static INLINE void d207_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
49                                  const uint8_t *above, const uint8_t *left) {
50  int r, c;
51
52  // first column
53  for (r = 0; r < bs - 1; ++r)
54    dst[r * stride] = ROUND_POWER_OF_TWO(left[r] + left[r + 1], 1);
55  dst[(bs - 1) * stride] = left[bs - 1];
56  dst++;
57
58  // second column
59  for (r = 0; r < bs - 2; ++r)
60    dst[r * stride] = ROUND_POWER_OF_TWO(left[r] + left[r + 1] * 2 +
61                                         left[r + 2], 2);
62  dst[(bs - 2) * stride] = ROUND_POWER_OF_TWO(left[bs - 2] +
63                                              left[bs - 1] * 3, 2);
64  dst[(bs - 1) * stride] = left[bs - 1];
65  dst++;
66
67  // rest of last row
68  for (c = 0; c < bs - 2; ++c)
69    dst[(bs - 1) * stride + c] = left[bs - 1];
70
71  for (r = bs - 2; r >= 0; --r)
72    for (c = 0; c < bs - 2; ++c)
73      dst[r * stride + c] = dst[(r + 1) * stride + c - 2];
74}
75intra_pred_allsizes(d207)
76
77static INLINE void d63_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
78                                 const uint8_t *above, const uint8_t *left) {
79  int r, c;
80  for (r = 0; r < bs; ++r) {
81    for (c = 0; c < bs; ++c)
82      dst[c] = r & 1 ? ROUND_POWER_OF_TWO(above[r/2 + c] +
83                                          above[r/2 + c + 1] * 2 +
84                                          above[r/2 + c + 2], 2)
85                     : ROUND_POWER_OF_TWO(above[r/2 + c] +
86                                          above[r/2 + c + 1], 1);
87    dst += stride;
88  }
89}
90intra_pred_allsizes(d63)
91
92static INLINE void d45_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
93                                 const uint8_t *above, const uint8_t *left) {
94  int r, c;
95  for (r = 0; r < bs; ++r) {
96    for (c = 0; c < bs; ++c)
97      dst[c] = r + c + 2 < bs * 2 ?  ROUND_POWER_OF_TWO(above[r + c] +
98                                                        above[r + c + 1] * 2 +
99                                                        above[r + c + 2], 2)
100                                  : above[bs * 2 - 1];
101    dst += stride;
102  }
103}
104intra_pred_allsizes(d45)
105
106static INLINE void d117_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
107                                  const uint8_t *above, const uint8_t *left) {
108  int r, c;
109
110  // first row
111  for (c = 0; c < bs; c++)
112    dst[c] = ROUND_POWER_OF_TWO(above[c - 1] + above[c], 1);
113  dst += stride;
114
115  // second row
116  dst[0] = ROUND_POWER_OF_TWO(left[0] + above[-1] * 2 + above[0], 2);
117  for (c = 1; c < bs; c++)
118    dst[c] = ROUND_POWER_OF_TWO(above[c - 2] + above[c - 1] * 2 + above[c], 2);
119  dst += stride;
120
121  // the rest of first col
122  dst[0] = ROUND_POWER_OF_TWO(above[-1] + left[0] * 2 + left[1], 2);
123  for (r = 3; r < bs; ++r)
124    dst[(r - 2) * stride] = ROUND_POWER_OF_TWO(left[r - 3] + left[r - 2] * 2 +
125                                               left[r - 1], 2);
126
127  // the rest of the block
128  for (r = 2; r < bs; ++r) {
129    for (c = 1; c < bs; c++)
130      dst[c] = dst[-2 * stride + c - 1];
131    dst += stride;
132  }
133}
134intra_pred_allsizes(d117)
135
136static INLINE void d135_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
137                                  const uint8_t *above, const uint8_t *left) {
138  int r, c;
139  dst[0] = ROUND_POWER_OF_TWO(left[0] + above[-1] * 2 + above[0], 2);
140  for (c = 1; c < bs; c++)
141    dst[c] = ROUND_POWER_OF_TWO(above[c - 2] + above[c - 1] * 2 + above[c], 2);
142
143  dst[stride] = ROUND_POWER_OF_TWO(above[-1] + left[0] * 2 + left[1], 2);
144  for (r = 2; r < bs; ++r)
145    dst[r * stride] = ROUND_POWER_OF_TWO(left[r - 2] + left[r - 1] * 2 +
146                                         left[r], 2);
147
148  dst += stride;
149  for (r = 1; r < bs; ++r) {
150    for (c = 1; c < bs; c++)
151      dst[c] = dst[-stride + c - 1];
152    dst += stride;
153  }
154}
155intra_pred_allsizes(d135)
156
157static INLINE void d153_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
158                                  const uint8_t *above, const uint8_t *left) {
159  int r, c;
160  dst[0] = ROUND_POWER_OF_TWO(above[-1] + left[0], 1);
161  for (r = 1; r < bs; r++)
162    dst[r * stride] = ROUND_POWER_OF_TWO(left[r - 1] + left[r], 1);
163  dst++;
164
165  dst[0] = ROUND_POWER_OF_TWO(left[0] + above[-1] * 2 + above[0], 2);
166  dst[stride] = ROUND_POWER_OF_TWO(above[-1] + left[0] * 2 + left[1], 2);
167  for (r = 2; r < bs; r++)
168    dst[r * stride] = ROUND_POWER_OF_TWO(left[r - 2] + left[r - 1] * 2 +
169                                         left[r], 2);
170  dst++;
171
172  for (c = 0; c < bs - 2; c++)
173    dst[c] = ROUND_POWER_OF_TWO(above[c - 1] + above[c] * 2 + above[c + 1], 2);
174  dst += stride;
175
176  for (r = 1; r < bs; ++r) {
177    for (c = 0; c < bs - 2; c++)
178      dst[c] = dst[-stride + c - 2];
179    dst += stride;
180  }
181}
182intra_pred_allsizes(d153)
183
184static INLINE void v_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
185                               const uint8_t *above, const uint8_t *left) {
186  int r;
187
188  for (r = 0; r < bs; r++) {
189    vpx_memcpy(dst, above, bs);
190    dst += stride;
191  }
192}
193intra_pred_allsizes(v)
194
195static INLINE void h_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
196                               const uint8_t *above, const uint8_t *left) {
197  int r;
198
199  for (r = 0; r < bs; r++) {
200    vpx_memset(dst, left[r], bs);
201    dst += stride;
202  }
203}
204intra_pred_allsizes(h)
205
206static INLINE void tm_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
207                                const uint8_t *above, const uint8_t *left) {
208  int r, c;
209  int ytop_left = above[-1];
210
211  for (r = 0; r < bs; r++) {
212    for (c = 0; c < bs; c++)
213      dst[c] = clip_pixel(left[r] + above[c] - ytop_left);
214    dst += stride;
215  }
216}
217intra_pred_allsizes(tm)
218
219static INLINE void dc_128_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
220                                    const uint8_t *above, const uint8_t *left) {
221  int r;
222
223  for (r = 0; r < bs; r++) {
224    vpx_memset(dst, 128, bs);
225    dst += stride;
226  }
227}
228intra_pred_allsizes(dc_128)
229
230static INLINE void dc_left_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
231                                     const uint8_t *above,
232                                     const uint8_t *left) {
233  int i, r, expected_dc, sum = 0;
234
235  for (i = 0; i < bs; i++)
236    sum += left[i];
237  expected_dc = (sum + (bs >> 1)) / bs;
238
239  for (r = 0; r < bs; r++) {
240    vpx_memset(dst, expected_dc, bs);
241    dst += stride;
242  }
243}
244intra_pred_allsizes(dc_left)
245
246static INLINE void dc_top_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
247                                    const uint8_t *above, const uint8_t *left) {
248  int i, r, expected_dc, sum = 0;
249
250  for (i = 0; i < bs; i++)
251    sum += above[i];
252  expected_dc = (sum + (bs >> 1)) / bs;
253
254  for (r = 0; r < bs; r++) {
255    vpx_memset(dst, expected_dc, bs);
256    dst += stride;
257  }
258}
259intra_pred_allsizes(dc_top)
260
261static INLINE void dc_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
262                                const uint8_t *above, const uint8_t *left) {
263  int i, r, expected_dc, sum = 0;
264  const int count = 2 * bs;
265
266  for (i = 0; i < bs; i++) {
267    sum += above[i];
268    sum += left[i];
269  }
270
271  expected_dc = (sum + (count >> 1)) / count;
272
273  for (r = 0; r < bs; r++) {
274    vpx_memset(dst, expected_dc, bs);
275    dst += stride;
276  }
277}
278intra_pred_allsizes(dc)
279#undef intra_pred_allsizes
280
281typedef void (*intra_pred_fn)(uint8_t *dst, ptrdiff_t stride,
282                              const uint8_t *above, const uint8_t *left);
283
284static intra_pred_fn pred[INTRA_MODES][4];
285static intra_pred_fn dc_pred[2][2][4];
286
287static void init_intra_pred_fn_ptrs(void) {
288#define intra_pred_allsizes(l, type) \
289  l[0] = vp9_##type##_predictor_4x4; \
290  l[1] = vp9_##type##_predictor_8x8; \
291  l[2] = vp9_##type##_predictor_16x16; \
292  l[3] = vp9_##type##_predictor_32x32
293
294  intra_pred_allsizes(pred[V_PRED], v);
295  intra_pred_allsizes(pred[H_PRED], h);
296  intra_pred_allsizes(pred[D207_PRED], d207);
297  intra_pred_allsizes(pred[D45_PRED], d45);
298  intra_pred_allsizes(pred[D63_PRED], d63);
299  intra_pred_allsizes(pred[D117_PRED], d117);
300  intra_pred_allsizes(pred[D135_PRED], d135);
301  intra_pred_allsizes(pred[D153_PRED], d153);
302  intra_pred_allsizes(pred[TM_PRED], tm);
303
304  intra_pred_allsizes(dc_pred[0][0], dc_128);
305  intra_pred_allsizes(dc_pred[0][1], dc_top);
306  intra_pred_allsizes(dc_pred[1][0], dc_left);
307  intra_pred_allsizes(dc_pred[1][1], dc);
308
309#undef intra_pred_allsizes
310}
311
312static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref,
313                                   int ref_stride, uint8_t *dst, int dst_stride,
314                                   MB_PREDICTION_MODE mode, TX_SIZE tx_size,
315                                   int up_available, int left_available,
316                                   int right_available, int x, int y,
317                                   int plane) {
318  int i;
319  DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
320  DECLARE_ALIGNED_ARRAY(16, uint8_t, above_data, 128 + 16);
321  uint8_t *above_row = above_data + 16;
322  const uint8_t *const_above_row = above_row;
323  const int bs = 4 << tx_size;
324  int frame_width, frame_height;
325  int x0, y0;
326  const struct macroblockd_plane *const pd = &xd->plane[plane];
327
328  // 127 127 127 .. 127 127 127 127 127 127
329  // 129  A   B  ..  Y   Z
330  // 129  C   D  ..  W   X
331  // 129  E   F  ..  U   V
332  // 129  G   H  ..  S   T   T   T   T   T
333  // ..
334
335  once(init_intra_pred_fn_ptrs);
336
337  // Get current frame pointer, width and height.
338  if (plane == 0) {
339    frame_width = xd->cur_buf->y_width;
340    frame_height = xd->cur_buf->y_height;
341  } else {
342    frame_width = xd->cur_buf->uv_width;
343    frame_height = xd->cur_buf->uv_height;
344  }
345
346  // Get block position in current frame.
347  x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
348  y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
349
350  vpx_memset(left_col, 129, 64);
351
352  // left
353  if (left_available) {
354    if (xd->mb_to_bottom_edge < 0) {
355      /* slower path if the block needs border extension */
356      if (y0 + bs <= frame_height) {
357        for (i = 0; i < bs; ++i)
358          left_col[i] = ref[i * ref_stride - 1];
359      } else {
360        const int extend_bottom = frame_height - y0;
361        for (i = 0; i < extend_bottom; ++i)
362          left_col[i] = ref[i * ref_stride - 1];
363        for (; i < bs; ++i)
364          left_col[i] = ref[(extend_bottom - 1) * ref_stride - 1];
365      }
366    } else {
367      /* faster path if the block does not need extension */
368      for (i = 0; i < bs; ++i)
369        left_col[i] = ref[i * ref_stride - 1];
370    }
371  }
372
373  // TODO(hkuang) do not extend 2*bs pixels for all modes.
374  // above
375  if (up_available) {
376    const uint8_t *above_ref = ref - ref_stride;
377    if (xd->mb_to_right_edge < 0) {
378      /* slower path if the block needs border extension */
379      if (x0 + 2 * bs <= frame_width) {
380        if (right_available && bs == 4) {
381          vpx_memcpy(above_row, above_ref, 2 * bs);
382        } else {
383          vpx_memcpy(above_row, above_ref, bs);
384          vpx_memset(above_row + bs, above_row[bs - 1], bs);
385        }
386      } else if (x0 + bs <= frame_width) {
387        const int r = frame_width - x0;
388        if (right_available && bs == 4) {
389          vpx_memcpy(above_row, above_ref, r);
390          vpx_memset(above_row + r, above_row[r - 1],
391                     x0 + 2 * bs - frame_width);
392        } else {
393          vpx_memcpy(above_row, above_ref, bs);
394          vpx_memset(above_row + bs, above_row[bs - 1], bs);
395        }
396      } else if (x0 <= frame_width) {
397        const int r = frame_width - x0;
398        if (right_available && bs == 4) {
399          vpx_memcpy(above_row, above_ref, r);
400          vpx_memset(above_row + r, above_row[r - 1],
401                     x0 + 2 * bs - frame_width);
402        } else {
403          vpx_memcpy(above_row, above_ref, r);
404          vpx_memset(above_row + r, above_row[r - 1],
405                     x0 + 2 * bs - frame_width);
406        }
407      }
408      above_row[-1] = left_available ? above_ref[-1] : 129;
409    } else {
410      /* faster path if the block does not need extension */
411      if (bs == 4 && right_available && left_available) {
412        const_above_row = above_ref;
413      } else {
414        vpx_memcpy(above_row, above_ref, bs);
415        if (bs == 4 && right_available)
416          vpx_memcpy(above_row + bs, above_ref + bs, bs);
417        else
418          vpx_memset(above_row + bs, above_row[bs - 1], bs);
419        above_row[-1] = left_available ? above_ref[-1] : 129;
420      }
421    }
422  } else {
423    vpx_memset(above_row, 127, bs * 2);
424    above_row[-1] = 127;
425  }
426
427  // predict
428  if (mode == DC_PRED) {
429    dc_pred[left_available][up_available][tx_size](dst, dst_stride,
430                                                   const_above_row, left_col);
431  } else {
432    pred[mode][tx_size](dst, dst_stride, const_above_row, left_col);
433  }
434}
435
436void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
437                             TX_SIZE tx_size, MB_PREDICTION_MODE mode,
438                             const uint8_t *ref, int ref_stride,
439                             uint8_t *dst, int dst_stride,
440                             int aoff, int loff, int plane) {
441  const int bwl = bwl_in - tx_size;
442  const int wmask = (1 << bwl) - 1;
443  const int have_top = (block_idx >> bwl) || xd->up_available;
444  const int have_left = (block_idx & wmask) || xd->left_available;
445  const int have_right = ((block_idx & wmask) != wmask);
446  const int x = aoff * 4;
447  const int y = loff * 4;
448
449  assert(bwl >= 0);
450  build_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode, tx_size,
451                         have_top, have_left, have_right, x, y, plane);
452}
453