reconintra.c 67.6 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
#if CONFIG_CB4X4 || CONFIG_EXT_PARTITION
83
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
#endif  // CONFIG_CB4X4 || CONFIG_EXT_PARTITION
124

125
#if CONFIG_EXT_PARTITION
clang-format's avatar
clang-format committed
126
/* clang-format off */
127
static const uint8_t *const orders[BLOCK_SIZES] = {
Jingning Han's avatar
Jingning Han committed
128 129 130 131
#if CONFIG_CB4X4
  // 2X2,         2X4,            4X2
  orders_8x8,     orders_8x8,     orders_8x8,
#endif
132 133 134 135 136 137 138 139 140 141 142 143
  //                              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
144
};
clang-format's avatar
clang-format committed
145
/* clang-format on */
146
#else
clang-format's avatar
clang-format committed
147
/* clang-format off */
148
static const uint8_t *const orders[BLOCK_SIZES] = {
Jingning Han's avatar
Jingning Han committed
149 150
#if CONFIG_CB4X4
  // 2X2,         2X4,            4X2
151 152 153 154 155 156
  orders_8x8,     orders_8x8,     orders_8x8,
  //                              4X4
                                  orders_8x8,
  // 4X8,         8X4,            8X8
  orders_8x16,    orders_16x8,    orders_16x16,
#else
157 158 159 160
  //                              4X4
                                  orders_16x16,
  // 4X8,         8X4,            8X8
  orders_16x16,   orders_16x16,   orders_16x16,
161
#endif
162 163 164 165 166 167 168
  // 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
169
/* clang-format on */
170 171
#endif  // CONFIG_EXT_PARTITION

172
#if CONFIG_EXT_PARTITION_TYPES
173
static const uint8_t orders_verta_64x64[4] = {
clang-format's avatar
clang-format committed
174
  0, 2, 1, 2,
175
};
176
static const uint8_t orders_verta_32x32[16] = {
clang-format's avatar
clang-format committed
177
  0, 2, 4, 6, 1, 2, 5, 6, 8, 10, 12, 14, 9, 10, 13, 14,
178
};
179
static const uint8_t orders_verta_16x16[64] = {
clang-format's avatar
clang-format committed
180 181 182 183
  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,
184
};
185 186
#if CONFIG_EXT_PARTITION
static const uint8_t orders_verta_8x8[256] = {
clang-format's avatar
clang-format committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
  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,
205
};
clang-format's avatar
clang-format committed
206 207

/* clang-format off */
208 209 210 211 212 213 214 215 216 217 218 219 220 221
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
222
/* clang-format on */
223
#else
clang-format's avatar
clang-format committed
224
/* clang-format off */
225
static const uint8_t *const orders_verta[BLOCK_SIZES] = {
226 227 228 229 230 231 232 233 234 235
  //                                      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
236
};
clang-format's avatar
clang-format committed
237
/* clang-format on */
238
#endif  // CONFIG_EXT_PARTITION
239
#endif  // CONFIG_EXT_PARTITION_TYPES
240

Yaowu Xu's avatar
Yaowu Xu committed
241 242
static int av1_has_right(BLOCK_SIZE bsize, int mi_row, int mi_col,
                         int right_available,
243
#if CONFIG_EXT_PARTITION_TYPES
Yaowu Xu's avatar
Yaowu Xu committed
244
                         PARTITION_TYPE partition,
245
#endif
Yaowu Xu's avatar
Yaowu Xu committed
246
                         TX_SIZE txsz, int y, int x, int ss_x) {
247 248
  const int width = block_size_wide[bsize] >> tx_size_wide_log2[0];
  const int w = AOMMAX(width >> ss_x, 1);
249
  const int step = tx_size_wide_unit[txsz];
hui su's avatar
hui su committed
250

251
#if !CONFIG_CB4X4
252 253 254 255 256 257 258
  // 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;
259
#endif
260

261 262 263
  if (!right_available) return 0;

  // Handle block size 4x8 and 4x4
264
  if (ss_x == 0 && width < 2 && x == 0) return 1;
265

266
  if (y == 0) {
267
    const int wl = mi_width_log2_lookup[bsize];
268 269 270
    const int hl = mi_height_log2_lookup[bsize];
    const uint8_t *order;
    int my_order, tr_order;
271
#if CONFIG_EXT_PARTITION_TYPES
272 273 274
    if (partition == PARTITION_VERT_A)
      order = orders_verta[bsize];
    else
275
#endif  // CONFIG_EXT_PARTITION_TYPES
276
      order = orders[bsize];
277

278
    if (x + step < w) return 1;
279

280 281
    mi_row = (mi_row & MAX_MIB_MASK) >> hl;
    mi_col = (mi_col & MAX_MIB_MASK) >> wl;
282

283 284
    // If top row of coding unit
    if (mi_row == 0) return 1;
285

286 287
    // If rightmost column of coding unit
    if (((mi_col + 1) << wl) >= MAX_MIB_SIZE) return 0;
288

289 290
    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];
291

292 293 294
    return my_order > tr_order;
  } else {
    return x + step < w;
295 296 297
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
298 299 300
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) {
301 302 303
  if (!bottom_available || x != 0) {
    return 0;
  } else {
hui su's avatar
hui su committed
304 305
    const int wl = mi_width_log2_lookup[bsize];
    const int hl = mi_height_log2_lookup[bsize];
306 307
    const int height = block_size_high[bsize] >> tx_size_high_log2[0];
    const int h = AOMMAX(height >> ss_y, 1);
308
    const int step = tx_size_wide_unit[txsz];
309 310 311
    const uint8_t *order = orders[bsize];
    int my_order, bl_order;

312
#if !CONFIG_CB4X4
313
    // Handle block size 8x4 and 4x4
314
    if (ss_y == 0 && height < 2 && y == 0) return 1;
315
#endif
316

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

319 320
    mi_row = (mi_row & MAX_MIB_MASK) >> hl;
    mi_col = (mi_col & MAX_MIB_MASK) >> wl;
321 322

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

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

327 328
    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];
329

330
    return bl_order < my_order;
331 332
  }
}
Jingning Han's avatar
Jingning Han committed
333 334 335 336 337 338 339

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
340
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
341 342 343
typedef void (*intra_high_pred_fn)(uint16_t *dst, ptrdiff_t stride,
                                   const uint16_t *above, const uint16_t *left,
                                   int bd);
