reconintra.c 58 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10 11
 */

hui su's avatar
hui su committed
12 13
#include <math.h>

Yaowu Xu's avatar
Yaowu Xu committed
14 15 16
#include "./av1_rtcd.h"
#include "./aom_config.h"
#include "./aom_dsp_rtcd.h"
17
#include "aom_ports/system_state.h"
Jingning Han's avatar
Jingning Han committed
18

Yaowu Xu's avatar
Yaowu Xu committed
19 20 21 22
#if CONFIG_AOM_HIGHBITDEPTH
#include "aom_dsp/aom_dsp_common.h"
#endif  // CONFIG_AOM_HIGHBITDEPTH
#include "aom_mem/aom_mem.h"
23
#include "aom_ports/mem.h"
Yaowu Xu's avatar
Yaowu Xu committed
24
#include "aom_ports/aom_once.h"
25 26
#include "av1/common/reconintra.h"
#include "av1/common/onyxc_int.h"
Jingning Han's avatar
Jingning Han committed
27

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
enum {
  NEED_LEFT = 1 << 1,
  NEED_ABOVE = 1 << 2,
  NEED_ABOVERIGHT = 1 << 3,
  NEED_ABOVELEFT = 1 << 4,
  NEED_BOTTOMLEFT = 1 << 5,
};

static const uint8_t extend_modes[INTRA_MODES] = {
  NEED_ABOVE | NEED_LEFT,                   // DC
  NEED_ABOVE,                               // V
  NEED_LEFT,                                // H
  NEED_ABOVE | NEED_ABOVERIGHT,             // D45
  NEED_LEFT | NEED_ABOVE | NEED_ABOVELEFT,  // D135
  NEED_LEFT | NEED_ABOVE | NEED_ABOVELEFT,  // D117
  NEED_LEFT | NEED_ABOVE | NEED_ABOVELEFT,  // D153
  NEED_LEFT | NEED_BOTTOMLEFT,              // D207
  NEED_ABOVE | NEED_ABOVERIGHT,             // D63
46 47 48
#if CONFIG_ALT_INTRA
  NEED_LEFT | NEED_ABOVE,                   // SMOOTH
#endif                                      // CONFIG_ALT_INTRA
49 50
  NEED_LEFT | NEED_ABOVE | NEED_ABOVELEFT,  // TM
};
Jingning Han's avatar
Jingning Han committed
51

52 53 54 55
static const uint8_t orders_128x128[1] = { 0 };
static const uint8_t orders_128x64[2] = { 0, 1 };
static const uint8_t orders_64x128[2] = { 0, 1 };
static const uint8_t orders_64x64[4] = {
clang-format's avatar
clang-format committed
56
  0, 1, 2, 3,
57
};
58
static const uint8_t orders_64x32[8] = {
clang-format's avatar
clang-format committed
59
  0, 2, 1, 3, 4, 6, 5, 7,
60
};
61
static const uint8_t orders_32x64[8] = {
clang-format's avatar
clang-format committed
62
  0, 1, 2, 3, 4, 5, 6, 7,
63
};
64
static const uint8_t orders_32x32[16] = {
clang-format's avatar
clang-format committed
65
  0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15,
66
};
67
static const uint8_t orders_32x16[32] = {
clang-format's avatar
clang-format committed
68 69
  0,  2,  8,  10, 1,  3,  9,  11, 4,  6,  12, 14, 5,  7,  13, 15,
  16, 18, 24, 26, 17, 19, 25, 27, 20, 22, 28, 30, 21, 23, 29, 31,
70
};
71
static const uint8_t orders_16x32[32] = {
clang-format's avatar
clang-format committed
72 73
  0,  1,  2,  3,  8,  9,  10, 11, 4,  5,  6,  7,  12, 13, 14, 15,
  16, 17, 18, 19, 24, 25, 26, 27, 20, 21, 22, 23, 28, 29, 30, 31,
74
};
75
static const uint8_t orders_16x16[64] = {
clang-format's avatar
clang-format committed
76 77 78 79
  0,  1,  4,  5,  16, 17, 20, 21, 2,  3,  6,  7,  18, 19, 22, 23,
  8,  9,  12, 13, 24, 25, 28, 29, 10, 11, 14, 15, 26, 27, 30, 31,
  32, 33, 36, 37, 48, 49, 52, 53, 34, 35, 38, 39, 50, 51, 54, 55,
  40, 41, 44, 45, 56, 57, 60, 61, 42, 43, 46, 47, 58, 59, 62, 63,
80
};
81 82 83

#if CONFIG_EXT_PARTITION
static const uint8_t orders_16x8[128] = {
clang-format's avatar
clang-format committed
84 85 86 87 88 89 90 91
  0,  2,  8,  10, 32,  34,  40,  42,  1,  3,  9,  11, 33,  35,  41,  43,
  4,  6,  12, 14, 36,  38,  44,  46,  5,  7,  13, 15, 37,  39,  45,  47,
  16, 18, 24, 26, 48,  50,  56,  58,  17, 19, 25, 27, 49,  51,  57,  59,
  20, 22, 28, 30, 52,  54,  60,  62,  21, 23, 29, 31, 53,  55,  61,  63,
  64, 66, 72, 74, 96,  98,  104, 106, 65, 67, 73, 75, 97,  99,  105, 107,
  68, 70, 76, 78, 100, 102, 108, 110, 69, 71, 77, 79, 101, 103, 109, 111,
  80, 82, 88, 90, 112, 114, 120, 122, 81, 83, 89, 91, 113, 115, 121, 123,
  84, 86, 92, 94, 116, 118, 124, 126, 85, 87, 93, 95, 117, 119, 125, 127,
92 93
};
static const uint8_t orders_8x16[128] = {
clang-format's avatar
clang-format committed
94 95 96 97 98
  0,  1,  2,  3,  8,  9,  10, 11, 32,  33,  34,  35,  40,  41,  42,  43,
  4,  5,  6,  7,  12, 13, 14, 15, 36,  37,  38,  39,  44,  45,  46,  47,
  16, 17, 18, 19, 24, 25, 26, 27, 48,  49,  50,  51,  56,  57,  58,  59,
  20, 21, 22, 23, 28, 29, 30, 31, 52,  53,  54,  55,  60,  61,  62,  63,
  64, 65, 66, 67, 72, 73, 74, 75, 96,  97,  98,  99,  104, 105, 106, 107,
99 100 101 102 103
  68, 69, 70, 71, 76, 77, 78, 79, 100, 101, 102, 103, 108, 109, 110, 111,
  80, 81, 82, 83, 88, 89, 90, 91, 112, 113, 114, 115, 120, 121, 122, 123,
  84, 85, 86, 87, 92, 93, 94, 95, 116, 117, 118, 119, 124, 125, 126, 127,
};
static const uint8_t orders_8x8[256] = {
clang-format's avatar
clang-format committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
  0,   1,   4,   5,   16,  17,  20,  21,  64,  65,  68,  69,  80,  81,  84,
  85,  2,   3,   6,   7,   18,  19,  22,  23,  66,  67,  70,  71,  82,  83,
  86,  87,  8,   9,   12,  13,  24,  25,  28,  29,  72,  73,  76,  77,  88,
  89,  92,  93,  10,  11,  14,  15,  26,  27,  30,  31,  74,  75,  78,  79,
  90,  91,  94,  95,  32,  33,  36,  37,  48,  49,  52,  53,  96,  97,  100,
  101, 112, 113, 116, 117, 34,  35,  38,  39,  50,  51,  54,  55,  98,  99,
  102, 103, 114, 115, 118, 119, 40,  41,  44,  45,  56,  57,  60,  61,  104,
  105, 108, 109, 120, 121, 124, 125, 42,  43,  46,  47,  58,  59,  62,  63,
  106, 107, 110, 111, 122, 123, 126, 127, 128, 129, 132, 133, 144, 145, 148,
  149, 192, 193, 196, 197, 208, 209, 212, 213, 130, 131, 134, 135, 146, 147,
  150, 151, 194, 195, 198, 199, 210, 211, 214, 215, 136, 137, 140, 141, 152,
  153, 156, 157, 200, 201, 204, 205, 216, 217, 220, 221, 138, 139, 142, 143,
  154, 155, 158, 159, 202, 203, 206, 207, 218, 219, 222, 223, 160, 161, 164,
  165, 176, 177, 180, 181, 224, 225, 228, 229, 240, 241, 244, 245, 162, 163,
  166, 167, 178, 179, 182, 183, 226, 227, 230, 231, 242, 243, 246, 247, 168,
  169, 172, 173, 184, 185, 188, 189, 232, 233, 236, 237, 248, 249, 252, 253,
  170, 171, 174, 175, 186, 187, 190, 191, 234, 235, 238, 239, 250, 251, 254,
  255,
122 123
};

