Files
vpx/vp10/common/reconintra.c
Geza Lore 511da8cbe5 Rename MI_BLOCK_SIZE and MI_MASK macros.
Rename MI_BLOCK_SIZE.* -> MAX_MIB_SIZE.* (MIB is for MI Block).
Rename MI_MASK.* -> MAX_MIB_MASK.*

There are no functional changes.

This is in preparation for coding the superblock size at the frame
level, which will require some of these constants to become variables.
The new names better reflect future semantics, and hence make the code
clearer.

Change-Id: Iee08d97554cf4cc16a5dc166a3ffd1ab91529992
2016-03-31 09:57:41 +01:00

1590 lines
54 KiB
C

/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include "./vpx_config.h"
#include "./vpx_dsp_rtcd.h"
#if CONFIG_VP9_HIGHBITDEPTH
#include "vpx_dsp/vpx_dsp_common.h"
#endif // CONFIG_VP9_HIGHBITDEPTH
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h"
#include "vpx_ports/vpx_once.h"
#include "vp10/common/reconintra.h"
#include "vp10/common/onyxc_int.h"
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
NEED_LEFT | NEED_ABOVE | NEED_ABOVELEFT, // TM
};
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] = {
0, 1,
2, 3,
};
static const uint8_t orders_64x32[8] = {
0, 2,
1, 3,
4, 6,
5, 7,
};
static const uint8_t orders_32x64[8] = {
0, 1, 2, 3,
4, 5, 6, 7,
};
static const uint8_t orders_32x32[16] = {
0, 1, 4, 5,
2, 3, 6, 7,
8, 9, 12, 13,
10, 11, 14, 15,
};
static const uint8_t orders_32x16[32] = {
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,
};
static const uint8_t orders_16x32[32] = {
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,
};
static const uint8_t orders_16x16[64] = {
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,
};
#if CONFIG_EXT_PARTITION
static const uint8_t orders_16x8[128] = {
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,
};
static const uint8_t orders_8x16[128] = {
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,
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] = {
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,
};
static const uint8_t *const orders[BLOCK_SIZES] = {
// 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
};
#else
static const uint8_t *const orders[BLOCK_SIZES] = {
// 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
};
#endif // CONFIG_EXT_PARTITION
#if CONFIG_EXT_PARTITION_TYPES
static const uint8_t orders_verta_64x64[4] = {
0, 2,
1, 2,
};
static const uint8_t orders_verta_32x32[16] = {
0, 2, 4, 6,
1, 2, 5, 6,
8, 10, 12, 14,
9, 10, 13, 14,
};
static const uint8_t orders_verta_16x16[64] = {
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,
};
#if CONFIG_EXT_PARTITION
static const uint8_t orders_verta_8x8[256] = {
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,
};
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
};
#else
static const uint8_t *const orders_verta[BLOCK_SIZES] = {
// 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
};
#endif // CONFIG_EXT_PARTITION
#endif // CONFIG_EXT_PARTITION_TYPES
static int vp10_has_right(BLOCK_SIZE bsize, int mi_row, int mi_col,
int right_available,
#if CONFIG_EXT_PARTITION_TYPES
PARTITION_TYPE partition,
#endif
TX_SIZE txsz, int y, int x, int ss_x) {
const int wl = mi_width_log2_lookup[bsize];
const int w = VPXMAX(num_4x4_blocks_wide_lookup[bsize] >> ss_x, 1);
const int step = 1 << txsz;
if (!right_available) {
return 0;
} else {
// Handle block size 4x8 and 4x4
if (ss_x == 0 && num_4x4_blocks_wide_lookup[bsize] < 2 && x == 0)
return 1;
if (y == 0) {
const int hl = mi_height_log2_lookup[bsize];
const uint8_t *order;
int my_order, tr_order;
#if CONFIG_EXT_PARTITION_TYPES
if (partition == PARTITION_VERT_A)
order = orders_verta[bsize];
else
#endif // CONFIG_EXT_PARTITION_TYPES
order = orders[bsize];
if (x + step < w)
return 1;
mi_row = (mi_row & MAX_MIB_MASK) >> hl;
mi_col = (mi_col & MAX_MIB_MASK) >> wl;
// If top row of coding unit
if (mi_row == 0)
return 1;
// If rightmost column of coding unit
if (((mi_col + 1) << wl) >= MAX_MIB_SIZE)
return 0;
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];
return my_order > tr_order;
} else {
return x + step < w;
}
}
}
static int vp10_has_bottom(BLOCK_SIZE bsize, int mi_row, int mi_col,
int bottom_available, TX_SIZE txsz,
int y, int x, int ss_y) {
if (!bottom_available || x != 0) {
return 0;
} else {
const int wl = mi_width_log2_lookup[bsize];
const int hl = mi_height_log2_lookup[bsize];
const int h = 1 << (hl + 1 - ss_y);
const int step = 1 << txsz;
const uint8_t *order = orders[bsize];
int my_order, bl_order;
// Handle block size 8x4 and 4x4
if (ss_y == 0 && num_4x4_blocks_high_lookup[bsize] < 2 && y == 0)
return 1;
if (y + step < h)
return 1;
mi_row = (mi_row & MAX_MIB_MASK) >> hl;
mi_col = (mi_col & MAX_MIB_MASK) >> wl;
if (mi_col == 0)
return (mi_row << (hl + !ss_y)) + y + step < (MAX_MIB_SIZE << !ss_y);
if (((mi_row + 1) << hl) >= MAX_MIB_SIZE)
return 0;
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];
return bl_order < my_order;
}
}
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];
#if CONFIG_VP9_HIGHBITDEPTH
typedef void (*intra_high_pred_fn)(uint16_t *dst, ptrdiff_t stride,
const uint16_t *above, const uint16_t *left,
int bd);
static intra_high_pred_fn pred_high[INTRA_MODES][4];
static intra_high_pred_fn dc_pred_high[2][2][4];
#endif // CONFIG_VP9_HIGHBITDEPTH
static void vp10_init_intra_predictors_internal(void) {
#define INIT_NO_4X4(p, type) \
p[TX_8X8] = vpx_##type##_predictor_8x8; \
p[TX_16X16] = vpx_##type##_predictor_16x16; \
p[TX_32X32] = vpx_##type##_predictor_32x32
#define INIT_ALL_SIZES(p, type) \
p[TX_4X4] = vpx_##type##_predictor_4x4; \
INIT_NO_4X4(p, type)
INIT_ALL_SIZES(pred[V_PRED], v);
INIT_ALL_SIZES(pred[H_PRED], h);
INIT_ALL_SIZES(pred[D207_PRED], d207e);
INIT_ALL_SIZES(pred[D45_PRED], d45e);
INIT_ALL_SIZES(pred[D63_PRED], d63e);
INIT_ALL_SIZES(pred[D117_PRED], d117);
INIT_ALL_SIZES(pred[D135_PRED], d135);
INIT_ALL_SIZES(pred[D153_PRED], d153);
INIT_ALL_SIZES(pred[TM_PRED], tm);
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);
#if CONFIG_VP9_HIGHBITDEPTH
INIT_ALL_SIZES(pred_high[V_PRED], highbd_v);
INIT_ALL_SIZES(pred_high[H_PRED], highbd_h);
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);
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);
INIT_ALL_SIZES(pred_high[TM_PRED], highbd_tm);
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);
#endif // CONFIG_VP9_HIGHBITDEPTH
#undef intra_pred_allsizes
}
#if CONFIG_EXT_INTRA
#define PI 3.14159265
#define FILTER_INTRA_PREC_BITS 10
#define FILTER_INTRA_ROUND_VAL 511
static const uint8_t ext_intra_extend_modes[FILTER_INTRA_MODES] = {
NEED_LEFT | NEED_ABOVE, // FILTER_DC
NEED_LEFT | NEED_ABOVE, // FILTER_V
NEED_LEFT | NEED_ABOVE, // FILTER_H
NEED_LEFT | NEED_ABOVE, // FILTER_D45
NEED_LEFT | NEED_ABOVE, // FILTER_D135
NEED_LEFT | NEED_ABOVE, // FILTER_D117
NEED_LEFT | NEED_ABOVE, // FILTER_D153
NEED_LEFT | NEED_ABOVE, // FILTER_D207
NEED_LEFT | NEED_ABOVE, // FILTER_D63
NEED_LEFT | NEED_ABOVE, // FILTER_TM
};
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);
filter = vp10_intra_filter_kernels[filter_type][filter_idx];
if (filter_idx < (1 << SUBPEL_BITS)) {
val = 0;
for (k = 0; k < SUBPEL_TAPS; ++k) {
idx = base + 1 - (SUBPEL_TAPS / 2) + k;
idx = VPXMAX(VPXMIN(idx, ref_end_idx), ref_start_idx);
val += ref[idx] * filter[k];
}
val = ROUND_POWER_OF_TWO(val, FILTER_BITS);
} else {
val = ref[base + 1];
}
}
return val;
}
// Directional prediction, zone 1: 0 < angle < 90
static void dr_prediction_z1(uint8_t *dst, ptrdiff_t stride, int bs,
const uint8_t *above, const uint8_t *left,
int dx, int dy, INTRA_FILTER filter_type) {
int r, c, x, base, shift, val;
(void)left;
(void)dy;
assert(dy == 1);
assert(dx < 0);
if (filter_type != INTRA_FILTER_LINEAR) {
const int pad_size = SUBPEL_TAPS >> 1;
int len;
DECLARE_ALIGNED(16, uint8_t, buf[SUBPEL_SHIFTS][MAX_SB_SIZE]);
DECLARE_ALIGNED(16, uint8_t, src[MAX_SB_SIZE + SUBPEL_TAPS]);
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) {
base = x >> 8;
shift = x & 0xFF;
shift = ROUND_POWER_OF_TWO(shift, 8 - SUBPEL_BITS);
if (shift == SUBPEL_SHIFTS) {
base += 1;
shift = 0;
}
len = VPXMIN(bs, 2 * bs - 1 - base);
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]) {
const int16_t *filter = vp10_intra_filter_kernels[filter_type][shift];
vpx_convolve8_horiz(src + pad_size, 2 * bs, buf[shift], 2 * bs,
filter, 16,
NULL, 16, 2 * bs, 2 * bs < 16 ? 2 : 1);
flags[shift] = 1;
}
memcpy(dst, shift == 0 ? src + pad_size + base : &buf[shift][base],
len * sizeof(dst[0]));
}
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) {
if (base < 2 * bs - 1) {
val = above[base] * (256 - shift) + above[base + 1] * shift;
val = ROUND_POWER_OF_TWO(val, 8);
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,
const uint8_t *above, const uint8_t *left,
int dx, int dy, INTRA_FILTER filter_type) {
int r, c, x, y, shift1, shift2, val, base1, base2;
assert(dx > 0);
assert(dy > 0);
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;
val = intra_subpel_interp(base1, shift1, above, -1, bs - 1,
filter_type);
} else {
base2 = y >> 8;
if (base2 >= 0) {
shift2 = y & 0xFF;
val = intra_subpel_interp(base2, shift2, left, 0, bs - 1,
filter_type);
} else {
val = left[0];
}
}
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,
const uint8_t *above, const uint8_t *left,
int dx, int dy, INTRA_FILTER filter_type) {
int r, c, y, base, shift, val;
(void)above;
(void)dx;
assert(dx == 1);
assert(dy < 0);
if (filter_type != INTRA_FILTER_LINEAR) {
const int pad_size = SUBPEL_TAPS >> 1;
int len, i;
DECLARE_ALIGNED(16, uint8_t, buf[MAX_SB_SIZE][4 * SUBPEL_SHIFTS]);
DECLARE_ALIGNED(16, uint8_t, src[(MAX_SB_SIZE + SUBPEL_TAPS) * 4]);
uint8_t flags[SUBPEL_SHIFTS];
memset(flags, 0, SUBPEL_SHIFTS * sizeof(flags[0]));
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];
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) {
base = y >> 8;
shift = y & 0xFF;
shift = ROUND_POWER_OF_TWO(shift, 8 - SUBPEL_BITS);
if (shift == SUBPEL_SHIFTS) {
base += 1;
shift = 0;
}
len = VPXMIN(bs, 2 * bs - 1 - base);
if (len <= 0) {
for (r = 0; r < bs; ++r) {
dst[r * stride + c] = left[ 2 * bs - 1];
}
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]) {
const int16_t *filter = vp10_intra_filter_kernels[filter_type][shift];
vpx_convolve8_vert(src + 4 * pad_size, 4,
buf[0] + 4 * shift, 4 * SUBPEL_SHIFTS, NULL, 16,
filter, 16,
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) {
dst[r * stride + c] = left[ 2 * bs - 1];
}
}
}
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) {
if (base < 2 * bs - 1) {
val = left[base] * (256 - shift) + left[base + 1] * shift;
val = ROUND_POWER_OF_TWO(val, 8);
dst[r * stride + c] = clip_pixel(val);
} else {
for (; r < bs; ++r)
dst[r * stride + c] = left[2 * bs - 1];
break;
}
}
}
}
static void dr_predictor(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size,
const uint8_t *above, const uint8_t *left, int angle,
INTRA_FILTER filter_type) {
double t = 0;
int dx, dy;
int bs = 4 << tx_size;
if (angle != 90 && angle != 180)
t = tan(angle * PI / 180.0);
if (angle > 0 && angle < 90) {
dx = -((int)(256 / t));
dy = 1;
dr_prediction_z1(dst, stride, bs, above, left, dx, dy, filter_type);
} else if (angle > 90 && angle < 180) {
t = -t;
dx = (int)(256 / t);
dy = (int)(256 * t);
dr_prediction_z2(dst, stride, bs, above, left, dx, dy, filter_type);
} else if (angle > 180 && angle < 270) {
dx = 1;
dy = -((int)(256 * t));
dr_prediction_z3(dst, stride, bs, above, left, dx, dy, filter_type);
} else if (angle == 90) {
pred[V_PRED][tx_size](dst, stride, above, left);
} else if (angle == 180) {
pred[H_PRED][tx_size](dst, stride, above, left);
}
}
static int 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},
},
};
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 pred[33][65];
int mean, ipred;
const TX_SIZE tx_size = (bs == 32) ? TX_32X32 :
((bs == 16) ? TX_16X16 : ((bs == 8) ? TX_8X8 : (TX_4X4)));
const int c0 = filter_intra_taps_4[tx_size][mode][0];
const int c1 = filter_intra_taps_4[tx_size][mode][1];
const int c2 = filter_intra_taps_4[tx_size][mode][2];
const int c3 = filter_intra_taps_4[tx_size][mode][3];
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)
pred[r + 1][0] = (int)left[r] - mean;
for (c = 0; c < 2 * bs + 1; ++c)
pred[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 * pred[r - 1][c] + c1 * pred[r][c - 1] +
c2 * pred[r - 1][c - 1] + c3 * pred[r - 1][c + 1];
pred[r][c] = ipred < 0 ?
-((-ipred + FILTER_INTRA_ROUND_VAL) >> FILTER_INTRA_PREC_BITS) :
((ipred + FILTER_INTRA_ROUND_VAL) >> FILTER_INTRA_PREC_BITS);
}
for (r = 0; r < bs; ++r) {
for (c = 0; c < bs; ++c) {
ipred = pred[r + 1][c + 1] + mean;
dst[c] = clip_pixel(ipred);
}
dst += stride;
}
}
static void dc_filter_predictor(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);
}
static void v_filter_predictor(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);
}
static void h_filter_predictor(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);
}
static void d45_filter_predictor(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);
}
static void d135_filter_predictor(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);
}
static void d117_filter_predictor(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);
}
static void d153_filter_predictor(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);
}
static void d207_filter_predictor(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);
}
static void d63_filter_predictor(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);
}
static void tm_filter_predictor(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, TM_PRED);
}
static void (*filter_intra_predictors[EXT_INTRA_MODES])(uint8_t *dst,
ptrdiff_t stride, int bs, const uint8_t *above, const uint8_t *left) = {
dc_filter_predictor, v_filter_predictor, h_filter_predictor,
d45_filter_predictor, d135_filter_predictor, d117_filter_predictor,
d153_filter_predictor, d207_filter_predictor, d63_filter_predictor,
tm_filter_predictor,
};
#if CONFIG_VP9_HIGHBITDEPTH
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);
filter = vp10_intra_filter_kernels[filter_type][filter_idx];
if (filter_idx < (1 << SUBPEL_BITS)) {
val = 0;
for (k = 0; k < SUBPEL_TAPS; ++k) {
idx = base + 1 - (SUBPEL_TAPS / 2) + k;
idx = VPXMAX(VPXMIN(idx, ref_end_idx), ref_start_idx);
val += ref[idx] * filter[k];
}
val = ROUND_POWER_OF_TWO(val, FILTER_BITS);
} else {
val = ref[base + 1];
}
}
return val;
}
// 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,
int dx, int dy, int bd,
INTRA_FILTER filter_type) {
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) {
x = (c << 8) - y * dx;
base = x >> 8;
shift = x - (base << 8);
if (base < 2 * bs - 1) {
val = highbd_intra_subpel_interp(base, shift, above, 0, 2 * bs - 1,
filter_type);
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,
int dx, int dy, int bd,
INTRA_FILTER filter_type) {
int r, c, x, y, shift, val, base;
assert(dx > 0);
assert(dy > 0);
for (r = 0; r < bs; ++r) {
for (c = 0; c < bs; ++c) {
y = r + 1;
x = (c << 8) - y * dx;
base = x >> 8;
if (base >= -1) {
shift = x - (base << 8);
val = highbd_intra_subpel_interp(base, shift, above, -1, bs - 1,
filter_type);
} else {
x = c + 1;
y = (r << 8) - x * dy;
base = y >> 8;
if (base >= 0) {
shift = y - (base << 8);
val = highbd_intra_subpel_interp(base, shift, left, 0, bs - 1,
filter_type);
} else {
val = left[0];
}
}
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,
int dx, int dy, int bd,
INTRA_FILTER filter_type) {
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;
y = (r << 8) - x * dy;
base = y >> 8;
shift = y - (base << 8);
if (base < 2 * bs - 1) {
val = highbd_intra_subpel_interp(base, shift, left, 0, 2 * bs - 1,
filter_type);
dst[c] = clip_pixel_highbd(val, bd);
} else {
dst[c] = left[2 * bs - 1];
}
}
dst += stride;
}
}
static INLINE void highbd_v_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
int r;
(void) left;
(void) bd;
for (r = 0; r < bs; r++) {
memcpy(dst, above, bs * sizeof(uint16_t));
dst += stride;
}
}
static INLINE void highbd_h_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
int r;
(void) above;
(void) bd;
for (r = 0; r < bs; r++) {
vpx_memset16(dst, left[r], bs);
dst += stride;
}
}
static void highbd_dr_predictor(uint16_t *dst, ptrdiff_t stride, int bs,
const uint16_t *above, const uint16_t *left,
int angle, int bd, INTRA_FILTER filter) {
double t = 0;
int dx, dy;
if (angle != 90 && angle != 180)
t = tan(angle * PI / 180.0);
if (angle > 0 && angle < 90) {
dx = -((int)(256 / t));
dy = 1;
highbd_dr_prediction_z1(dst, stride, bs, above, left, dx, dy, bd, filter);
} else if (angle > 90 && angle < 180) {
t = -t;
dx = (int)(256 / t);
dy = (int)(256 * t);
highbd_dr_prediction_z2(dst, stride, bs, above, left, dx, dy, bd, filter);
} else if (angle > 180 && angle < 270) {
dx = 1;
dy = -((int)(256 * t));
highbd_dr_prediction_z3(dst, stride, bs, above, left, dx, dy, bd, filter);
} 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);
}
}
static void highbd_filter_intra_predictors_4tap(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int mode,
int bd) {
int k, r, c;
int pred[33][65];
int mean, ipred;
const TX_SIZE tx_size = (bs == 32) ? TX_32X32 :
((bs == 16) ? TX_16X16 : ((bs == 8) ? TX_8X8 : (TX_4X4)));
const int c0 = filter_intra_taps_4[tx_size][mode][0];
const int c1 = filter_intra_taps_4[tx_size][mode][1];
const int c2 = filter_intra_taps_4[tx_size][mode][2];
const int c3 = filter_intra_taps_4[tx_size][mode][3];
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)
pred[r + 1][0] = (int)left[r] - mean;
for (c = 0; c < 2 * bs + 1; ++c)
pred[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 * pred[r - 1][c] + c1 * pred[r][c - 1] +
c2 * pred[r - 1][c - 1] + c3 * pred[r - 1][c + 1];
pred[r][c] = ipred < 0 ?
-((-ipred + FILTER_INTRA_ROUND_VAL) >> FILTER_INTRA_PREC_BITS) :
((ipred + FILTER_INTRA_ROUND_VAL) >> FILTER_INTRA_PREC_BITS);
}
for (r = 0; r < bs; ++r) {
for (c = 0; c < bs; ++c) {
ipred = pred[r + 1][c + 1] + mean;
dst[c] = clip_pixel_highbd(ipred, bd);
}
dst += stride;
}
}
static void highbd_dc_filter_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
highbd_filter_intra_predictors_4tap(dst, stride, bs, above, left, DC_PRED,
bd);
}
static void highbd_v_filter_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
highbd_filter_intra_predictors_4tap(dst, stride, bs, above, left, V_PRED,
bd);
}
static void highbd_h_filter_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
highbd_filter_intra_predictors_4tap(dst, stride, bs, above, left, H_PRED,
bd);
}
static void highbd_d45_filter_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
highbd_filter_intra_predictors_4tap(dst, stride, bs, above, left, D45_PRED,
bd);
}
static void highbd_d135_filter_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
highbd_filter_intra_predictors_4tap(dst, stride, bs, above, left, D135_PRED,
bd);
}
static void highbd_d117_filter_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
highbd_filter_intra_predictors_4tap(dst, stride, bs, above, left, D117_PRED,
bd);
}
static void highbd_d153_filter_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
highbd_filter_intra_predictors_4tap(dst, stride, bs, above, left, D153_PRED,
bd);
}
static void highbd_d207_filter_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
highbd_filter_intra_predictors_4tap(dst, stride, bs, above, left, D207_PRED,
bd);
}
static void highbd_d63_filter_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
highbd_filter_intra_predictors_4tap(dst, stride, bs, above, left, D63_PRED,
bd);
}
static void highbd_tm_filter_predictor(uint16_t *dst, ptrdiff_t stride,
int bs, const uint16_t *above,
const uint16_t *left, int bd) {
highbd_filter_intra_predictors_4tap(dst, stride, bs, above, left, TM_PRED,
bd);
}
static void (*highbd_filter_intra_predictors[EXT_INTRA_MODES])(uint16_t *dst,
ptrdiff_t stride, int bs, const uint16_t *above, const uint16_t *left,
int bd) = {
highbd_dc_filter_predictor, highbd_v_filter_predictor,
highbd_h_filter_predictor, highbd_d45_filter_predictor,
highbd_d135_filter_predictor, highbd_d117_filter_predictor,
highbd_d153_filter_predictor, highbd_d207_filter_predictor,
highbd_d63_filter_predictor, highbd_tm_filter_predictor,
};
#endif // CONFIG_VP9_HIGHBITDEPTH
#endif // CONFIG_EXT_INTRA
#if CONFIG_VP9_HIGHBITDEPTH
static void build_intra_predictors_high(const MACROBLOCKD *xd,
const uint8_t *ref8,
int ref_stride,
uint8_t *dst8,
int dst_stride,
PREDICTION_MODE mode,
TX_SIZE tx_size,
int n_top_px, int n_topright_px,
int n_left_px, int n_bottomleft_px,
int plane) {
int i;
uint16_t *dst = CONVERT_TO_SHORTPTR(dst8);
uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
DECLARE_ALIGNED(16, uint16_t, left_col[MAX_SB_SIZE]);
DECLARE_ALIGNED(16, uint16_t, above_data[MAX_SB_SIZE + 16]);
uint16_t *above_row = above_data + 16;
const uint16_t *const_above_row = above_row;
const int bs = 4 << tx_size;
int need_left = extend_modes[mode] & NEED_LEFT;
int need_above = extend_modes[mode] & NEED_ABOVE;
const uint16_t *above_ref = ref - ref_stride;
int base = 128 << (xd->bd - 8);
// 127 127 127 .. 127 127 127 127 127 127
// 129 A B .. Y Z
// 129 C D .. W X
// 129 E F .. U V
// 129 G H .. S T T T T T
#if CONFIG_EXT_INTRA
const EXT_INTRA_MODE_INFO *ext_intra_mode_info =
&xd->mi[0]->mbmi.ext_intra_mode_info;
const EXT_INTRA_MODE ext_intra_mode =
ext_intra_mode_info->ext_intra_mode[plane != 0];
int p_angle = 0;
if (mode != DC_PRED && mode != TM_PRED &&
xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
p_angle = mode_to_angle_map[mode] +
xd->mi[0]->mbmi.angle_delta[plane != 0] * ANGLE_STEP;
if (p_angle <= 90)
need_above = 1, need_left = 0;
else if (p_angle < 180)
need_above = 1, need_left = 1;
else
need_above = 0, need_left = 1;
}
if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
EXT_INTRA_MODE ext_intra_mode =
ext_intra_mode_info->ext_intra_mode[plane != 0];
need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT;
need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE;
}
#endif // CONFIG_EXT_INTRA
(void) plane;
// NEED_LEFT
if (need_left) {
#if CONFIG_EXT_INTRA
int need_bottom;
if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
need_bottom = 0;
} else if (mode != DC_PRED && mode != TM_PRED &&
xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
need_bottom = p_angle > 180;
} else {
need_bottom = !!(extend_modes[mode] & NEED_BOTTOMLEFT);
}
#else
const int need_bottom = !!(extend_modes[mode] & NEED_BOTTOMLEFT);
#endif // CONFIG_EXT_INTRA
i = 0;
if (n_left_px > 0) {
for (; i < n_left_px; i++)
left_col[i] = ref[i * ref_stride - 1];
if (need_bottom && n_bottomleft_px > 0) {
assert(i == bs);
for (; i < bs + n_bottomleft_px; i++)
left_col[i] = ref[i * ref_stride - 1];
}
if (i < (bs << need_bottom))
vpx_memset16(&left_col[i], left_col[i - 1], (bs << need_bottom) - i);
} else {
vpx_memset16(left_col, base + 1, bs << need_bottom);
}
}
// NEED_ABOVE
if (need_above) {
#if CONFIG_EXT_INTRA
int need_right;
if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
need_right = 1;
} else if (mode != DC_PRED && mode != TM_PRED &&
xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
need_right = p_angle < 90;
} else {
need_right = !!(extend_modes[mode] & NEED_ABOVERIGHT);
}
#else
const int need_right = !!(extend_modes[mode] & NEED_ABOVERIGHT);
#endif // CONFIG_EXT_INTRA
if (n_top_px > 0) {
memcpy(above_row, above_ref, n_top_px * 2);
i = n_top_px;
if (need_right && n_topright_px > 0) {
assert(n_top_px == bs);
memcpy(above_row + bs, above_ref + bs, n_topright_px * 2);
i += n_topright_px;
}
if (i < (bs << need_right))
vpx_memset16(&above_row[i], above_row[i - 1], (bs << need_right) - i);
} else {
vpx_memset16(above_row, base - 1, bs << need_right);
}
}
#if CONFIG_EXT_INTRA
if (ext_intra_mode_info->use_ext_intra_mode[plane != 0] ||
(extend_modes[mode] & NEED_ABOVELEFT) ||
(mode != DC_PRED && mode != TM_PRED &&
xd->mi[0]->mbmi.sb_type >= BLOCK_8X8)) {
above_row[-1] = n_top_px > 0 ?
(n_left_px > 0 ? above_ref[-1] : base + 1) : base - 1;
}
#else
if ((extend_modes[mode] & NEED_ABOVELEFT)) {
above_row[-1] = n_top_px > 0 ?
(n_left_px > 0 ? above_ref[-1] : base + 1) : base - 1;
}
#endif // CONFIG_EXT_INTRA
#if CONFIG_EXT_INTRA
if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
highbd_filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs,
const_above_row, left_col, xd->bd);
return;
}
if (mode != DC_PRED && mode != TM_PRED &&
xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
INTRA_FILTER filter = INTRA_FILTER_LINEAR;
if (plane == 0 && pick_intra_filter(p_angle))
filter = xd->mi[0]->mbmi.intra_filter;
highbd_dr_predictor(dst, dst_stride, bs, const_above_row, left_col,
p_angle, xd->bd, filter);
return;
}
#endif // CONFIG_EXT_INTRA
// predict
if (mode == DC_PRED) {
dc_pred_high[n_left_px > 0][n_top_px > 0][tx_size](dst, dst_stride,
const_above_row,
left_col, xd->bd);
} else {
pred_high[mode][tx_size](dst, dst_stride, const_above_row, left_col,
xd->bd);
}
}
#endif // CONFIG_VP9_HIGHBITDEPTH
static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref,
int ref_stride, uint8_t *dst, int dst_stride,
PREDICTION_MODE mode, TX_SIZE tx_size,
int n_top_px, int n_topright_px,
int n_left_px, int n_bottomleft_px,
int plane) {
int i;
DECLARE_ALIGNED(16, uint8_t, left_col[MAX_SB_SIZE]);
const uint8_t *above_ref = ref - ref_stride;
DECLARE_ALIGNED(16, uint8_t, above_data[MAX_SB_SIZE + 16]);
uint8_t *above_row = above_data + 16;
const uint8_t *const_above_row = above_row;
const int bs = 4 << tx_size;
int need_left = extend_modes[mode] & NEED_LEFT;
int need_above = extend_modes[mode] & NEED_ABOVE;
#if CONFIG_EXT_INTRA
const EXT_INTRA_MODE_INFO *ext_intra_mode_info =
&xd->mi[0]->mbmi.ext_intra_mode_info;
const EXT_INTRA_MODE ext_intra_mode =
ext_intra_mode_info->ext_intra_mode[plane != 0];
int p_angle = 0;
if (mode != DC_PRED && mode != TM_PRED &&
xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
p_angle = mode_to_angle_map[mode] +
xd->mi[0]->mbmi.angle_delta[plane != 0] * ANGLE_STEP;
if (p_angle <= 90)
need_above = 1, need_left = 0;
else if (p_angle < 180)
need_above = 1, need_left = 1;
else
need_above = 0, need_left = 1;
}
if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
EXT_INTRA_MODE ext_intra_mode =
ext_intra_mode_info->ext_intra_mode[plane != 0];
need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT;
need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE;
}
#endif // CONFIG_EXT_INTRA
// 127 127 127 .. 127 127 127 127 127 127
// 129 A B .. Y Z
// 129 C D .. W X
// 129 E F .. U V
// 129 G H .. S T T T T T
// ..
(void) xd;
(void) plane;
assert(n_top_px >= 0);
assert(n_topright_px >= 0);
assert(n_left_px >= 0);
assert(n_bottomleft_px >= 0);
// NEED_LEFT
if (need_left) {
#if CONFIG_EXT_INTRA
int need_bottom;
if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
need_bottom = 0;
} else if (mode != DC_PRED && mode != TM_PRED &&
xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
need_bottom = p_angle > 180;
} else {
need_bottom = !!(extend_modes[mode] & NEED_BOTTOMLEFT);
}
#else
const int need_bottom = !!(extend_modes[mode] & NEED_BOTTOMLEFT);
#endif // CONFIG_EXT_INTRA
i = 0;
if (n_left_px > 0) {
for (; i < n_left_px; i++)
left_col[i] = ref[i * ref_stride - 1];
if (need_bottom && n_bottomleft_px > 0) {
assert(i == bs);
for (; i < bs + n_bottomleft_px; i++)
left_col[i] = ref[i * ref_stride - 1];
}
if (i < (bs << need_bottom))
memset(&left_col[i], left_col[i - 1], (bs << need_bottom) - i);
} else {
memset(left_col, 129, bs << need_bottom);
}
}
// NEED_ABOVE
if (need_above) {
#if CONFIG_EXT_INTRA
int need_right;
if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
need_right = 1;
} else if (mode != DC_PRED && mode != TM_PRED &&
xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
need_right = p_angle < 90;
} else {
need_right = !!(extend_modes[mode] & NEED_ABOVERIGHT);
}
#else
const int need_right = !!(extend_modes[mode] & NEED_ABOVERIGHT);
#endif // CONFIG_EXT_INTRA
if (n_top_px > 0) {
memcpy(above_row, above_ref, n_top_px);
i = n_top_px;
if (need_right && n_topright_px > 0) {
assert(n_top_px == bs);
memcpy(above_row + bs, above_ref + bs, n_topright_px);
i += n_topright_px;
}
if (i < (bs << need_right))
memset(&above_row[i], above_row[i - 1], (bs << need_right) - i);
} else {
memset(above_row, 127, bs << need_right);
}
}
#if CONFIG_EXT_INTRA
if (ext_intra_mode_info->use_ext_intra_mode[plane != 0] ||
(extend_modes[mode] & NEED_ABOVELEFT) ||
(mode != DC_PRED && mode != TM_PRED &&
xd->mi[0]->mbmi.sb_type >= BLOCK_8X8)) {
above_row[-1] = n_top_px > 0 ? (n_left_px > 0 ? above_ref[-1] : 129) : 127;
}
#else
if ((extend_modes[mode] & NEED_ABOVELEFT)) {
above_row[-1] = n_top_px > 0 ? (n_left_px > 0 ? above_ref[-1] : 129) : 127;
}
#endif // CONFIG_EXT_INTRA
#if CONFIG_EXT_INTRA
if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs,
const_above_row, left_col);
return;
}
if (mode != DC_PRED && mode != TM_PRED &&
xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
INTRA_FILTER filter = INTRA_FILTER_LINEAR;
if (plane == 0 && pick_intra_filter(p_angle))
filter = xd->mi[0]->mbmi.intra_filter;
dr_predictor(dst, dst_stride, tx_size, const_above_row, left_col, p_angle,
filter);
return;
}
#endif // CONFIG_EXT_INTRA
// predict
if (mode == DC_PRED) {
dc_pred[n_left_px > 0][n_top_px > 0][tx_size](dst, dst_stride,
const_above_row, left_col);
} else {
pred[mode][tx_size](dst, dst_stride, const_above_row, left_col);
}
}
void vp10_predict_intra_block(const MACROBLOCKD *xd, int bwl_in, int bhl_in,
TX_SIZE tx_size, PREDICTION_MODE mode,
const uint8_t *ref, int ref_stride,
uint8_t *dst, int dst_stride,
int col_off, int row_off, int plane) {
const int txw = (1 << tx_size);
const int have_top = row_off || xd->up_available;
const int have_left = col_off || xd->left_available;
const int x = col_off * 4;
const int y = row_off * 4;
const int bw = VPXMAX(2, 1 << bwl_in);
const int bh = VPXMAX(2, 1 << bhl_in);
const int mi_row = -xd->mb_to_top_edge >> (3 + MI_SIZE_LOG2);
const int mi_col = -xd->mb_to_left_edge >> (3 + MI_SIZE_LOG2);
const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
const struct macroblockd_plane *const pd = &xd->plane[plane];
const int right_available =
mi_col + (1 << mi_width_log2_lookup[bsize]) < xd->tile.mi_col_end;
#if CONFIG_EXT_PARTITION_TYPES
const PARTITION_TYPE partition = xd->mi[0]->mbmi.partition;
#endif
const int have_right = vp10_has_right(bsize, mi_row, mi_col,
right_available,
#if CONFIG_EXT_PARTITION_TYPES
partition,
#endif
tx_size, row_off, col_off,
pd->subsampling_x);
const int have_bottom = vp10_has_bottom(bsize, mi_row, mi_col,
xd->mb_to_bottom_edge > 0,
tx_size, row_off, col_off,
pd->subsampling_y);
const int wpx = 4 * bw;
const int hpx = 4 * bh;
const int txpx = 4 * txw;
// Distance between the right edge of this prediction block to
// the frame right edge
const int xr = (xd->mb_to_right_edge >> (3 + pd->subsampling_x)) +
(wpx - x - txpx);
// Distance between the bottom edge of this prediction block to
// the frame bottom edge
const int yd = (xd->mb_to_bottom_edge >> (3 + pd->subsampling_y)) +
(hpx - y - txpx);
if (xd->mi[0]->mbmi.palette_mode_info.palette_size[plane != 0] > 0) {
const int bs = 4 * (1 << tx_size);
const int stride = 4 * (1 << bwl_in);
int r, c;
uint8_t *map = NULL;
#if CONFIG_VP9_HIGHBITDEPTH
uint16_t *palette = xd->mi[0]->mbmi.palette_mode_info.palette_colors +
plane * PALETTE_MAX_SIZE;
#else
uint8_t *palette = xd->mi[0]->mbmi.palette_mode_info.palette_colors +
plane * PALETTE_MAX_SIZE;
#endif // CONFIG_VP9_HIGHBITDEPTH
map = xd->plane[plane != 0].color_index_map;
#if CONFIG_VP9_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
uint16_t *dst16 = CONVERT_TO_SHORTPTR(dst);
for (r = 0; r < bs; ++r)
for (c = 0; c < bs; ++c)
dst16[r * dst_stride + c] =
palette[map[(r + y) * stride + c + x]];
} else {
for (r = 0; r < bs; ++r)
for (c = 0; c < bs; ++c)
dst[r * dst_stride + c] =
(uint8_t)(palette[map[(r + y) * stride + c + x]]);
}
#else
for (r = 0; r < bs; ++r)
for (c = 0; c < bs; ++c)
dst[r * dst_stride + c] = palette[map[(r + y) * stride + c + x]];
#endif // CONFIG_VP9_HIGHBITDEPTH
return;
}
#if CONFIG_VP9_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
build_intra_predictors_high(xd, ref, ref_stride, dst, dst_stride, mode,
tx_size,
have_top ? VPXMIN(txpx, xr + txpx) : 0,
have_top && have_right ? VPXMIN(txpx, xr) : 0,
have_left ? VPXMIN(txpx, yd + txpx) : 0,
have_bottom && have_left ? VPXMIN(txpx, yd) : 0,
plane);
return;
}
#endif
build_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode,
tx_size,
have_top ? VPXMIN(txpx, xr + txpx) : 0,
have_top && have_right ? VPXMIN(txpx, xr) : 0,
have_left ? VPXMIN(txpx, yd + txpx) : 0,
have_bottom && have_left ? VPXMIN(txpx, yd) : 0,
plane);
}
void vp10_init_intra_predictors(void) {
once(vp10_init_intra_predictors_internal);
}