344 345
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
346
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
347

Yaowu Xu's avatar
Yaowu Xu committed
348
static void av1_init_intra_predictors_internal(void) {
349 350 351 352 353 354 355
#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
356
#define INIT_NO_4X4(p, type)                  \
Yaowu Xu's avatar
Yaowu Xu committed
357 358 359
  p[TX_8X8] = aom_##type##_predictor_8x8;     \
  p[TX_16X16] = aom_##type##_predictor_16x16; \
  p[TX_32X32] = aom_##type##_predictor_32x32
360
#endif  // CONFIG_TX64X64
Jingning Han's avatar
Jingning Han committed
361

Jingning Han's avatar
Jingning Han committed
362 363 364 365 366 367
#if CONFIG_CB4X4
#define INIT_ALL_SIZES(p, type)           \
  p[TX_2X2] = aom_##type##_predictor_2x2; \
  p[TX_4X4] = aom_##type##_predictor_4x4; \
  INIT_NO_4X4(p, type)
#else
clang-format's avatar
clang-format committed
368
#define INIT_ALL_SIZES(p, type)           \
Yaowu Xu's avatar
Yaowu Xu committed
369
  p[TX_4X4] = aom_##type##_predictor_4x4; \
370
  INIT_NO_4X4(p, type)
Jingning Han's avatar
Jingning Han committed
371
#endif
372

Jingning Han's avatar
Jingning Han committed
373 374
  INIT_ALL_SIZES(pred[V_PRED], v);
  INIT_ALL_SIZES(pred[H_PRED], h);
375 376 377
  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
378 379 380
  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
381 382 383

#if CONFIG_ALT_INTRA
  INIT_ALL_SIZES(pred[TM_PRED], paeth);
384
  INIT_ALL_SIZES(pred[SMOOTH_PRED], smooth);
Urvang Joshi's avatar
Urvang Joshi committed
385
#else
Jingning Han's avatar
Jingning Han committed
386
  INIT_ALL_SIZES(pred[TM_PRED], tm);
Urvang Joshi's avatar
Urvang Joshi committed
387
#endif  // CONFIG_ALT_INTRA
Jingning Han's avatar
Jingning Han committed
388 389 390 391 392 393

  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
394
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
395 396
  INIT_ALL_SIZES(pred_high[V_PRED], highbd_v);
  INIT_ALL_SIZES(pred_high[H_PRED], highbd_h);
397 398 399
  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
400 401 402
  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
403 404 405

#if CONFIG_ALT_INTRA
  INIT_ALL_SIZES(pred_high[TM_PRED], highbd_paeth);
406
  INIT_ALL_SIZES(pred_high[SMOOTH_PRED], highbd_smooth);
Urvang Joshi's avatar
Urvang Joshi committed
407
#else
Jingning Han's avatar
Jingning Han committed
408
  INIT_ALL_SIZES(pred_high[TM_PRED], highbd_tm);
Urvang Joshi's avatar
Urvang Joshi committed
409
#endif  // CONFIG_ALT_INTRA
Jingning Han's avatar
Jingning Han committed
410 411 412 413 414

  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
415
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
416 417 418 419

#undef intra_pred_allsizes
}