clang-format's avatar
clang-format committed
124
/* clang-format off */
125
static const uint8_t *const orders[BLOCK_SIZES] = {
Jingning Han's avatar
Jingning Han committed
126 127 128 129
#if CONFIG_CB4X4
  // 2X2,         2X4,            4X2
  orders_8x8,     orders_8x8,     orders_8x8,
#endif
130 131 132 133 134 135 136 137 138 139 140 141
  //                              4X4
                                  orders_8x8,
  // 4X8,         8X4,            8X8
  orders_8x8,     orders_8x8,     orders_8x8,
  // 8X16,        16X8,           16X16
  orders_8x16,    orders_16x8,    orders_16x16,
  // 16X32,       32X16,          32X32
  orders_16x32,   orders_32x16,   orders_32x32,
  // 32X64,       64X32,          64X64
  orders_32x64,   orders_64x32,   orders_64x64,
  // 64x128,      128x64,         128x128
  orders_64x128,  orders_128x64,  orders_128x128
142
};
clang-format's avatar
clang-format committed
143
/* clang-format on */
144
#else
clang-format's avatar
clang-format committed
145
/* clang-format off */
146
static const uint8_t *const orders[BLOCK_SIZES] = {
Jingning Han's avatar
Jingning Han committed
147 148 149 150
#if CONFIG_CB4X4
  // 2X2,         2X4,            4X2
  orders_16x16,   orders_16x16,   orders_16x16,
#endif
151 152 153 154 155 156 157 158 159 160 161
  //                              4X4
                                  orders_16x16,
  // 4X8,         8X4,            8X8
  orders_16x16,   orders_16x16,   orders_16x16,
  // 8X16,        16X8,           16X16
  orders_16x32,   orders_32x16,   orders_32x32,
  // 16X32,       32X16,          32X32
  orders_32x64,   orders_64x32,   orders_64x64,
  // 32X64,       64X32,          64X64
  orders_64x128,  orders_128x64,  orders_128x128
};
clang-format's avatar
clang-format committed
162
/* clang-format on */
163 164
#endif  // CONFIG_EXT_PARTITION

165
#if CONFIG_EXT_PARTITION_TYPES
166
static const uint8_t orders_verta_64x64[4] = {
clang-format's avatar
clang-format committed
167
  0, 2, 1, 2,
168
};
169
static const uint8_t orders_verta_32x32[16] = {
clang-format's avatar
clang-format committed
170
  0, 2, 4, 6, 1, 2, 5, 6, 8, 10, 12, 14, 9, 10, 13, 14,
171
};
172
static const uint8_t orders_verta_16x16[64] = {
clang-format's avatar
clang-format committed
173 174 175 176
  0,  2,  4,  6,  16, 18, 20, 22, 1,  2,  5,  6,  17, 18, 21, 22,
  8,  10, 12, 14, 24, 26, 28, 30, 9,  10, 13, 14, 25, 26, 29, 30,
  32, 34, 36, 38, 48, 50, 52, 54, 33, 34, 37, 38, 49, 50, 53, 54,
  40, 42, 44, 46, 56, 58, 60, 62, 41, 42, 45, 46, 57, 58, 61, 62,
177
};
178 179
#if CONFIG_EXT_PARTITION
static const uint8_t orders_verta_8x8[256] = {
clang-format's avatar
clang-format committed
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
  0,   2,   4,   6,   16,  18,  20,  22,  64,  66,  68,  70,  80,  82,  84,
  86,  1,   2,   5,   6,   17,  18,  21,  22,  65,  66,  69,  70,  81,  82,
  85,  86,  8,   10,  12,  14,  24,  26,  28,  30,  72,  74,  76,  78,  88,
  90,  92,  94,  9,   10,  13,  14,  25,  26,  29,  30,  73,  74,  77,  78,
  89,  90,  93,  94,  32,  34,  36,  38,  48,  50,  52,  54,  96,  98,  100,
  102, 112, 114, 116, 118, 33,  34,  37,  38,  49,  50,  53,  54,  97,  98,
  101, 102, 113, 114, 117, 118, 40,  42,  44,  46,  56,  58,  60,  62,  104,
  106, 108, 110, 120, 122, 124, 126, 41,  42,  45,  46,  57,  58,  61,  62,
  105, 106, 109, 110, 121, 122, 125, 126, 128, 130, 132, 134, 144, 146, 148,
  150, 192, 194, 196, 198, 208, 210, 212, 214, 129, 130, 133, 134, 145, 146,
  149, 150, 193, 194, 197, 198, 209, 210, 213, 214, 136, 138, 140, 142, 152,
  154, 156, 158, 200, 202, 204, 206, 216, 218, 220, 222, 137, 138, 141, 142,
  153, 154, 157, 158, 201, 202, 205, 206, 217, 218, 221, 222, 160, 162, 164,
  166, 176, 178, 180, 182, 224, 226, 228, 230, 240, 242, 244, 246, 161, 162,
  165, 166, 177, 178, 181, 182, 225, 226, 229, 230, 241, 242, 245, 246, 168,
  170, 172, 174, 184, 186, 188, 190, 232, 234, 236, 238, 248, 250, 252, 254,
  169, 170, 173, 174, 185, 186, 189, 190, 233, 234, 237, 238, 249, 250, 253,
  254,
198
};
clang-format's avatar
clang-format committed
199 200

