Commit 3b1c7668 authored by hui su's avatar hui su

Add 8-tap interpolation filter options for intra prediction

BD-rate performance improvement (on top of ext-intra):
derflr  0.22%
hevclr  0.36%
hevcmr  0.48%
hevchr  0.37%
stdhd   0.19%

Average speed impact on some derf clips is about 40% slower (on
top of ext-intra). Speed improvment is a to-do.

Change-Id: I8fe3fe8c5e4f60d0462778adbcc15c84dfbe7a25
parent 392d577c
......@@ -8,6 +8,7 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include <math.h>
#include "vp10/common/blockd.h"
PREDICTION_MODE vp10_left_block_mode(const MODE_INFO *cur_mi,
......@@ -134,3 +135,23 @@ void vp10_setup_block_planes(MACROBLOCKD *xd, int ss_x, int ss_y) {
xd->plane[i].subsampling_y = i ? ss_y : 0;
}
}
#if CONFIG_EXT_INTRA
#define PI 3.14159265
// Returns whether filter selection is needed for a given
// intra prediction angle.
int pick_intra_filter(int angle) {
if (angle % 45 == 0)
return 0;
if (angle > 90 && angle < 180) {
return 1;
} else {
double t = tan(angle * PI / 180.0);
double n;
if (angle < 90)
t = 1 / t;
n = floor(t);
return (t - n) * 1024 > 1;
}
}
#endif // CONFIG_EXT_INTRA
......@@ -163,6 +163,8 @@ typedef struct {
#if CONFIG_EXT_INTRA
EXT_INTRA_MODE_INFO ext_intra_mode_info;
int8_t angle_delta[2];
// To-Do (huisu): this may be replaced by interp_filter
INTRA_FILTER intra_filter;
#endif // CONFIG_EXT_INTRA
int_mv mv[2];
......@@ -413,6 +415,8 @@ static const TX_TYPE filter_intra_mode_to_tx_type_lookup[FILTER_INTRA_MODES] = {
ADST_DCT, // FILTER_D63
ADST_ADST, // FILTER_TM
};
int pick_intra_filter(int angle);
#endif // CONFIG_EXT_INTRA
static INLINE TX_TYPE get_tx_type(PLANE_TYPE plane_type,
......
......@@ -1220,9 +1220,7 @@ default_intra_ext_tx_prob[EXT_TX_SETS_INTRA][EXT_TX_SIZES]
},
},
};
#else
const vpx_tree_index vp10_ext_tx_tree[TREE_SIZE(TX_TYPES)] = {
-DCT_DCT, 2,
-ADST_ADST, 4,
......@@ -1244,6 +1242,24 @@ static const vpx_prob default_inter_ext_tx_prob[EXT_TX_SIZES]
};
#endif // CONFIG_EXT_TX
#if CONFIG_EXT_INTRA
static const vpx_prob
default_intra_filter_probs[INTRA_FILTERS + 1][INTRA_FILTERS - 1] = {
{ 98, 63, 60, },
{ 98, 82, 80, },
{ 94, 65, 103, },
{ 49, 25, 24, },
{ 72, 38, 50, },
};
static const vpx_prob default_ext_intra_probs[2] = {230, 230};
const vpx_tree_index vp10_intra_filter_tree[TREE_SIZE(INTRA_FILTERS)] = {
-INTRA_FILTER_LINEAR, 2,
-INTRA_FILTER_8TAP, 4,
-INTRA_FILTER_8TAP_SHARP, -INTRA_FILTER_8TAP_SMOOTH,
};
#endif // CONFIG_EXT_INTRA
#if CONFIG_SUPERTX
static const vpx_prob default_supertx_prob[PARTITION_SUPERTX_CONTEXTS]
[TX_SIZES] = {
......@@ -1258,10 +1274,6 @@ static const struct segmentation_probs default_seg_probs = {
{ 128, 128, 128 },
};
#if CONFIG_EXT_INTRA
static const vpx_prob default_ext_intra_probs[2] = {230, 230};
#endif // CONFIG_EXT_INTRA
static void init_mode_probs(FRAME_CONTEXT *fc) {
vp10_copy(fc->uv_mode_prob, default_uv_probs);
vp10_copy(fc->y_mode_prob, default_if_y_probs);
......@@ -1295,6 +1307,7 @@ static void init_mode_probs(FRAME_CONTEXT *fc) {
vp10_copy(fc->seg.pred_probs, default_seg_probs.pred_probs);
#if CONFIG_EXT_INTRA
vp10_copy(fc->ext_intra_probs, default_ext_intra_probs);
vp10_copy(fc->intra_filter_probs, default_intra_filter_probs);
#endif // CONFIG_EXT_INTRA
vp10_copy(fc->inter_ext_tx_prob, default_inter_ext_tx_prob);
vp10_copy(fc->intra_ext_tx_prob, default_intra_ext_tx_prob);
......@@ -1494,6 +1507,10 @@ void vp10_adapt_intra_frame_probs(VP10_COMMON *cm) {
fc->ext_intra_probs[i] = mode_mv_merge_probs(
pre_fc->ext_intra_probs[i], counts->ext_intra[i]);
}
for (i = 0; i < INTRA_FILTERS + 1; ++i)
vpx_tree_merge_probs(vp10_intra_filter_tree, pre_fc->intra_filter_probs[i],
counts->intra_filter[i], fc->intra_filter_probs[i]);
#endif // CONFIG_EXT_INTRA
}
......
......@@ -103,6 +103,7 @@ typedef struct frame_contexts {
struct segmentation_probs seg;
#if CONFIG_EXT_INTRA
vpx_prob ext_intra_probs[PLANE_TYPES];
vpx_prob intra_filter_probs[INTRA_FILTERS + 1][INTRA_FILTERS - 1];
#endif // CONFIG_EXT_INTRA
} FRAME_CONTEXT;
......@@ -154,6 +155,7 @@ typedef struct FRAME_COUNTS {
struct seg_counts seg;
#if CONFIG_EXT_INTRA
unsigned int ext_intra[PLANE_TYPES][2];
unsigned int intra_filter[INTRA_FILTERS + 1][INTRA_FILTERS];
#endif // CONFIG_EXT_INTRA
} FRAME_COUNTS;
......@@ -182,7 +184,18 @@ extern const vpx_tree_index vp10_switchable_interp_tree
extern const vpx_tree_index vp10_palette_size_tree[TREE_SIZE(PALETTE_SIZES)];
extern const vpx_tree_index
vp10_palette_color_tree[PALETTE_MAX_SIZE - 1][TREE_SIZE(PALETTE_COLORS)];
#if CONFIG_EXT_INTRA
extern const vpx_tree_index vp10_intra_filter_tree[TREE_SIZE(INTRA_FILTERS)];
#endif // CONFIG_EXT_INTRA
#if CONFIG_EXT_TX
extern const vpx_tree_index
vp10_ext_tx_inter_tree[EXT_TX_SETS_INTER][TREE_SIZE(TX_TYPES)];
extern const vpx_tree_index
vp10_ext_tx_intra_tree[EXT_TX_SETS_INTRA][TREE_SIZE(TX_TYPES)];
#else
extern const vpx_tree_index
vp10_ext_tx_tree[TREE_SIZE(TX_TYPES)];
#endif // CONFIG_EXT_TX
void vp10_setup_past_independence(struct VP10Common *cm);
......@@ -196,16 +209,6 @@ void vp10_tx_counts_to_branch_counts_16x16(const unsigned int *tx_count_16x16p,
void vp10_tx_counts_to_branch_counts_8x8(const unsigned int *tx_count_8x8p,
unsigned int (*ct_8x8p)[2]);
#if CONFIG_EXT_TX
extern const vpx_tree_index
vp10_ext_tx_inter_tree[EXT_TX_SETS_INTER][TREE_SIZE(TX_TYPES)];
extern const vpx_tree_index
vp10_ext_tx_intra_tree[EXT_TX_SETS_INTRA][TREE_SIZE(TX_TYPES)];
#else
extern const vpx_tree_index
vp10_ext_tx_tree[TREE_SIZE(TX_TYPES)];
#endif // CONFIG_EXT_TX
static INLINE int vp10_ceil_log2(int n) {
int i = 1, p = 2;
while (p < n) {
......
......@@ -192,3 +192,12 @@ const InterpKernel *vp10_filter_kernels[SWITCHABLE_FILTERS + 1] = {
#endif
bilinear_filters
};
#if CONFIG_EXT_INTRA
const InterpKernel *vp10_intra_filter_kernels[INTRA_FILTERS] = {
NULL, // INTRA_FILTER_LINEAR
sub_pel_filters_8, // INTRA_FILTER_8TAP
sub_pel_filters_8sharp, // INTRA_FILTER_8TAP_SHARP
sub_pel_filters_8smooth, // INTRA_FILTER_8TAP_SMOOTH
};
#endif // CONFIG_EXT_INTRA
......@@ -43,6 +43,18 @@ typedef uint8_t INTERP_FILTER;
extern const InterpKernel *vp10_filter_kernels[SWITCHABLE_FILTERS + 1];
#if CONFIG_EXT_INTRA
typedef enum {
INTRA_FILTER_LINEAR,
INTRA_FILTER_8TAP,
INTRA_FILTER_8TAP_SHARP,
INTRA_FILTER_8TAP_SMOOTH,
INTRA_FILTERS,
} INTRA_FILTER;
extern const InterpKernel *vp10_intra_filter_kernels[INTRA_FILTERS];
#endif // CONFIG_EXT_INTRA
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -21,10 +21,10 @@ int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd) {
// The prediction flags in these dummy entries are initialized to 0.
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int left_type = xd->left_available && is_inter_block(left_mbmi) ?
left_mbmi->interp_filter : SWITCHABLE_FILTERS;
left_mbmi->interp_filter : SWITCHABLE_FILTERS;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const int above_type = xd->up_available && is_inter_block(above_mbmi) ?
above_mbmi->interp_filter : SWITCHABLE_FILTERS;
above_mbmi->interp_filter : SWITCHABLE_FILTERS;
if (left_type == above_type)
return left_type;
......@@ -36,6 +36,85 @@ int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd) {
return SWITCHABLE_FILTERS;
}
#if CONFIG_EXT_INTRA
int vp10_get_pred_context_intra_interp(const MACROBLOCKD *xd) {
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
int left_type = INTRA_FILTERS, above_type = INTRA_FILTERS;
if (xd->left_available && left_mbmi->sb_type >= BLOCK_8X8) {
PREDICTION_MODE mode = left_mbmi->mode;
if (is_inter_block(left_mbmi)) {
switch (left_mbmi->interp_filter) {
case EIGHTTAP:
left_type = INTRA_FILTER_8TAP;
break;
case EIGHTTAP_SMOOTH:
left_type = INTRA_FILTER_8TAP_SMOOTH;
break;
case EIGHTTAP_SHARP:
left_type = INTRA_FILTER_8TAP_SHARP;
break;
case BILINEAR:
left_type = INTRA_FILTERS;
break;
default:
break;
}
} else {
if (mode != DC_PRED && mode != TM_PRED) {
int p_angle;
p_angle = mode_to_angle_map[mode] +
left_mbmi->angle_delta[0] * ANGLE_STEP;
if (pick_intra_filter(p_angle)) {
left_type = left_mbmi->intra_filter;
}
}
}
}
if (xd->up_available && above_mbmi->sb_type >= BLOCK_8X8) {
if (is_inter_block(above_mbmi)) {
switch (above_mbmi->interp_filter) {
case EIGHTTAP:
above_type = INTRA_FILTER_8TAP;
break;
case EIGHTTAP_SMOOTH:
above_type = INTRA_FILTER_8TAP_SMOOTH;
break;
case EIGHTTAP_SHARP:
above_type = INTRA_FILTER_8TAP_SHARP;
break;
case BILINEAR:
above_type = INTRA_FILTERS;
break;
default:
break;
}
} else {
PREDICTION_MODE mode = above_mbmi->mode;
if (mode != DC_PRED && mode != TM_PRED) {
int p_angle;
p_angle = mode_to_angle_map[mode] +
above_mbmi->angle_delta[0] * ANGLE_STEP;
if (pick_intra_filter(p_angle)) {
above_type = above_mbmi->intra_filter;
}
}
}
}
if (left_type == above_type)
return left_type;
else if (left_type == INTRA_FILTERS && above_type != INTRA_FILTERS)
return above_type;
else if (left_type != INTRA_FILTERS && above_type == INTRA_FILTERS)
return left_type;
else
return INTRA_FILTERS;
}
#endif // CONFIG_EXT_INTRA
// The mode info data structure has a one element border above and to the
// left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
......
......@@ -68,6 +68,10 @@ static INLINE vpx_prob vp10_get_skip_prob(const VP10_COMMON *cm,
int vp10_get_pred_context_switchable_interp(const MACROBLOCKD *xd);
#if CONFIG_EXT_INTRA
int vp10_get_pred_context_intra_interp(const MACROBLOCKD *xd);
#endif // CONFIG_EXT_INTRA
int vp10_get_intra_inter_context(const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_intra_inter_prob(const VP10_COMMON *cm,
......
......@@ -248,10 +248,39 @@ static const uint8_t ext_intra_extend_modes[FILTER_INTRA_MODES] = {
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) {
int dx, int dy, INTRA_FILTER filter_type) {
int r, c, x, y, base, shift, val;
(void)left;
......@@ -262,12 +291,12 @@ static void dr_prediction_z1(uint8_t *dst, ptrdiff_t stride, int bs,
for (r = 0; r < bs; ++r) {
y = r + 1;
for (c = 0; c < bs; ++c) {
x = c * 256 - y * dx;
x = (c << 8) - y * dx;
base = x >> 8;
shift = x - base * 256;
shift = x - (base << 8);
if (base < 2 * bs - 1) {
val =
(above[base] * (256 - shift) + above[base + 1] * shift + 128) >> 8;
val = intra_subpel_interp(base, shift, above, 0, 2 * bs - 1,
filter_type);
dst[c] = clip_pixel(val);
} else {
dst[c] = above[2 * bs - 1];
......@@ -280,8 +309,8 @@ static void dr_prediction_z1(uint8_t *dst, ptrdiff_t stride, int bs,
// 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) {
int r, c, x, y, val1, val2, shift, val, base;
int dx, int dy, INTRA_FILTER filter_type) {
int r, c, x, y, shift, val, base;
assert(dx > 0);
assert(dy > 0);
......@@ -289,32 +318,22 @@ static void dr_prediction_z2(uint8_t *dst, ptrdiff_t stride, int bs,
for (r = 0; r < bs; ++r) {
for (c = 0; c < bs; ++c) {
y = r + 1;
x = c * 256 - y * dx;
if (x >= -256) {
if (x <= 0) {
val1 = above[-1];
val2 = above[0];
shift = x + 256;
} else {
base = x >> 8;
val1 = above[base];
val2 = above[base + 1];
shift = x - base * 256;
}
x = (c << 8) - y * dx;
base = x >> 8;
if (base >= -1) {
shift = x - (base << 8);
val = intra_subpel_interp(base, shift, above, -1, bs - 1, filter_type);
} else {
x = c + 1;
y = r * 256 - x * dy;
y = (r << 8) - x * dy;
base = y >> 8;
if (base >= 0) {
val1 = left[base];
val2 = left[base + 1];
shift = y - base * 256;
shift = y - (base << 8);
val = intra_subpel_interp(base, shift, left, 0, bs - 1, filter_type);
} else {
val1 = val2 = left[0];
shift = 0;
val = left[0];
}
}
val = (val1 * (256 - shift) + val2 * shift + 128) >> 8;
dst[c] = clip_pixel(val);
}
dst += stride;
......@@ -324,26 +343,27 @@ static void dr_prediction_z2(uint8_t *dst, ptrdiff_t stride, int bs,
// 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) {
int dx, int dy, 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 * 256 - x * dy;
y = (r << 8) - x * dy;
base = y >> 8;
shift = y - base * 256;
shift = y - (base << 8);
if (base < 2 * bs - 1) {
val =
(left[base] * (256 - shift) + left[base + 1] * shift + 128) >> 8;
val = intra_subpel_interp(base, shift, left, 0, 2 * bs - 1,
filter_type);
dst[c] = clip_pixel(val);
} else {
dst[c] = left[bs - 1];
dst[c] = left[ 2 * bs - 1];
}
}
dst += stride;
......@@ -351,7 +371,8 @@ static void dr_prediction_z3(uint8_t *dst, ptrdiff_t stride, int bs,
}
static void dr_predictor(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size,
const uint8_t *above, const uint8_t *left, int angle) {
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;
......@@ -361,16 +382,16 @@ static void dr_predictor(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size,
if (angle > 0 && angle < 90) {
dx = -((int)(256 / t));
dy = 1;
dr_prediction_z1(dst, stride, bs, above, left, dx, dy);
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);
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);
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) {
......@@ -535,10 +556,40 @@ static void (*filter_intra_predictors[EXT_INTRA_MODES])(uint8_t *dst,
};
#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) {
int dx, int dy, int bd,
INTRA_FILTER filter_type) {
int r, c, x, y, base, shift, val;
(void)left;
......@@ -549,12 +600,12 @@ static void highbd_dr_prediction_z1(uint16_t *dst, ptrdiff_t stride, int bs,
for (r = 0; r < bs; ++r) {
y = r + 1;
for (c = 0; c < bs; ++c) {
x = c * 256 - y * dx;
x = (c << 8) - y * dx;
base = x >> 8;
shift = x - base * 256;
shift = x - (base << 8);
if (base < 2 * bs - 1) {
val =
(above[base] * (256 - shift) + above[base + 1] * shift + 128) >> 8;
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];
......@@ -567,8 +618,9 @@ static void highbd_dr_prediction_z1(uint16_t *dst, ptrdiff_t stride, int bs,
// 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) {
int r, c, x, y, val1, val2, shift, val, base;
int dx, int dy, int bd,
INTRA_FILTER filter_type) {
int r, c, x, y, shift, val, base;
assert(dx > 0);
assert(dy > 0);
......@@ -576,32 +628,24 @@ static void highbd_dr_prediction_z2(uint16_t *dst, ptrdiff_t stride, int bs,
for (r = 0; r < bs; ++r) {
for (c = 0; c < bs; ++c) {
y = r + 1;
x = c * 256 - y * dx;
if (x >= -256) {
if (x <= 0) {
val1 = above[-1];
val2 = above[0];
shift = x + 256;
} else {
base = x >> 8;
val1 = above[base];
val2 = above[base + 1];
shift = x - base * 256;
}
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 * 256 - x * dy;
y = (r << 8) - x * dy;
base = y >> 8;
if (base >= 0) {
val1 = left[base];
val2 = left[base + 1];
shift = y - base * 256;
shift = y - (base << 8);
val = highbd_intra_subpel_interp(base, shift, left, 0, bs - 1,
filter_type);
} else {
val1 = val2 = left[0];
shift = 0;
val = left[0];
}
}
val = (val1 * (256 - shift) + val2 * shift + 128) >> 8;
dst[c] = clip_pixel_highbd(val, bd);
}
dst += stride;
......@@ -611,7 +655,8 @@ static void highbd_dr_prediction_z2(uint16_t *dst, ptrdiff_t stride, int bs,
// 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) {
int dx, int dy, int bd,
INTRA_FILTER filter_type) {
int r, c, x, y, base, shift, val;
(void)above;
......@@ -622,15 +667,15 @@ static void highbd_dr_prediction_z3(uint16_t *dst, ptrdiff_t stride, int bs,
for (r = 0; r < bs; ++r) {
for (c = 0; c < bs; ++c) {
x = c + 1;
y = r * 256 - x * dy;
y = (r << 8) - x * dy;
base = y >> 8;
shift = y - base * 256;
shift = y - (base << 8);
if (base < 2 * bs - 1) {
val =
(left[base] * (256 - shift) + left[base + 1] * shift + 128) >> 8;
val = highbd_intra_subpel_interp(base, shift, left, 0, 2 * bs - 1<