hui su's avatar
hui su committed
420
#if CONFIG_EXT_INTRA
hui su's avatar
hui su committed
421
#if CONFIG_INTRA_INTERP
422 423 424 425 426 427 428 429 430 431 432
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
433
    filter = av1_intra_filter_kernels[filter_type][filter_idx];
434 435 436 437 438

    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
439
        idx = AOMMAX(AOMMIN(idx, ref_end_idx), ref_start_idx);
440 441 442 443 444 445 446 447 448 449
        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
450
#endif  // CONFIG_INTRA_INTERP
451

hui su's avatar
hui su committed
452 453
// Directional prediction, zone 1: 0 < angle < 90
static void dr_prediction_z1(uint8_t *dst, ptrdiff_t stride, int bs,
hui su's avatar
hui su committed
454 455 456 457 458
                             const uint8_t *above, const uint8_t *left,
#if CONFIG_INTRA_INTERP
                             INTRA_FILTER filter_type,
#endif  // CONFIG_INTRA_INTERP
                             int dx, int dy) {
hui su's avatar
hui su committed
459
  int r, c, x, base, shift, val;
hui su's avatar
hui su committed
460 461 462 463

  (void)left;
  (void)dy;
  assert(dy == 1);
hui su's avatar
hui su committed
464
  assert(dx > 0);
hui su's avatar
hui su committed
465

hui su's avatar
hui su committed
466
#if CONFIG_INTRA_INTERP
hui su's avatar
hui su committed
467 468 469
  if (filter_type != INTRA_FILTER_LINEAR) {
    const int pad_size = SUBPEL_TAPS >> 1;
    int len;
470 471
    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
472 473 474 475 476 477 478 479
    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;
hui su's avatar
hui su committed
480 481
    x = dx;
    for (r = 0; r < bs; ++r, dst += stride, x += dx) {
hui su's avatar
hui su committed
482
      base = x >> 8;
hui su's avatar
hui su committed
483 484 485 486 487 488
      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
489
      len = AOMMIN(bs, 2 * bs - 1 - base);
hui su's avatar
hui su committed
490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
      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
510 511
          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
512 513
                              filter, 16, NULL, 16, 2 * bs,
                              2 * bs < 16 ? 2 : 1);
hui su's avatar
hui su committed
514 515 516
          flags[shift] = 1;
        }
        memcpy(dst, shift == 0 ? src + pad_size + base : &buf[shift][base],
clang-format's avatar
clang-format committed
517
               len * sizeof(dst[0]));
hui su's avatar
hui su committed
518 519 520 521 522 523 524
      }

      if (len < bs)
        memset(dst + len, above[2 * bs - 1], (bs - len) * sizeof(dst[0]));
    }
    return;
  }