/* clang-format off */
201 202 203 204 205 206 207 208 209 210 211 212 213 214
static const uint8_t *const orders_verta[BLOCK_SIZES] = {
  //                                  4X4
                                      orders_verta_8x8,
  // 4X8,           8X4,              8X8
  orders_verta_8x8, orders_verta_8x8, orders_verta_8x8,
  // 8X16,          16X8,             16X16
  orders_8x16,      orders_16x8,      orders_verta_16x16,
  // 16X32,         32X16,            32X32
  orders_16x32,     orders_32x16,     orders_verta_32x32,
  // 32X64,         64X32,            64X64
  orders_32x64,     orders_64x32,     orders_verta_64x64,
  // 64x128,        128x64,           128x128
  orders_64x128,    orders_128x64,    orders_128x128
};
clang-format's avatar
clang-format committed
215
/* clang-format on */
216
#else
clang-format's avatar
clang-format committed
217
/* clang-format off */
218
static const uint8_t *const orders_verta[BLOCK_SIZES] = {
219 220 221 222 223 224 225 226 227 228
  //                                      4X4
                                          orders_verta_16x16,
  // 4X8,             8X4,                8X8
  orders_verta_16x16, orders_verta_16x16, orders_verta_16x16,
  // 8X16,            16X8,               16X16
  orders_16x32,       orders_32x16,       orders_verta_32x32,
  // 16X32,           32X16,              32X32
  orders_32x64,       orders_64x32,       orders_verta_64x64,
  // 32X64,           64X32,              64X64
  orders_64x128,      orders_128x64,      orders_128x128
229
};
clang-format's avatar
clang-format committed
230
/* clang-format on */
231
#endif  // CONFIG_EXT_PARTITION
232
#endif  // CONFIG_EXT_PARTITION_TYPES
233

