reconintra.c 61.3 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) {
240 241
  const int width = block_size_wide[bsize] >> tx_size_wide_log2[0];
  const int w = AOMMAX(width >> 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
  if (!right_available) return 0;

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

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

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

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

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

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

280 281
    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];
282

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

Yaowu Xu's avatar
Yaowu Xu committed
289 290 291
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) {
292 293 294
  if (!bottom_available || x != 0) {
    return 0;
  } else {
hui su's avatar
hui su committed
295 296
    const int wl = mi_width_log2_lookup[bsize];
    const int hl = mi_height_log2_lookup[bsize];
297 298
    const int height = block_size_high[bsize] >> tx_size_high_log2[0];
    const int h = AOMMAX(height >> ss_y, 1);
299
    const int step = tx_size_wide_unit[txsz];
300 301 302
    const uint8_t *order = orders[bsize];
    int my_order, bl_order;

303
    // Handle block size 8x4 and 4x4
304
    if (ss_y == 0 && height < 2 && y == 0) return 1;
305

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

308 309
    mi_row = (mi_row & MAX_MIB_MASK) >> hl;
    mi_col = (mi_col & MAX_MIB_MASK) >> wl;
310 311

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

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

316 317
    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];
318

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

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
329
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
330 331 332
typedef void (*intra_high_pred_fn)(uint16_t *dst, ptrdiff_t stride,
                                   const uint16_t *above, const uint16_t *left,
                                   int bd);
333 334
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
335
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
336

Yaowu Xu's avatar
Yaowu Xu committed
337
static void av1_init_intra_predictors_internal(void) {
338 339 340 341 342 343 344
#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
345
#define INIT_NO_4X4(p, type)                  \
Yaowu Xu's avatar
Yaowu Xu committed
346 347 348
  p[TX_8X8] = aom_##type##_predictor_8x8;     \
  p[TX_16X16] = aom_##type##_predictor_16x16; \
  p[TX_32X32] = aom_##type##_predictor_32x32
349
#endif  // CONFIG_TX64X64
Jingning Han's avatar
Jingning Han committed
350

Jingning Han's avatar
Jingning Han committed
351 352 353 354 355 356
#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
357
#define INIT_ALL_SIZES(p, type)           \
Yaowu Xu's avatar
Yaowu Xu committed
358
  p[TX_4X4] = aom_##type##_predictor_4x4; \
359
  INIT_NO_4X4(p, type)
Jingning Han's avatar
Jingning Han committed
360
#endif
361

Jingning Han's avatar
Jingning Han committed
362 363
  INIT_ALL_SIZES(pred[V_PRED], v);
  INIT_ALL_SIZES(pred[H_PRED], h);
364 365 366
  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
367 368 369
  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
370 371 372

#if CONFIG_ALT_INTRA
  INIT_ALL_SIZES(pred[TM_PRED], paeth);
373
  INIT_ALL_SIZES(pred[SMOOTH_PRED], smooth);
Urvang Joshi's avatar
Urvang Joshi committed
374
#else
Jingning Han's avatar
Jingning Han committed
375
  INIT_ALL_SIZES(pred[TM_PRED], tm);
Urvang Joshi's avatar
Urvang Joshi committed
376
#endif  // CONFIG_ALT_INTRA
Jingning Han's avatar
Jingning Han committed
377 378 379 380 381 382

  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
383
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
384 385
  INIT_ALL_SIZES(pred_high[V_PRED], highbd_v);
  INIT_ALL_SIZES(pred_high[H_PRED], highbd_h);
386 387 388
  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
389 390 391
  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
392 393 394

#if CONFIG_ALT_INTRA
  INIT_ALL_SIZES(pred_high[TM_PRED], highbd_paeth);
395
  INIT_ALL_SIZES(pred_high[SMOOTH_PRED], highbd_smooth);
Urvang Joshi's avatar
Urvang Joshi committed
396
#else
Jingning Han's avatar
Jingning Han committed
397
  INIT_ALL_SIZES(pred_high[TM_PRED], highbd_tm);
Urvang Joshi's avatar
Urvang Joshi committed
398
#endif  // CONFIG_ALT_INTRA
Jingning Han's avatar
Jingning Han committed
399 400 401 402 403

  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
404
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
405 406 407 408

#undef intra_pred_allsizes
}

hui su's avatar
hui su committed
409
#if CONFIG_EXT_INTRA
hui su's avatar
hui su committed
410
#if CONFIG_INTRA_INTERP
411 412 413 414 415 416 417 418 419 420 421
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
422
    filter = av1_intra_filter_kernels[filter_type][filter_idx];
423 424 425 426 427

    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
428
        idx = AOMMAX(AOMMIN(idx, ref_end_idx), ref_start_idx);
429 430 431 432 433 434 435 436 437 438
        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
439
#endif  // CONFIG_INTRA_INTERP
440

hui su's avatar
hui su committed
441 442
// 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
443 444 445 446 447
                             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
448
  int r, c, x, base, shift, val;
hui su's avatar
hui su committed
449 450 451 452

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

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

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

hui su's avatar
hui su committed
516 517
  x = dx;
  for (r = 0; r < bs; ++r, dst += stride, x += dx) {
hui su's avatar
hui su committed
518 519 520 521 522 523 524 525 526 527 528 529 530
    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
531
      if (base < 2 * bs - 1) {
hui su's avatar
hui su committed
532 533
        val = above[base] * (256 - shift) + above[base + 1] * shift;
        val = ROUND_POWER_OF_TWO(val, 8);
hui su's avatar
hui su committed
534 535 536 537 538 539 540 541 542 543
        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
544 545 546 547 548
                             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
549
  int r, c, x, y, shift1, shift2, val, base1, base2;
hui su's avatar
hui su committed
550 551 552 553

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

hui su's avatar
hui su committed
554 555 556 557 558 559 560
  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
561
#if CONFIG_INTRA_INTERP
clang-format's avatar
clang-format committed
562 563
        val =
            intra_subpel_interp(base1, shift1, above, -1, bs - 1, filter_type);
hui su's avatar
hui su committed
564 565 566 567
#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
568
      } else {
hui su's avatar
hui su committed
569 570 571
        base2 = y >> 8;
        if (base2 >= 0) {
          shift2 = y & 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(base2, shift2, left, 0, bs - 1, filter_type);
hui su's avatar
hui su committed
575 576 577 578
#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
579
        } else {
580
          val = left[0];
hui su's avatar
hui su committed
581 582 583 584 585 586 587 588 589
        }
      }
      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
590 591 592 593 594
                             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
595
  int r, c, y, base, shift, val;
hui su's avatar
hui su committed
596 597 598

  (void)above;
  (void)dx;
599

hui su's avatar
hui su committed
600
  assert(dx == 1);
hui su's avatar
hui su committed
601
  assert(dy > 0);
hui su's avatar
hui su committed
602

hui su's avatar
hui su committed
603
#if CONFIG_INTRA_INTERP
hui su's avatar
hui su committed
604 605 606
  if (filter_type != INTRA_FILTER_LINEAR) {
    const int pad_size = SUBPEL_TAPS >> 1;
    int len, i;
607 608
    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
609 610 611
    uint8_t flags[SUBPEL_SHIFTS];

    memset(flags, 0, SUBPEL_SHIFTS * sizeof(flags[0]));
clang-format's avatar
clang-format committed
612 613
    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
614 615 616
    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
617 618
    y = dy;
    for (c = 0; c < bs; ++c, y += dy) {
hui su's avatar
hui su committed
619
      base = y >> 8;
hui su's avatar
hui su committed
620 621 622 623 624 625
      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
626
      len = AOMMIN(bs, 2 * bs - 1 - base);
hui su's avatar
hui su committed
627 628

      if (len <= 0) {
Debargha Mukherjee's avatar
Debargha Mukherjee committed
629
        for (r = 0; r < bs; ++r) {
clang-format's avatar
clang-format committed
630
          dst[r * stride + c] = left[2 * bs - 1];
hui su's avatar
hui su committed
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645
        }
        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
646 647
          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
648
                             4 * SUBPEL_SHIFTS, NULL, 16, filter, 16,
hui su's avatar
hui su committed
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
                             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
666
          dst[r * stride + c] = left[2 * bs - 1];
hui su's avatar
hui su committed
667 668 669 670 671
        }
      }
    }
    return;
  }
hui su's avatar
hui su committed
672
#endif  // CONFIG_INTRA_INTERP
hui su's avatar
hui su committed
673

hui su's avatar
hui su committed
674 675
  y = dy;
  for (c = 0; c < bs; ++c, y += dy) {
hui su's avatar
hui su committed
676 677 678 679
    base = y >> 8;
    shift = y & 0xFF;

    for (r = 0; r < bs; ++r, ++base) {
680
      if (base < 2 * bs - 1) {
hui su's avatar
hui su committed
681 682 683
        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
684
      } else {
clang-format's avatar
clang-format committed
685
        for (; r < bs; ++r) dst[r * stride + c] = left[2 * bs - 1];
hui su's avatar
hui su committed
686
        break;
hui su's avatar
hui su committed
687 688 689 690 691
      }
    }
  }
}

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