hui su's avatar
hui su committed
525
#endif  // CONFIG_INTRA_INTERP
hui su's avatar
hui su committed
526

hui su's avatar
hui su committed
527 528
  x = dx;
  for (r = 0; r < bs; ++r, dst += stride, x += dx) {
hui su's avatar
hui su committed
529 530 531 532 533 534 535 536 537 538 539 540 541
    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
542
      if (base < 2 * bs - 1) {
hui su's avatar
hui su committed
543 544
        val = above[base] * (256 - shift) + above[base + 1] * shift;
        val = ROUND_POWER_OF_TWO(val, 8);
hui su's avatar
hui su committed
545 546 547 548 549 550 551 552 553 554
        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,
hui su's avatar
hui su committed
555 556 557 558 559
                             const uint8_t *above, const uint8_t *left,
#if CONFIG_INTRA_INTERP
                             INTRA_FILTER filter_type,
#endif  // CONFIG_INTRA_INTERP
                             int dx, int dy) {
Debargha Mukherjee's avatar
Debargha Mukherjee committed
560
  int r, c, x, y, shift1, shift2, val, base1, base2;
hui su's avatar
hui su committed
561 562 563 564

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

hui su's avatar
hui su committed
565 566 567 568 569 570 571
  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;
hui su's avatar
hui su committed
572
#if CONFIG_INTRA_INTERP
clang-format's avatar
clang-format committed
573 574
        val =
            intra_subpel_interp(base1, shift1, above, -1, bs - 1, filter_type);
hui su's avatar
hui su committed
575 576 577 578
#else
        val = above[base1] * (256 - shift1) + above[base1 + 1] * shift1;
        val = ROUND_POWER_OF_TWO(val, 8);
#endif  // CONFIG_INTRA_INTERP
hui su's avatar
hui su committed
579
      } else {
hui su's avatar
hui su committed
580 581 582
        base2 = y >> 8;
        if (base2 >= 0) {
          shift2 = y & 0xFF;
hui su's avatar
hui su committed
583
#if CONFIG_INTRA_INTERP
clang-format's avatar
clang-format committed
584 585
          val =
              intra_subpel_interp(base2, shift2, left, 0, bs - 1, filter_type);
hui su's avatar
hui su committed
586 587 588 589
#else
          val = left[base2] * (256 - shift2) + left[base2 + 1] * shift2;
          val = ROUND_POWER_OF_TWO(val, 8);
#endif  // CONFIG_INTRA_INTERP
hui su's avatar
hui su committed
590
        } else {
591
          val = left[0];
hui su's avatar
hui su committed
592 593 594 595 596 597 598 599 600
        }
      }
      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,
hui su's avatar
hui su committed
601 602 603 604 605
                             const uint8_t *above, const uint8_t *left,
#if CONFIG_INTRA_INTERP
                             INTRA_FILTER filter_type,
#endif  // CONFIG_INTRA_INTERP
                             int dx, int dy) {
hui su's avatar
hui su committed
606
  int r, c, y, base, shift, val;
hui su's avatar
hui su committed
607 608 609

  (void)above;
  (void)dx;
610

hui su's avatar
hui su committed
611
  assert(dx == 1);
hui su's avatar
hui su committed
612
  assert(dy > 0);
hui su's avatar
hui su committed
613

hui su's avatar
hui su committed
614
#if CONFIG_INTRA_INTERP
hui su's avatar
hui su committed
615 616 617
  if (filter_type != INTRA_FILTER_LINEAR) {
    const int pad_size = SUBPEL_TAPS >> 1;
    int len, i;
618 619
    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
620 621 622
    uint8_t flags[SUBPEL_SHIFTS];

    memset(flags, 0, SUBPEL_SHIFTS * sizeof(flags[0]));
clang-format's avatar
clang-format committed
623 624
    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
625 626 627
    for (i = 0; i < pad_size; ++i)
      src[4 * (i + 2 * bs + pad_size)] = left[2 * bs - 1];
    flags[0] = 1;
hui su's avatar
hui su committed
628 629
    y = dy;
    for (c = 0; c < bs; ++c, y += dy) {
hui su's avatar
hui su committed
630
      base = y >> 8;
hui su's avatar
hui su committed
631 632 633 634 635 636
      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
637
      len = AOMMIN(bs, 2 * bs - 1 - base);
hui su's avatar
hui su committed
638 639

      if (len <= 0) {
Debargha Mukherjee's avatar
Debargha Mukherjee committed
640
        for (r = 0; r < bs; ++r) {
clang-format's avatar
clang-format committed
641
          dst[r * stride + c] = left[2 * bs - 1];
hui su's avatar
hui su committed
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
        }
        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
657 658
          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
659
                             4 * SUBPEL_SHIFTS, NULL, 16, filter, 16,
hui su's avatar
hui su committed
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
                             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
677
          dst[r * stride + c] = left[2 * bs - 1];
hui su's avatar
hui su committed
678 679 680 681 682
        }
      }
    }
    return;
  }