Yaowu Xu's avatar
Yaowu Xu committed
234 235
static int av1_has_right(BLOCK_SIZE bsize, int mi_row, int mi_col,
                         int right_available,
236
#if CONFIG_EXT_PARTITION_TYPES
Yaowu Xu's avatar
Yaowu Xu committed
237
                         PARTITION_TYPE partition,
238
#endif
Yaowu Xu's avatar
Yaowu Xu committed
239
                         TX_SIZE txsz, int y, int x, int ss_x) {
hui su's avatar
hui su committed
240
  const int wl = mi_width_log2_lookup[bsize];
Yaowu Xu's avatar
Yaowu Xu committed
241
  const int w = AOMMAX(num_4x4_blocks_wide_lookup[bsize] >> ss_x, 1);
242
  const int step = tx_size_wide_unit[txsz];
hui su's avatar
hui su committed
243

244 245 246 247 248 249 250 251
  // TODO(bshacklett, huisu): Currently the RD loop traverses 4X8 blocks in
  // inverted N order while in the bitstream the subblocks are stored in Z
  // order. This discrepancy makes this function incorrect when considering 4X8
  // blocks in the RD loop, so we disable the extended right edge for these
  // blocks. The correct solution is to change the bitstream to store these
  // blocks in inverted N order, and then update this function appropriately.
  if (bsize == BLOCK_4X8 && y == 1) return 0;

252 253 254 255
  if (!right_available) return 0;

  // Handle block size 4x8 and 4x4
  if (ss_x == 0 && num_4x4_blocks_wide_lookup[bsize] < 2 && x == 0) return 1;
256

257 258 259 260
  if (y == 0) {
    const int hl = mi_height_log2_lookup[bsize];
    const uint8_t *order;
    int my_order, tr_order;
261
#if CONFIG_EXT_PARTITION_TYPES
262 263 264
    if (partition == PARTITION_VERT_A)
      order = orders_verta[bsize];
    else
265
#endif  // CONFIG_EXT_PARTITION_TYPES
266
      order = orders[bsize];
267

268
    if (x + step < w) return 1;
269

270 271
    mi_row = (mi_row & MAX_MIB_MASK) >> hl;
    mi_col = (mi_col & MAX_MIB_MASK) >> wl;
272

273 274
    // If top row of coding unit
    if (mi_row == 0) return 1;
275

276 277
    // If rightmost column of coding unit
    if (((mi_col + 1) << wl) >= MAX_MIB_SIZE) return 0;
278

279 280
    my_order = order[((mi_row + 0) << (MAX_MIB_SIZE_LOG2 - wl)) + mi_col + 0];
    tr_order = order[((mi_row - 1) << (MAX_MIB_SIZE_LOG2 - wl)) + mi_col + 1];
281

282 283 284
    return my_order > tr_order;
  } else {
    return x + step < w;
285 286 287
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
288 289 290
static int av1_has_bottom(BLOCK_SIZE bsize, int mi_row, int mi_col,
                          int bottom_available, TX_SIZE txsz, int y, int x,
                          int ss_y) {
291 292 293
  if (!bottom_available || x != 0) {
    return 0;
  } else {
hui su's avatar
hui su committed
294 295 296
    const int wl = mi_width_log2_lookup[bsize];
    const int hl = mi_height_log2_lookup[bsize];
    const int h = 1 << (hl + 1 - ss_y);
297
    const int step = tx_size_wide_unit[txsz];
298 299 300
    const uint8_t *order = orders[bsize];
    int my_order, bl_order;

301
    // Handle block size 8x4 and 4x4
clang-format's avatar
clang-format committed
302
    if (ss_y == 0 && num_4x4_blocks_high_lookup[bsize] < 2 && y == 0) return 1;
303

clang-format's avatar
clang-format committed
304
    if (y + step < h) return 1;
305

306 307
    mi_row = (mi_row & MAX_MIB_MASK) >> hl;
    mi_col = (mi_col & MAX_MIB_MASK) >> wl;
308 309

    if (mi_col == 0)
310
      return (mi_row << (hl + !ss_y)) + y + step < (MAX_MIB_SIZE << !ss_y);
311

clang-format's avatar
clang-format committed
312
    if (((mi_row + 1) << hl) >= MAX_MIB_SIZE) return 0;
313

314 315
    my_order = order[((mi_row + 0) << (MAX_MIB_SIZE_LOG2 - wl)) + mi_col + 0];
    bl_order = order[((mi_row + 1) << (MAX_MIB_SIZE_LOG2 - wl)) + mi_col - 1];
316

317
    return bl_order < my_order;
318 319
  }
}
Jingning Han's avatar
Jingning Han committed
320 321 322 323 324 325 326

typedef void (*intra_pred_fn)(uint8_t *dst, ptrdiff_t stride,
                              const uint8_t *above, const uint8_t *left);

static intra_pred_fn pred[INTRA_MODES][TX_SIZES];
static intra_pred_fn dc_pred[2][2][TX_SIZES];

Yaowu Xu's avatar
Yaowu Xu committed
327
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
328 329 330
typedef void (*intra_high_pred_fn)(uint16_t *dst, ptrdiff_t stride,
                                   const uint16_t *above, const uint16_t *left,
                                   int bd);
331 332
static intra_high_pred_fn pred_high[INTRA_MODES][TX_SIZES];
static intra_high_pred_fn dc_pred_high[2][2][TX_SIZES];
Yaowu Xu's avatar
Yaowu Xu committed
333
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
334

Yaowu Xu's avatar
Yaowu Xu committed
335
static void av1_init_intra_predictors_internal(void) {
336 337 338 339 340 341 342
#if CONFIG_TX64X64
#define INIT_NO_4X4(p, type)                  \
  p[TX_8X8] = aom_##type##_predictor_8x8;     \
  p[TX_16X16] = aom_##type##_predictor_16x16; \
  p[TX_32X32] = aom_##type##_predictor_32x32; \
  p[TX_64X64] = aom_##type##_predictor_64x64
#else
clang-format's avatar
clang-format committed
343
#define INIT_NO_4X4(p, type)                  \
Yaowu Xu's avatar
Yaowu Xu committed
344 345 346
  p[TX_8X8] = aom_##type##_predictor_8x8;     \
  p[TX_16X16] = aom_##type##_predictor_16x16; \
  p[TX_32X32] = aom_##type##_predictor_32x32
347
#endif  // CONFIG_TX64X64
Jingning Han's avatar
Jingning Han committed
348

clang-format's avatar
clang-format committed
349
#define INIT_ALL_SIZES(p, type)           \
Yaowu Xu's avatar
Yaowu Xu committed
350
  p[TX_4X4] = aom_##type##_predictor_4x4; \
351 352
  INIT_NO_4X4(p, type)

Jingning Han's avatar
Jingning Han committed
353 354
  INIT_ALL_SIZES(pred[V_PRED], v);
  INIT_ALL_SIZES(pred[H_PRED], h);
355 356 357
  INIT_ALL_SIZES(pred[D207_PRED], d207e);
  INIT_ALL_SIZES(pred[D45_PRED], d45e);
  INIT_ALL_SIZES(pred[D63_PRED], d63e);
Jingning Han's avatar
Jingning Han committed
358 359 360
  INIT_ALL_SIZES(pred[D117_PRED], d117);
  INIT_ALL_SIZES(pred[D135_PRED], d135);
  INIT_ALL_SIZES(pred[D153_PRED], d153);
Urvang Joshi's avatar
Urvang Joshi committed
361 362 363

#if CONFIG_ALT_INTRA
  INIT_ALL_SIZES(pred[TM_PRED], paeth);
364
  INIT_ALL_SIZES(pred[SMOOTH_PRED], smooth);
Urvang Joshi's avatar
Urvang Joshi committed
365
#else
Jingning Han's avatar
Jingning Han committed
366
  INIT_ALL_SIZES(pred[TM_PRED], tm);
Urvang Joshi's avatar
Urvang Joshi committed
367
#endif  // CONFIG_ALT_INTRA
Jingning Han's avatar
Jingning Han committed
368 369 370 371 372 373

  INIT_ALL_SIZES(dc_pred[0][0], dc_128);
  INIT_ALL_SIZES(dc_pred[0][1], dc_top);
  INIT_ALL_SIZES(dc_pred[1][0], dc_left);
  INIT_ALL_SIZES(dc_pred[1][1], dc);

Yaowu Xu's avatar
Yaowu Xu committed
374
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
375 376
  INIT_ALL_SIZES(pred_high[V_PRED], highbd_v);
  INIT_ALL_SIZES(pred_high[H_PRED], highbd_h);
377 378 379
  INIT_ALL_SIZES(pred_high[D207_PRED], highbd_d207e);
  INIT_ALL_SIZES(pred_high[D45_PRED], highbd_d45e);
  INIT_ALL_SIZES(pred_high[D63_PRED], highbd_d63e);
Jingning Han's avatar
Jingning Han committed
380 381 382
  INIT_ALL_SIZES(pred_high[D117_PRED], highbd_d117);
  INIT_ALL_SIZES(pred_high[D135_PRED], highbd_d135);
  INIT_ALL_SIZES(pred_high[D153_PRED], highbd_d153);
Urvang Joshi's avatar
Urvang Joshi committed
383 384 385

#if CONFIG_ALT_INTRA
  INIT_ALL_SIZES(pred_high[TM_PRED], highbd_paeth);
386
  INIT_ALL_SIZES(pred_high[SMOOTH_PRED], highbd_smooth);
Urvang Joshi's avatar
Urvang Joshi committed
387
#else
Jingning Han's avatar
Jingning Han committed
388
  INIT_ALL_SIZES(pred_high[TM_PRED], highbd_tm);
Urvang Joshi's avatar
Urvang Joshi committed
389
#endif  // CONFIG_ALT_INTRA
Jingning Han's avatar
Jingning Han committed
390 391 392 393 394

  INIT_ALL_SIZES(dc_pred_high[0][0], highbd_dc_128);
  INIT_ALL_SIZES(dc_pred_high[0][1], highbd_dc_top);
  INIT_ALL_SIZES(dc_pred_high[1][0], highbd_dc_left);
  INIT_ALL_SIZES(dc_pred_high[1][1], highbd_dc);
Yaowu Xu's avatar
Yaowu Xu committed
395
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
396 397 398 399

#undef intra_pred_allsizes
}

hui su's avatar
hui su committed
400
#if CONFIG_EXT_INTRA
401 402 403 404 405 406 407 408 409 410 411
static int intra_subpel_interp(int base, int shift, const uint8_t *ref,
                               int ref_start_idx, int ref_end_idx,
                               INTRA_FILTER filter_type) {
  int val, k, idx, filter_idx = 0;
  const int16_t *filter = NULL;

  if (filter_type == INTRA_FILTER_LINEAR) {
    val = ref[base] * (256 - shift) + ref[base + 1] * shift;
    val = ROUND_POWER_OF_TWO(val, 8);
  } else {
    filter_idx = ROUND_POWER_OF_TWO(shift, 8 - SUBPEL_BITS);
Yaowu Xu's avatar
Yaowu Xu committed
412
    filter = av1_intra_filter_kernels[filter_type][filter_idx];
413 414 415 416 417

    if (filter_idx < (1 << SUBPEL_BITS)) {
      val = 0;
      for (k = 0; k < SUBPEL_TAPS; ++k) {
        idx = base + 1 - (SUBPEL_TAPS / 2) + k;
Yaowu Xu's avatar
Yaowu Xu committed
418
        idx = AOMMAX(AOMMIN(idx, ref_end_idx), ref_start_idx);
419 420 421 422 423 424 425 426 427 428 429
        val += ref[idx] * filter[k];
      }
      val = ROUND_POWER_OF_TWO(val, FILTER_BITS);
    } else {
      val = ref[base + 1];
    }
  }

  return val;
}

hui su's avatar
hui su committed
430 431
// Directional prediction, zone 1: 0 < angle < 90
static void dr_prediction_z1(uint8_t *dst, ptrdiff_t stride, int bs,
clang-format's avatar
clang-format committed
432 433
                             const uint8_t *above, const uint8_t *left, int dx,
                             int dy, INTRA_FILTER filter_type) {
hui su's avatar
hui su committed
434
  int r, c, x, base, shift, val;
hui su's avatar
hui su committed
435 436 437 438 439 440

  (void)left;
  (void)dy;
  assert(dy == 1);
  assert(dx < 0);

hui su's avatar
hui su committed
441 442 443
  if (filter_type != INTRA_FILTER_LINEAR) {
    const int pad_size = SUBPEL_TAPS >> 1;
    int len;
444 445
    DECLARE_ALIGNED(16, uint8_t, buf[SUBPEL_SHIFTS][MAX_SB_SIZE]);
    DECLARE_ALIGNED(16, uint8_t, src[MAX_SB_SIZE + SUBPEL_TAPS]);
hui su's avatar
hui su committed
446 447 448 449 450 451 452 453 454 455
    uint8_t flags[SUBPEL_SHIFTS];

    memset(flags, 0, SUBPEL_SHIFTS * sizeof(flags[0]));
    memset(src, above[0], pad_size * sizeof(above[0]));
    memcpy(src + pad_size, above, 2 * bs * sizeof(above[0]));
    memset(src + pad_size + 2 * bs, above[2 * bs - 1],
           pad_size * sizeof(above[0]));
    flags[0] = 1;
    x = -dx;
    for (r = 0; r < bs; ++r, dst += stride, x -= dx) {
hui su's avatar
hui su committed
456
      base = x >> 8;
hui su's avatar
hui su committed
457 458 459 460 461 462
      shift = x & 0xFF;
      shift = ROUND_POWER_OF_TWO(shift, 8 - SUBPEL_BITS);
      if (shift == SUBPEL_SHIFTS) {
        base += 1;
        shift = 0;
      }
Yaowu Xu's avatar
Yaowu Xu committed
463
      len = AOMMIN(bs, 2 * bs - 1 - base);
hui su's avatar
hui su committed
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
      if (len <= 0) {
        int i;
        for (i = r; i < bs; ++i) {
          memset(dst, above[2 * bs - 1], bs * sizeof(dst[0]));
          dst += stride;
        }
        return;
      }

      if (len <= (bs >> 1) && !flags[shift]) {
        base = x >> 8;
        shift = x & 0xFF;
        for (c = 0; c < len; ++c) {
          val = intra_subpel_interp(base, shift, above, 0, 2 * bs - 1,
                                    filter_type);
          dst[c] = clip_pixel(val);
          ++base;
        }
      } else {
        if (!flags[shift]) {
Yaowu Xu's avatar
Yaowu Xu committed
484 485
          const int16_t *filter = av1_intra_filter_kernels[filter_type][shift];
          aom_convolve8_horiz(src + pad_size, 2 * bs, buf[shift], 2 * bs,
clang-format's avatar
clang-format committed
486 487
                              filter, 16, NULL, 16, 2 * bs,
                              2 * bs < 16 ? 2 : 1);
hui su's avatar
hui su committed
488 489 490
          flags[shift] = 1;
        }
        memcpy(dst, shift == 0 ? src + pad_size + base : &buf[shift][base],
clang-format's avatar
clang-format committed
491
               len * sizeof(dst[0]));
hui su's avatar
hui su committed
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515
      }

      if (len < bs)
        memset(dst + len, above[2 * bs - 1], (bs - len) * sizeof(dst[0]));
    }
    return;
  }

  // For linear filter, C code is faster.
  x = -dx;
  for (r = 0; r < bs; ++r, dst += stride, x -= dx) {
    base = x >> 8;
    shift = x & 0xFF;

    if (base >= 2 * bs - 1) {
      int i;
      for (i = r; i < bs; ++i) {
        memset(dst, above[2 * bs - 1], bs * sizeof(dst[0]));
        dst += stride;
      }
      return;
    }

    for (c = 0; c < bs; ++c, ++base) {
hui su's avatar
hui su committed
516
      if (base < 2 * bs - 1) {
hui su's avatar
hui su committed
517 518
        val = above[base] * (256 - shift) + above[base + 1] * shift;
        val = ROUND_POWER_OF_TWO(val, 8);
hui su's avatar
hui su committed
519 520 521 522 523 524 525 526 527 528
        dst[c] = clip_pixel(val);
      } else {
        dst[c] = above[2 * bs - 1];
      }
    }
  }
}

// Directional prediction, zone 2: 90 < angle < 180
static void dr_prediction_z2(uint8_t *dst, ptrdiff_t stride, int bs,
clang-format's avatar
clang-format committed
529 530
                             const uint8_t *above, const uint8_t *left, int dx,
                             int dy, INTRA_FILTER filter_type) {
Debargha Mukherjee's avatar
Debargha Mukherjee committed
531
  int r, c, x, y, shift1, shift2, val, base1, base2;
hui su's avatar
hui su committed
532 533 534 535

  assert(dx > 0);
  assert(dy > 0);

hui su's avatar
hui su committed
536 537 538 539 540 541 542
  x = -dx;
  for (r = 0; r < bs; ++r, x -= dx, dst += stride) {
    base1 = x >> 8;
    y = (r << 8) - dy;
    for (c = 0; c < bs; ++c, ++base1, y -= dy) {
      if (base1 >= -1) {
        shift1 = x & 0xFF;
clang-format's avatar
clang-format committed
543 544
        val =
            intra_subpel_interp(base1, shift1, above, -1, bs - 1, filter_type);
hui su's avatar
hui su committed
545
      } else {
hui su's avatar
hui su committed
546 547 548
        base2 = y >> 8;
        if (base2 >= 0) {
          shift2 = y & 0xFF;
clang-format's avatar
clang-format committed
549 550
          val =
              intra_subpel_interp(base2, shift2, left, 0, bs - 1, filter_type);
hui su's avatar
hui su committed
551
        } else {
552
          val = left[0];
hui su's avatar
hui su committed
553 554 555 556 557 558 559 560 561
        }
      }
      dst[c] = clip_pixel(val);
    }
  }
}

// Directional prediction, zone 3: 180 < angle < 270
static void dr_prediction_z3(uint8_t *dst, ptrdiff_t stride, int bs,
clang-format's avatar
clang-format committed
562 563
                             const uint8_t *above, const uint8_t *left, int dx,
                             int dy, INTRA_FILTER filter_type) {
hui su's avatar
hui su committed
564
  int r, c, y, base, shift, val;
hui su's avatar
hui su committed
565 566 567

  (void)above;
  (void)dx;
568

hui su's avatar
hui su committed
569 570 571
  assert(dx == 1);
  assert(dy < 0);

hui su's avatar
hui su committed
572 573 574
  if (filter_type != INTRA_FILTER_LINEAR) {
    const int pad_size = SUBPEL_TAPS >> 1;
    int len, i;
575 576
    DECLARE_ALIGNED(16, uint8_t, buf[MAX_SB_SIZE][4 * SUBPEL_SHIFTS]);
    DECLARE_ALIGNED(16, uint8_t, src[(MAX_SB_SIZE + SUBPEL_TAPS) * 4]);
hui su's avatar
hui su committed
577 578 579
    uint8_t flags[SUBPEL_SHIFTS];

    memset(flags, 0, SUBPEL_SHIFTS * sizeof(flags[0]));
clang-format's avatar
clang-format committed
580 581
    for (i = 0; i < pad_size; ++i) src[4 * i] = left[0];
    for (i = 0; i < 2 * bs; ++i) src[4 * (i + pad_size)] = left[i];
hui su's avatar
hui su committed
582 583 584 585 586
    for (i = 0; i < pad_size; ++i)
      src[4 * (i + 2 * bs + pad_size)] = left[2 * bs - 1];
    flags[0] = 1;
    y = -dy;
    for (c = 0; c < bs; ++c, y -= dy) {
hui su's avatar
hui su committed
587
      base = y >> 8;
hui su's avatar
hui su committed
588 589 590 591 592 593
      shift = y & 0xFF;
      shift = ROUND_POWER_OF_TWO(shift, 8 - SUBPEL_BITS);
      if (shift == SUBPEL_SHIFTS) {
        base += 1;
        shift = 0;
      }
Yaowu Xu's avatar
Yaowu Xu committed
594
      len = AOMMIN(bs, 2 * bs - 1 - base);
hui su's avatar
hui su committed
595 596

      if (len <= 0) {
Debargha Mukherjee's avatar
Debargha Mukherjee committed
597
        for (r = 0; r < bs; ++r) {
clang-format's avatar
clang-format committed
598
          dst[r * stride + c] = left[2 * bs - 1];
hui su's avatar
hui su committed
599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
        }
        continue;
      }

      if (len <= (bs >> 1) && !flags[shift]) {
        base = y >> 8;
        shift = y & 0xFF;
        for (r = 0; r < len; ++r) {
          val = intra_subpel_interp(base, shift, left, 0, 2 * bs - 1,
                                    filter_type);
          dst[r * stride + c] = clip_pixel(val);
          ++base;
        }
      } else {
        if (!flags[shift]) {
Yaowu Xu's avatar
Yaowu Xu committed
614 615
          const int16_t *filter = av1_intra_filter_kernels[filter_type][shift];
          aom_convolve8_vert(src + 4 * pad_size, 4, buf[0] + 4 * shift,
clang-format's avatar
clang-format committed
616
                             4 * SUBPEL_SHIFTS, NULL, 16, filter, 16,
hui su's avatar
hui su committed
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
                             2 * bs < 16 ? 4 : 4, 2 * bs);
          flags[shift] = 1;
        }

        if (shift == 0) {
          for (r = 0; r < len; ++r) {
            dst[r * stride + c] = left[r + base];
          }
        } else {
          for (r = 0; r < len; ++r) {
            dst[r * stride + c] = buf[r + base][4 * shift];
          }
        }
      }

      if (len < bs) {
        for (r = len; r < bs; ++r) {
clang-format's avatar
clang-format committed
634
          dst[r * stride + c] = left[2 * bs - 1];
hui su's avatar
hui su committed
635 636 637 638 639 640 641 642 643 644 645 646 647
        }
      }
    }
    return;
  }

  // For linear filter, C code is faster.
  y = -dy;
  for (c = 0; c < bs; ++c, y -= dy) {
    base = y >> 8;
    shift = y & 0xFF;

    for (r = 0; r < bs; ++r, ++base) {
648
      if (base < 2 * bs - 1) {
hui su's avatar
hui su committed
649 650 651
        val = left[base] * (256 - shift) + left[base + 1] * shift;
        val = ROUND_POWER_OF_TWO(val, 8);
        dst[r * stride + c] = clip_pixel(val);
hui su's avatar
hui su committed
652
      } else {
clang-format's avatar
clang-format committed
653
        for (; r < bs; ++r) dst[r * stride + c] = left[2 * bs - 1];
hui su's avatar
hui su committed
654
        break;
hui su's avatar
hui su committed
655 656 657 658 659
      }
    }
  }
}

660 661 662 663
// Get the shift (up-scaled by 256) in X w.r.t a unit change in Y.
// If angle > 0 && angle < 90, dx = -((int)(256 / t));
// If angle > 90 && angle < 180, dx = (int)(256 / t);
// If angle > 180 && angle < 270, dx = 1;
Yaowu Xu's avatar
Yaowu Xu committed
664
static INLINE int get_dx(int angle) {
665 666 667 668 669 670 671 672 673 674 675 676 677 678
  if (angle > 0 && angle < 90) {
    return -dr_intra_derivative[angle];
  } else if (angle > 90 && angle < 180) {
    return dr_intra_derivative[180 - angle];
  } else {
    // In this case, we are not really going to use dx. We may return any value.
    return 1;
  }
}

// Get the shift (up-scaled by 256) in Y w.r.t a unit change in X.
// If angle > 0 && angle < 90, dy = 1;
// If angle > 90 && angle < 180, dy = (int)(256 * t);
// If angle > 180 && angle < 270, dy = -((int)(256 * t));
Yaowu Xu's avatar
Yaowu Xu committed
679
static INLINE int get_dy(int angle) {
680
  if (angle > 90 && angle < 180) {
clang-format's avatar
clang-format committed
681 682 683 684
    return dr_intra_derivative[angle - 90];
  } else if (angle > 180 && angle < 270) {
    return -dr_intra_derivative[270 - angle];
  } else {
685 686 687 688 689
    // In this case, we are not really going to use dy. We may return any value.
    return 1;
  }
}

hui su's avatar
hui su committed
690
static void dr_predictor(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size,
691 692
                         const uint8_t *above, const uint8_t *left, int angle,
                         INTRA_FILTER filter_type) {
693 694
  const int dx = get_dx(angle);
  const int dy = get_dy(angle);
695
  const int bs = tx_size_wide[tx_size];
696 697
  assert(angle > 0 && angle < 270);

hui su's avatar
hui su committed
698
  if (angle > 0 && angle < 90) {
699
    dr_prediction_z1(dst, stride, bs, above, left, dx, dy, filter_type);
hui su's avatar
hui su committed
700
  } else if (angle > 90 && angle < 180) {
701
    dr_prediction_z2(dst, stride, bs, above, left, dx, dy, filter_type);
hui su's avatar
hui su committed
702
  } else if (angle > 180 && angle < 270) {
703
    dr_prediction_z3(dst, stride, bs, above, left, dx, dy, filter_type);
hui su's avatar
hui su committed
704
  } else if (angle == 90) {
hui su's avatar
hui su committed
705
    pred[V_PRED][tx_size](dst, stride, above, left);
hui su's avatar
hui su committed
706
  } else if (angle == 180) {
hui su's avatar
hui su committed
707
    pred[H_PRED][tx_size](dst, stride, above, left);
hui su's avatar
hui su committed
708 709 710
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
711
#if CONFIG_AOM_HIGHBITDEPTH
712 713 714 715 716 717 718 719 720 721 722
static int highbd_intra_subpel_interp(int base, int shift, const uint16_t *ref,
                                      int ref_start_idx, int ref_end_idx,
                                      INTRA_FILTER filter_type) {
  int val, k, idx, filter_idx = 0;
  const int16_t *filter = NULL;

  if (filter_type == INTRA_FILTER_LINEAR) {
    val = ref[base] * (256 - shift) + ref[base + 1] * shift;
    val = ROUND_POWER_OF_TWO(val, 8);
  } else {
    filter_idx = ROUND_POWER_OF_TWO(shift, 8 - SUBPEL_BITS);
Yaowu Xu's avatar
Yaowu Xu committed
723
    filter = av1_intra_filter_kernels[filter_type][filter_idx];
724 725 726 727 728

    if (filter_idx < (1 << SUBPEL_BITS)) {
      val = 0;
      for (k = 0; k < SUBPEL_TAPS; ++k) {
        idx = base + 1 - (SUBPEL_TAPS / 2) + k;
Yaowu Xu's avatar
Yaowu Xu committed
729
        idx = AOMMAX(AOMMIN(idx, ref_end_idx), ref_start_idx);
730 731 732 733 734 735 736 737 738 739 740
        val += ref[idx] * filter[k];
      }
      val = ROUND_POWER_OF_TWO(val, FILTER_BITS);
    } else {
      val = ref[base + 1];
    }
  }

  return val;
}

hui su's avatar
hui su committed
741 742 743
// Directional prediction, zone 1: 0 < angle < 90
static void highbd_dr_prediction_z1(uint16_t *dst, ptrdiff_t stride, int bs,
                                    const uint16_t *above, const uint16_t *left,
744 745
                                    int dx, int dy, int bd,
                                    INTRA_FILTER filter_type) {
hui su's avatar
hui su committed
746 747 748 749 750 751 752 753 754 755
  int r, c, x, y, base, shift, val;

  (void)left;
  (void)dy;
  assert(dy == 1);
  assert(dx < 0);

  for (r = 0; r < bs; ++r) {
    y = r + 1;
    for (c = 0; c < bs; ++c) {
756
      x = (c << 8) - y * dx;
hui su's avatar
hui su committed
757
      base = x >> 8;
758
      shift = x & 0xFF;
hui su's avatar
hui su committed
759
      if (base < 2 * bs - 1) {
760 761
        val = highbd_intra_subpel_interp(base, shift, above, 0, 2 * bs - 1,
                                         filter_type);
hui su's avatar
hui su committed
762 763 764 765 766 767 768 769 770 771 772 773
        dst[c] = clip_pixel_highbd(val, bd);
      } else {
        dst[c] = above[2 * bs - 1];
      }
    }
    dst += stride;
  }
}

// Directional prediction, zone 2: 90 < angle < 180
static void highbd_dr_prediction_z2(uint16_t *dst, ptrdiff_t stride, int bs,
                                    const uint16_t *above, const uint16_t *left,
774 775 776
                                    int dx, int dy, int bd,
                                    INTRA_FILTER filter_type) {
  int r, c, x, y, shift, val, base;
hui su's avatar
hui su committed
777 778 779 780 781 782 783

  assert(dx > 0);
  assert(dy > 0);

  for (r = 0; r < bs; ++r) {
    for (c = 0; c < bs; ++c) {
      y = r + 1;
784 785 786
      x = (c << 8) - y * dx;
      base = x >> 8;
      if (base >= -1) {
787
        shift = x & 0xFF;
788 789
        val = highbd_intra_subpel_interp(base, shift, above, -1, bs - 1,
                                         filter_type);
hui su's avatar
hui su committed
790 791
      } else {
        x = c + 1;
792
        y = (r << 8) - x * dy;
hui su's avatar
hui su committed
793 794
        base = y >> 8;
        if (base >= 0) {
795
          shift = y & 0xFF;
796 797
          val = highbd_intra_subpel_interp(base, shift, left, 0, bs - 1,
                                           filter_type);
hui su's avatar
hui su committed
798
        } else {
799
          val = left[0];
hui su's avatar
hui su committed
800 801 802 803 804 805 806 807 808 809 810
        }
      }
      dst[c] = clip_pixel_highbd(val, bd);
    }
    dst += stride;
  }
}

// Directional prediction, zone 3: 180 < angle < 270
static void highbd_dr_prediction_z3(uint16_t *dst, ptrdiff_t stride, int bs,
                                    const uint16_t *above, const uint16_t *left,
811 812
                                    int dx, int dy, int bd,
                                    INTRA_FILTER filter_type) {
hui su's avatar
hui su committed
813 814 815 816 817 818 819 820 821 822
  int r, c, x, y, base, shift, val;

  (void)above;
  (void)dx;
  assert(dx == 1);
  assert(dy < 0);

  for (r = 0; r < bs; ++r) {
    for (c = 0; c < bs; ++c) {
      x = c + 1;
823
      y = (r << 8) - x * dy;
hui su's avatar
hui su committed
824
      base = y >> 8;
825
      shift = y & 0xFF;
826
      if (base < 2 * bs - 1) {
827 828
        val = highbd_intra_subpel_interp(base, shift, left, 0, 2 * bs - 1,
                                         filter_type);
hui su's avatar
hui su committed
829 830
        dst[c] = clip_pixel_highbd(val, bd);
      } else {
831
        dst[c] = left[2 * bs - 1];
hui su's avatar
hui su committed
832 833 834 835 836 837
      }
    }
    dst += stride;
  }
}

clang-format's avatar
clang-format committed
838 839
static INLINE void highbd_v_predictor(uint16_t *dst, ptrdiff_t stride, int bs,
                                      const uint16_t *above,
hui su's avatar
hui su committed
840 841
                                      const uint16_t *left, int bd) {
  int r;
clang-format's avatar
clang-format committed
842 843
  (void)left;
  (void)bd;
hui su's avatar
hui su committed
844 845 846 847 848 849
  for (r = 0; r < bs; r++) {
    memcpy(dst, above, bs * sizeof(uint16_t));
    dst += stride;
  }
}

clang-format's avatar
clang-format committed
850 851
static INLINE void highbd_h_predictor(uint16_t *dst, ptrdiff_t stride, int bs,
                                      const uint16_t *above,
hui su's avatar
hui su committed
852 853
                                      const uint16_t *left, int bd) {
  int r;
clang-format's avatar
clang-format committed
854 855
  (void)above;
  (void)bd;
hui su's avatar
hui su committed
856
  for (r = 0; r < bs; r++) {
Yaowu Xu's avatar
Yaowu Xu committed
857
    aom_memset16(dst, left[r], bs);
hui su's avatar
hui su committed
858 859 860 861 862 863
    dst += stride;
  }
}

static void highbd_dr_predictor(uint16_t *dst, ptrdiff_t stride, int bs,
                                const uint16_t *above, const uint16_t *left,
864
                                int angle, int bd, INTRA_FILTER filter) {
865 866
  const int dx = get_dx(angle);
  const int dy = get_dy(angle);
867
  assert(angle > 0 && angle < 270);
hui su's avatar
hui su committed
868 869

  if (angle > 0 && angle < 90) {
870
    highbd_dr_prediction_z1(dst, stride, bs, above, left, dx, dy, bd, filter);
hui su's avatar
hui su committed
871
  } else if (angle > 90 && angle < 180) {
872
    highbd_dr_prediction_z2(dst, stride, bs, above, left, dx, dy, bd, filter);
hui su's avatar
hui su committed
873
  } else if (angle > 180 && angle < 270) {
874
    highbd_dr_prediction_z3(dst, stride, bs, above, left, dx, dy, bd, filter);
hui su's avatar
hui su committed
875 876 877 878 879 880
  } else if (angle == 90) {
    highbd_v_predictor(dst, stride, bs, above, left, bd);
  } else if (angle == 180) {
    highbd_h_predictor(dst, stride, bs, above, left, bd);
  }
}
881 882
#endif  // CONFIG_AOM_HIGHBITDEPTH
#endif  // CONFIG_EXT_INTRA
hui su's avatar
hui su committed
883

884
#if CONFIG_FILTER_INTRA
hui su's avatar
hui su committed
885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
int av1_filter_intra_taps_4[TX_SIZES][INTRA_MODES][4] = {
  {
      { 735, 881, -537, -54 },
      { 1005, 519, -488, -11 },
      { 383, 990, -343, -6 },
      { 442, 805, -542, 319 },
      { 658, 616, -133, -116 },
      { 875, 442, -141, -151 },
      { 386, 741, -23, -80 },
      { 390, 1027, -446, 51 },
      { 679, 606, -523, 262 },
      { 903, 922, -778, -23 },
  },
  {
      { 648, 803, -444, 16 },
      { 972, 620, -576, 7 },
      { 561, 967, -499, -5 },
      { 585, 762, -468, 144 },
      { 596, 619, -182, -9 },
      { 895, 459, -176, -153 },
      { 557, 722, -126, -129 },
      { 601, 839, -523, 105 },
      { 562, 709, -499, 251 },
      { 803, 872, -695, 43 },
  },
  {
      { 423, 728, -347, 111 },
      { 963, 685, -665, 23 },
      { 281, 1024, -480, 216 },
      { 640, 596, -437, 78 },
      { 429, 669, -259, 99 },
      { 740, 646, -415, 23 },
      { 568, 771, -346, 40 },
      { 404, 833, -486, 209 },
      { 398, 712, -423, 307 },
      { 939, 935, -887, 17 },
  },
  {
      { 477, 737, -393, 150 },
      { 881, 630, -546, 67 },
      { 506, 984, -443, -20 },
      { 114, 459, -270, 528 },
      { 433, 528, 14, 3 },
      { 837, 470, -301, -30 },
      { 181, 777, 89, -107 },
      { -29, 716, -232, 259 },
      { 589, 646, -495, 255 },
      { 740, 884, -728, 77 },
  },
934 935 936 937 938 939 940 941 942 943 944 945 946 947
#if CONFIG_TX64X64
  {
      { 477, 737, -393, 150 },
      { 881, 630, -546, 67 },
      { 506, 984, -443, -20 },
      { 114, 459, -270, 528 },
      { 433, 528, 14, 3 },
      { 837, 470, -301, -30 },
      { 181, 777, 89, -107 },
      { -29, 716, -232, 259 },
      { 589, 646, -495, 255 },
      { 740, 884, -728, 77 },
  },
#endif  // CONFIG_TX64X64
hui su's avatar
hui su committed
948 949
};

950 951 952 953 954 955 956 957 958
static INLINE TX_SIZE get_txsize_from_blocklen(int bs) {
  switch (bs) {
    case 4: return TX_4X4;
    case 8: return TX_8X8;
    case 16: return TX_16X16;
    case 32: return TX_32X32;
#if CONFIG_TX64X64
    case 64: return TX_64X64;
#endif  // CONFIG_TX64X64
Yaowu Xu's avatar
Yaowu Xu committed
959
    default: assert(0); return TX_INVALID;
960 961 962
  }
}

963 964 965 966 967
static void filter_intra_predictors_4tap(uint8_t *dst, ptrdiff_t stride, int bs,
                                         const uint8_t *above,
                                         const uint8_t *left, int mode) {
  int k, r, c;
  int mean, ipred;
968 969 970 971 972 973
#if CONFIG_TX64X64
  int buffer[65][129];
#else
  int buffer[33][65];
#endif  // CONFIG_TX64X64
  const TX_SIZE tx_size = get_txsize_from_blocklen(bs);
hui su's avatar
hui su committed
974 975 976 977
  const int c0 = av1_filter_intra_taps_4[tx_size][mode][0];
  const int c1 = av1_filter_intra_taps_4[tx_size][mode][1];
  const int c2 = av1_filter_intra_taps_4[tx_size][mode][2];
  const int c3 = av1_filter_intra_taps_4[tx_size][mode][3];
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057

  k = 0;
  mean = 0;
  while (k < bs) {
    mean = mean + (int)left[k];
    mean = mean + (int)above[k];
    k++;
  }
  mean = (mean + bs) / (2 * bs);

  for (r = 0; r < bs; ++r) buffer[r + 1][0] = (int)left[r] - mean;

  for (c = 0; c < 2 * bs + 1; ++c) buffer[0][c] = (int)above[c - 1] - mean;

  for (r = 1; r < bs + 1; ++r)
    for (c = 1; c < 2 * bs + 1 - r; ++c) {
      ipred = c0 * buffer[r - 1][c] + c1 * buffer[r][c - 1] +
              c2 * buffer[r - 1][c - 1] + c3 * buffer[r - 1][c + 1];
      buffer[r][c] = ROUND_POWER_OF_TWO_SIGNED(ipred, FILTER_INTRA_PREC_BITS);
    }

  for (r = 0; r < bs; ++r) {
    for (c = 0; c < bs; ++c) {
      ipred = buffer[r + 1][c + 1] + mean;
      dst[c] = clip_pixel(ipred);
    }
    dst += stride;
  }
}

void av1_dc_filter_predictor_c(uint8_t *dst, ptrdiff_t stride, int bs,
                               const uint8_t *above, const uint8_t *left) {
  filter_intra_predictors_4tap(dst, stride, bs, above, left, DC_PRED);
}

void av1_v_filter_predictor_c(uint8_t *dst, ptrdiff_t stride, int bs,
                              const uint8_t *above, const uint8_t *left) {
  filter_intra_predictors_4tap(dst, stride, bs, above, left, V_PRED);
}

void av1_h_filter_predictor_c(uint8_t *dst, ptrdiff_t stride, int bs,
                              const uint8_t *above, const uint8_t *left) {
  filter_intra_predictors_4tap(dst, stride, bs, above, left, H_PRED);
}

void av1_d45_filter_predictor_c(uint8_t *dst, ptrdiff_t stride, int bs,
                                const uint8_t *above, const uint8_t *left) {
  filter_intra_predictors_4tap(dst, stride, bs, above, left, D45_PRED);
}

void av1_d135_filter_predictor_c(uint8_t *dst, ptrdiff_t stride, int bs,
                                 const uint8_t *above, const uint8_t *left) {
  filter_intra_predictors_4tap(dst, stride, bs, above, left, D135_PRED);
}

void av1_d117_filter_predictor_c(uint8_t *dst, ptrdiff_t stride, int bs,
                                 const uint8_t *above, const uint8_t *left) {
  filter_intra_predictors_4tap(dst, stride, bs, above, left, D117_PRED);
}

void av1_d153_filter_predictor_c(uint8_t *dst, ptrdiff_t stride, int bs,
                                 const uint8_t *above, const uint8_t *left) {
  filter_intra_predictors_4tap(dst, stride, bs, above, left, D153_PRED);
}

void av1_d207_filter_predictor_c(uint8_t *dst, ptrdiff_t stride, int bs,
                                 const uint8_t *above, const uint8_t *left) {
  filter_intra_predictors_4tap(dst, stride, bs, above, left, D207_PRED);
}

void av1_d63_filter_predictor_c(uint8_t *dst, ptrdiff_t stride, int bs,
                                const uint8_t *above, const uint8_t *left) {
  filter_intra_predictors_4tap(dst, stride, bs, above, left, D63_PRED);
}

void av1_tm_filter_predictor_c(uint8_t *dst