hui su's avatar
hui su committed
733
  if (angle > 0 && angle < 90) {
hui su's avatar
hui su committed
734 735 736 737 738
    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
739
  } else if (angle > 90 && angle < 180) {
hui su's avatar
hui su committed
740 741 742 743 744
    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
745
  } else if (angle > 180 && angle < 270) {
hui su's avatar
hui su committed
746 747 748 749 750
    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
751
  } else if (angle == 90) {
hui su's avatar
hui su committed
752
    pred[V_PRED][tx_size](dst, stride, above, left);
hui su's avatar
hui su committed
753
  } else if (angle == 180) {
hui su's avatar
hui su committed
754
    pred[H_PRED][tx_size](dst, stride, above, left);
hui su's avatar
hui su committed
755 756 757
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
758
#if CONFIG_AOM_HIGHBITDEPTH
hui su's avatar
hui su committed
759
#if CONFIG_INTRA_INTERP
760 761 762 763 764 765 766 767 768 769 770
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
771
    filter = av1_intra_filter_kernels[filter_type][filter_idx];
772 773 774 775 776

    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
777
        idx = AOMMAX(AOMMIN(idx, ref_end_idx), ref_start_idx);
778 779 780 781 782 783 784 785 786 787
        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
788
#endif  // CONFIG_INTRA_INTERP
789

hui su's avatar
hui su committed
790 791 792
// 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
793 794 795 796
#if CONFIG_INTRA_INTERP
                                    INTRA_FILTER filter_type,
#endif  // CONFIG_INTRA_INTERP
                                    int dx, int dy, int bd) {
797
  int r, c, x, base, shift, val;
hui su's avatar
hui su committed
798 799 800 801

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

804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
  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
819
      if (base < 2 * bs - 1) {
hui su's avatar
hui su committed
820
#if CONFIG_INTRA_INTERP
821 822
        val = highbd_intra_subpel_interp(base, shift, above, 0, 2 * bs - 1,
                                         filter_type);
hui su's avatar
hui su committed
823 824 825 826
#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
827 828 829 830 831 832 833 834 835 836 837
        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
838 839 840 841
#if CONFIG_INTRA_INTERP
                                    INTRA_FILTER filter_type,
#endif  // CONFIG_INTRA_INTERP
                                    int dx, int dy, int bd) {
842
  int r, c, x, y, shift, val, base;
hui su's avatar
hui su committed
843 844 845 846 847 848 849

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

  for (r = 0; r < bs; ++r) {
    for (c = 0; c < bs; ++c) {
      y = r + 1;
850 851 852
      x = (c << 8) - y * dx;
      base = x >> 8;
      if (base >= -1) {
853
        shift = x & 0xFF;
hui su's avatar
hui su committed
854
#if CONFIG_INTRA_INTERP
855 856
        val = highbd_intra_subpel_interp(base, shift, above, -1, bs - 1,
                                         filter_type);
hui su's avatar
hui su committed
857 858 859 860
#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
861 862
      } else {
        x = c + 1;
863
        y = (r << 8) - x * dy;
hui su's avatar
hui su committed
864 865
        base = y >> 8;
        if (base >= 0) {
866
          shift = y & 0xFF;
hui su's avatar
hui su committed
867
#if CONFIG_INTRA_INTERP
868 869
          val = highbd_intra_subpel_interp(base, shift, left, 0, bs - 1,
                                           filter_type);
hui su's avatar
hui su committed
870 871 872 873
#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
874
        } else {
875
          val = left[0];
hui su's avatar
hui su committed
876 877 878 879 880 881 882 883 884 885 886
        }
      }
      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
887 888 889 890
#if CONFIG_INTRA_INTERP
                                    INTRA_FILTER filter_type,
#endif  // CONFIG_INTRA_INTERP
                                    int dx, int dy, int bd) {
891
  int r, c, y, base, shift, val;
hui su's avatar
hui su committed
892 893 894 895

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

898 899 900 901 902 903
  y = dy;
  for (c = 0; c < bs; ++c, y += dy) {
    base = y >> 8;
    shift = y & 0xFF;

    for (r = 0; r < bs; ++r, ++base) {
904
      if (base < 2 * bs - 1) {
hui su's avatar
hui su committed
905
#if CONFIG_INTRA_INTERP
906 907
        val = highbd_intra_subpel_interp(base, shift, left, 0, 2 * bs - 1,
                                         filter_type);
hui su's avatar
hui su committed
908 909 910 911
#else
        val = left[base] * (256 - shift) + left[base + 1] * shift;
        val = ROUND_POWER_OF_TWO(val, 8);
#endif  // CONFIG_INTRA_INTERP
912
        dst[r * stride + c] = clip_pixel_highbd(val, bd);
hui su's avatar
hui su committed
913
      } else {
914 915
        for (; r < bs; ++r) dst[r * stride + c] = left[2 * bs - 1];
        break;
hui su's avatar
hui su committed
916 917 918 919 920
      }
    }
  }
}

clang-format's avatar
clang-format committed
921 922
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
923 924
                                      const uint16_t *left, int bd) {
  int r;
clang-format's avatar
clang-format committed
925 926
  (void)left;
  (void)bd;
hui su's avatar
hui su committed
927 928 929 930 931 932
  for (r = 0; r < bs; r++) {
    memcpy(dst, above, bs * sizeof(uint16_t));
    dst += stride;
  }
}

clang-format's avatar
clang-format committed
933 934
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
935 936
                                      const uint16_t *left, int bd) {
  int r;
clang-format's avatar
clang-format committed
937 938
  (void)above;
  (void)bd;
hui su's avatar
hui su committed
939
  for (r = 0; r < bs; r++) {
Yaowu Xu's avatar
Yaowu Xu committed
940
    aom_memset16(dst, left[r], bs);
hui su's avatar
hui su committed
941 942 943 944 945 946
    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
947 948 949 950
#if CONFIG_INTRA_INTERP
                                INTRA_FILTER filter,
#endif  // CONFIG_INTRA_INTERP
                                int angle, int bd) {
951 952
  const int dx = get_dx(angle);
  const int dy = get_dy(angle);
953
  assert(angle > 0 && angle < 270);
hui su's avatar
hui su committed
954 955

  if (angle > 0 && angle < 90) {
hui su's avatar
hui su committed
956 957 958 959 960
    highbd_dr_prediction_z1(dst, stride, bs, above, left,
#if CONFIG_INTRA_INTERP
                            filter,
#endif  // CONFIG_INTRA_INTERP
                            dx, dy, bd);
hui su's avatar
hui su committed
961
  } else if (angle > 90 && angle < 180) {
hui su's avatar
hui su committed
962 963 964 965 966
    highbd_dr_prediction_z2(dst, stride, bs, above, left,
#if CONFIG_INTRA_INTERP
                            filter,
#endif  // CONFIG_INTRA_INTERP
                            dx, dy, bd);
hui su's avatar
hui su committed
967
  } else if (angle > 180 && angle < 270) {
hui su's avatar
hui su committed
968 969 970 971 972
    highbd_dr_prediction_z3(dst, stride, bs, above, left,
#if CONFIG_INTRA_INTERP
                            filter,
#endif  // CONFIG_INTRA_INTERP
                            dx, dy, bd);
hui su's avatar
hui su committed
973 974 975 976 977 978
  } 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);
  }
}
979 980