hui su's avatar
hui su committed
683
#endif  // CONFIG_INTRA_INTERP
hui su's avatar
hui su committed
684

hui su's avatar
hui su committed
685 686
  y = dy;
  for (c = 0; c < bs; ++c, y += dy) {
hui su's avatar
hui su committed
687 688 689 690
    base = y >> 8;
    shift = y & 0xFF;

    for (r = 0; r < bs; ++r, ++base) {
691
      if (base < 2 * bs - 1) {
hui su's avatar
hui su committed
692 693 694
        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
695
      } else {
clang-format's avatar
clang-format committed
696
        for (; r < bs; ++r) dst[r * stride + c] = left[2 * bs - 1];
hui su's avatar
hui su committed
697
        break;
hui su's avatar
hui su committed
698 699 700 701 702
      }
    }
  }
}

703 704 705 706
// 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
707
static INLINE int get_dx(int angle) {
708
  if (angle > 0 && angle < 90) {
hui su's avatar
hui su committed
709
    return dr_intra_derivative[angle];
710 711 712 713 714 715 716 717 718 719 720 721
  } 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
722
static INLINE int get_dy(int angle) {
723
  if (angle > 90 && angle < 180) {
clang-format's avatar
clang-format committed
724 725
    return dr_intra_derivative[angle - 90];
  } else if (angle > 180 && angle < 270) {
hui su's avatar
hui su committed
726
    return dr_intra_derivative[270 - angle];
clang-format's avatar
clang-format committed
727
  } else {
728 729 730 731 732
    // 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
733
static void dr_predictor(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size,
hui su's avatar
hui su committed
734 735 736 737 738
                         const uint8_t *above, const uint8_t *left,
#if CONFIG_INTRA_INTERP
                         INTRA_FILTER filter_type,
#endif  // CONFIG_INTRA_INTERP
                         int angle) {
739 740
  const int dx = get_dx(angle);
  const int dy = get_dy(angle);
741
  const int bs = tx_size_wide[tx_size];
742 743
  assert(angle > 0 && angle < 270);

hui su's avatar
hui su committed
744
  if (angle > 0 && angle < 90) {
hui su's avatar
hui su committed
745 746 747 748 749
    dr_prediction_z1(dst, stride, bs, above, left,
#if CONFIG_INTRA_INTERP
                     filter_type,
#endif  // CONFIG_INTRA_INTERP
                     dx, dy);
hui su's avatar
hui su committed
750
  } else if (angle > 90 && angle < 180) {
hui su's avatar
hui su committed
751 752 753 754 755
    dr_prediction_z2(dst, stride, bs, above, left,
#if CONFIG_INTRA_INTERP
                     filter_type,
#endif  // CONFIG_INTRA_INTERP
                     dx, dy);
hui su's avatar
hui su committed
756
  } else if (angle > 180 && angle < 270) {
hui su's avatar
hui su committed
757 758 759 760 761
    dr_prediction_z3(dst, stride, bs, above, left,
#if CONFIG_INTRA_INTERP
                     filter_type,
#endif  // CONFIG_INTRA_INTERP
                     dx, dy);
hui su's avatar
hui su committed
762
  } else if (angle == 90) {
hui su's avatar
hui su committed
763
    pred[V_PRED][tx_size](dst, stride, above, left);
hui su's avatar
hui su committed
764
  } else if (angle == 180) {
hui su's avatar
hui su committed
765
    pred[H_PRED][tx_size](dst, stride, above, left);
hui su's avatar
hui su committed
766 767 768
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
769
#if CONFIG_AOM_HIGHBITDEPTH
hui su's avatar
hui su committed
770
#if CONFIG_INTRA_INTERP
771 772 773 774 775 776 777 778 779 780 781
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
782
    filter = av1_intra_filter_kernels[filter_type][filter_idx];
783 784 785 786 787

    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
788
        idx = AOMMAX(AOMMIN(idx, ref_end_idx), ref_start_idx);
789 790 791 792 793 794 795 796 797 798
        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
799
#endif  // CONFIG_INTRA_INTERP
800

hui su's avatar
hui su committed
801 802 803
// 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,
hui su's avatar
hui su committed
804 805 806 807
#if CONFIG_INTRA_INTERP
                                    INTRA_FILTER filter_type,
#endif  // CONFIG_INTRA_INTERP
                                    int dx, int dy, int bd) {
808
  int r, c, x, base, shift, val;
hui su's avatar
hui su committed
809 810 811 812

  (void)left;
  (void)dy;
  assert(dy == 1);
813
  assert(dx > 0);
hui su's avatar
hui su committed
814

815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
  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) {
        aom_memset16(dst, above[2 * bs - 1], bs);
        dst += stride;
      }
      return;
    }

    for (c = 0; c < bs; ++c, ++base) {
hui su's avatar
hui su committed
830
      if (base < 2 * bs - 1) {
hui su's avatar
hui su committed
831
#if CONFIG_INTRA_INTERP
832 833
        val = highbd_intra_subpel_interp(base, shift, above, 0, 2 * bs - 1,
                                         filter_type);
hui su's avatar
hui su committed
834 835 836 837
#else
        val = above[base] * (256 - shift) + above[base + 1] * shift;
        val = ROUND_POWER_OF_TWO(val, 8);
#endif  // CONFIG_INTRA_INTERP
hui su's avatar
hui su committed
838 839 840 841 842 843 844 845 846 847 848
        dst[c] = clip_pixel_highbd(val, bd);
      } else {
        dst[c] = above[2 * bs - 1];
      }
    }
  }
}

// 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,
hui su's avatar
hui su committed
849 850 851 852
#if CONFIG_INTRA_INTERP
                                    INTRA_FILTER filter_type,
#endif  // CONFIG_INTRA_INTERP
                                    int dx, int dy, int bd) {
853
  int r, c, x, y, shift, val, base;
hui su's avatar
hui su committed
854 855 856 857 858 859 860

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

  for (r = 0; r < bs; ++r) {
    for (c = 0; c < bs; ++c) {
      y = r + 1;
861 862 863
      x = (c << 8) - y * dx;
      base = x >> 8;
      if (base >= -1) {
864
        shift = x & 0xFF;
hui su's avatar
hui su committed
865
#if CONFIG_INTRA_INTERP
866 867
        val = highbd_intra_subpel_interp(base, shift, above, -1, bs - 1,
                                         filter_type);
hui su's avatar
hui su committed
868 869 870 871
#else
        val = above[base] * (256 - shift) + above[base + 1] * shift;
        val = ROUND_POWER_OF_TWO(val, 8);
#endif  // CONFIG_INTRA_INTERP
hui su's avatar
hui su committed
872 873
      } else {
        x = c + 1;
874
        y = (r << 8) - x * dy;
hui su's avatar
hui su committed
875 876
        base = y >> 8;
        if (base >= 0) {
877
          shift = y & 0xFF;
hui su's avatar
hui su committed
878
#if CONFIG_INTRA_INTERP
879 880
          val = highbd_intra_subpel_interp(base, shift, left, 0, bs - 1,
                                           filter_type);
hui su's avatar
hui su committed
881 882 883 884
#else
          val = left[base] * (256 - shift) + left[base + 1] * shift;
          val = ROUND_POWER_OF_TWO(val, 8);
#endif  // CONFIG_INTRA_INTERP
hui su's avatar
hui su committed
885
        } else {
886
          val = left[0];
hui su's avatar
hui su committed
887 888 889 890 891 892 893 894 895 896 897
        }
      }
      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,
hui su's avatar
hui su committed
898 899 900 901
#if CONFIG_INTRA_INTERP
                                    INTRA_FILTER filter_type,
#endif  // CONFIG_INTRA_INTERP
                                    int dx, int dy, int bd) {
902
  int r, c, y, base, shift, val;
hui su's avatar
hui su committed
903 904 905 906

  (void)above;
  (void)dx;
  assert(dx == 1);
907
  assert(dy > 0);
hui su's avatar
hui su committed
908

909 910 911 912 913 914
  y = dy;
  for (c = 0; c < bs; ++c, y += dy) {
    base = y >> 8;
    shift = y & 0xFF;

    for (r = 0; r < bs; ++r, ++base) {
915
      if (base < 2 * bs - 1) {
hui su's avatar
hui su committed
916
#if CONFIG_INTRA_INTERP
917 918
        val = highbd_intra_subpel_interp(base, shift, left, 0, 2 * bs - 1,
                                         filter_type);
hui su's avatar
hui su committed
919 920 921 922
#else
        val = left[base] * (256 - shift) + left[base + 1] * shift;
        val = ROUND_POWER_OF_TWO(val, 8);
#endif  // CONFIG_INTRA_INTERP
923
        dst[r * stride + c] = clip_pixel_highbd(val, bd);
hui su's avatar
hui su committed
924
      } else {
925 926
        for (; r < bs; ++r) dst[r * stride + c] = left[2 * bs - 1];
        break;
hui su's avatar
hui su committed
927 928 929 930 931
      }
    }
  }
}

clang-format's avatar
clang-format committed
932 933
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
934 935
                                      const uint16_t *left, int bd) {
  int r;
clang-format's avatar
clang-format committed
936 937
  (void)left;
  (void)bd;
hui su's avatar
hui su committed
938 939 940 941 942 943
  for (r = 0; r < bs; r++) {
    memcpy(dst, above, bs * sizeof(uint16_t));
    dst += stride;
  }
}

clang-format's avatar
clang-format committed
944 945
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
946 947
                                      const uint16_t *left, int bd) {
  int r;
clang-format's avatar
clang-format committed
948 949
  (void)above;
  (void)bd;
hui su's avatar
hui su committed
950
  for (r = 0; r < bs; r++) {
Yaowu Xu's avatar
Yaowu Xu committed
951
    aom_memset16(dst, left[r], bs);
hui su's avatar
hui su committed
952 953 954 955 956 957
    dst += stride;
  }
}

static void highbd_dr_predictor(uint16_t *dst, ptrdiff_t stride, int bs,
                                const uint16_t *above, const uint16_t *left,
hui su's avatar
hui su committed
958 959 960 961
#if CONFIG_INTRA_INTERP
                                INTRA_FILTER filter,
#endif  // CONFIG_INTRA_INTERP
                                int angle, int bd) {
962 963
  const int dx = get_dx(angle);
  const int dy = get_dy(angle);