* 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,
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
#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];
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,
},
},
};
-
#else
-
const vpx_tree_index vp10_ext_tx_tree[TREE_SIZE(TX_TYPES)] = {
-DCT_DCT, 2,
-ADST_ADST, 4,
};
#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] = {
{ 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);
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);
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
}
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;
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;
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);
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) {
#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
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
// 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;
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.
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,
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;
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];
// 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);
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;
// 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;
}
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;
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) {
};
#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;
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];
// 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);
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;
// 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;
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,
+ filter_type);
dst[c] = clip_pixel_highbd(val, bd);
} else {
- dst[c] = left[bs - 1];
+ dst[c] = left[2 * bs - 1];
}
}
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) {
+ int angle, int bd, INTRA_FILTER filter) {
double t = 0;
int dx, dy;
if (angle > 0 && angle < 90) {
dx = -((int)(256 / t));
dy = 1;
- highbd_dr_prediction_z1(dst, stride, bs, above, left, dx, dy, bd);
+ 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);
+ 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);
+ 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) {
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);
+ p_angle, xd->bd, filter);
return;
}
#endif // CONFIG_EXT_INTRA
if (mode != DC_PRED && mode != TM_PRED &&
xd->mi[0]->mbmi.sb_type >= BLOCK_8X8) {
- dr_predictor(dst, dst_stride, tx_size, const_above_row, left_col, p_angle);
+ 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
const uint8_t *ref, int ref_stride,
uint8_t *dst, int dst_stride,
int aoff, int loff, int plane);
+#if CONFIG_EXT_INTRA
+int pick_intra_filter(int angle);
+#endif // CONFIG_EXT_INTRA
#ifdef __cplusplus
} // extern "C"
#endif
#if CONFIG_EXT_INTRA
for (i = 0; i < PLANE_TYPES; ++i)
- for (j = 0; j < 2; j++)
+ for (j = 0; j < 2; ++j)
cm->counts.ext_intra[i][j] += counts->ext_intra[i][j];
+ for (i = 0; i < INTRA_FILTERS + 1; ++i)
+ for (j = 0; j < INTRA_FILTERS; ++j)
+ cm->counts.intra_filter[i][j] += counts->intra_filter[i][j];
#endif // CONFIG_EXT_INTRA
}
for (i = 0; i < PARTITION_TYPES - 1; ++i)
vp10_diff_update_prob(&r, &fc->partition_prob[j][i]);
+#if CONFIG_EXT_INTRA
+ for (i = 0; i < INTRA_FILTERS + 1; ++i)
+ for (j = 0; j < INTRA_FILTERS - 1; ++j)
+ vp10_diff_update_prob(&r, &fc->intra_filter_probs[i][j]);
+#endif // CONFIG_EXT_INTRA
+
if (frame_is_intra_only(cm)) {
vp10_copy(cm->kf_y_prob, vp10_kf_y_mode_prob);
for (k = 0; k < INTRA_MODES; k++)
mbmi->mode = read_intra_mode(r,
get_y_mode_probs(cm, mi, above_mi, left_mi, 0));
#if CONFIG_EXT_INTRA
- if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED)
+ if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED) {
+ int p_angle;
+ const int ctx = vp10_get_pred_context_intra_interp(xd);
mbmi->angle_delta[0] =
read_uniform(r, 2 * MAX_ANGLE_DELTAS + 1) - MAX_ANGLE_DELTAS;
+ p_angle = mode_to_angle_map[mbmi->mode] +
+ mbmi->angle_delta[0] * ANGLE_STEP;
+ if (pick_intra_filter(p_angle)) {
+ FRAME_COUNTS *counts = xd->counts;
+ mbmi->intra_filter = vpx_read_tree(r, vp10_intra_filter_tree,
+ cm->fc->intra_filter_probs[ctx]);
+ if (counts)
+ ++counts->intra_filter[ctx][mbmi->intra_filter];
+ } else {
+ mbmi->intra_filter = INTRA_FILTER_LINEAR;
+ }
+ }
#endif // CONFIG_EXT_INTRA
}
mbmi->mode = read_intra_mode_y(cm, xd, r, size_group_lookup[bsize]);
#if CONFIG_EXT_INTRA
mbmi->angle_delta[0] = 0;
- if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED)
+ if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED) {
+ int p_angle;
mbmi->angle_delta[0] =
read_uniform(r, 2 * MAX_ANGLE_DELTAS + 1) - MAX_ANGLE_DELTAS;
+ p_angle =
+ mode_to_angle_map[mbmi->mode] + mbmi->angle_delta[0] * ANGLE_STEP;
+ if (pick_intra_filter(p_angle)) {
+ FRAME_COUNTS *counts = xd->counts;
+ const int ctx = vp10_get_pred_context_intra_interp(xd);
+ mbmi->intra_filter = vpx_read_tree(r, vp10_intra_filter_tree,
+ cm->fc->intra_filter_probs[ctx]);
+ if (counts)
+ ++counts->intra_filter[ctx][mbmi->intra_filter];
+ } else {
+ mbmi->intra_filter = INTRA_FILTER_LINEAR;
+ }
+ }
#endif // CONFIG_EXT_INTRA
}
#else
static struct vp10_token ext_tx_encodings[TX_TYPES];
#endif // CONFIG_EXT_TX
+#if CONFIG_EXT_INTRA
+static struct vp10_token intra_filter_encodings[INTRA_FILTERS];
+#endif // CONFIG_EXT_INTRA
void vp10_encode_token_init() {
#if CONFIG_EXT_TX
#else
vp10_tokens_from_tree(ext_tx_encodings, vp10_ext_tx_tree);
#endif // CONFIG_EXT_TX
+#if CONFIG_EXT_INTRA
+ vp10_tokens_from_tree(intra_filter_encodings, vp10_intra_filter_tree);
+#endif // CONFIG_EXT_INTRA
}
#if CONFIG_SUPERTX
write_intra_mode(w, mode, cm->fc->y_mode_prob[size_group_lookup[bsize]]);
#if CONFIG_EXT_INTRA
if (mode != DC_PRED && mode != TM_PRED) {
+ int p_angle;
+ const int intra_filter_ctx = vp10_get_pred_context_intra_interp(xd);
write_uniform(w, 2 * MAX_ANGLE_DELTAS + 1,
MAX_ANGLE_DELTAS + mbmi->angle_delta[0]);
+ p_angle = mode_to_angle_map[mode] + mbmi->angle_delta[0] * ANGLE_STEP;
+ if (pick_intra_filter(p_angle)) {
+ vp10_write_token(w, vp10_intra_filter_tree,
+ cm->fc->intra_filter_probs[intra_filter_ctx],
+ &intra_filter_encodings[mbmi->intra_filter]);
+ }
}
#endif // CONFIG_EXT_INTRA
} else {
write_intra_mode(w, mbmi->mode,
get_y_mode_probs(cm, mi, above_mi, left_mi, 0));
#if CONFIG_EXT_INTRA
- if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED)
+ if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED) {
+ int p_angle;
+ const int intra_filter_ctx = vp10_get_pred_context_intra_interp(xd);
write_uniform(w, 2 * MAX_ANGLE_DELTAS + 1,
MAX_ANGLE_DELTAS + mbmi->angle_delta[0]);
+ p_angle =
+ mode_to_angle_map[mbmi->mode] + mbmi->angle_delta[0] * ANGLE_STEP;
+ if (pick_intra_filter(p_angle)) {
+ vp10_write_token(w, vp10_intra_filter_tree,
+ cm->fc->intra_filter_probs[intra_filter_ctx],
+ &intra_filter_encodings[mbmi->intra_filter]);
+ }
+ }
#endif // CONFIG_EXT_INTRA
} else {
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
prob_diff_update(vp10_partition_tree, fc->partition_prob[i],
counts->partition[i], PARTITION_TYPES, &header_bc);
+#if CONFIG_EXT_INTRA
+ for (i = 0; i < INTRA_FILTERS + 1; ++i)
+ prob_diff_update(vp10_intra_filter_tree, fc->intra_filter_probs[i],
+ counts->intra_filter[i], INTRA_FILTERS, &header_bc);
+#endif // CONFIG_EXT_INTRA
+
if (frame_is_intra_only(cm)) {
vp10_copy(cm->kf_y_prob, vp10_kf_y_mode_prob);
for (i = 0; i < INTRA_MODES; ++i)
sum_intra_stats(td->counts, mi, xd->above_mi, xd->left_mi,
frame_is_intra_only(cm));
+#if CONFIG_EXT_INTRA
+ if (output_enabled && bsize >= BLOCK_8X8) {
+ FRAME_COUNTS *counts = td->counts;
+ if (mbmi->mode == DC_PRED)
+ ++counts->ext_intra[0][mbmi->ext_intra_mode_info.use_ext_intra_mode[0]];
+ if (mbmi->uv_mode == DC_PRED)
+ ++counts->ext_intra[1][mbmi->ext_intra_mode_info.use_ext_intra_mode[1]];
+ if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED) {
+ int p_angle;
+ const int intra_filter_ctx = vp10_get_pred_context_intra_interp(xd);
+ p_angle = mode_to_angle_map[mbmi->mode] +
+ mbmi->angle_delta[0] * ANGLE_STEP;
+ if (pick_intra_filter(p_angle))
+ ++counts->intra_filter[intra_filter_ctx][mbmi->intra_filter];
+ }
+ }
+#endif // CONFIG_EXT_INTRA
+
if (bsize >= BLOCK_8X8 && output_enabled) {
if (mbmi->palette_mode_info.palette_size[0] > 0) {
mbmi->palette_mode_info.palette_first_color_idx[0] =
}
}
#endif // CONFIG_EXT_TX
-#if CONFIG_EXT_INTRA
- if (bsize >= BLOCK_8X8 && !is_inter_block(mbmi)) {
- if (mbmi->mode == DC_PRED)
- ++td->counts->ext_intra[0]
- [mbmi->ext_intra_mode_info.use_ext_intra_mode[0]];
- if (mbmi->uv_mode == DC_PRED)
- ++td->counts->ext_intra[1]
- [mbmi->ext_intra_mode_info.use_ext_intra_mode[1]];
- }
-#endif // CONFIG_EXT_INTRA
}
#if CONFIG_VAR_TX
[PALETTE_COLORS];
int palette_uv_color_cost[PALETTE_MAX_SIZE - 1][PALETTE_COLOR_CONTEXTS]
[PALETTE_COLORS];
-
- int multi_arf_allowed;
- int multi_arf_enabled;
- int multi_arf_last_grp_enabled;
#if CONFIG_EXT_TX
int inter_tx_type_costs[EXT_TX_SETS_INTER][EXT_TX_SIZES][TX_TYPES];
int intra_tx_type_costs[EXT_TX_SETS_INTRA][EXT_TX_SIZES][INTRA_MODES]
int intra_tx_type_costs[EXT_TX_SIZES][TX_TYPES][TX_TYPES];
int inter_tx_type_costs[EXT_TX_SIZES][TX_TYPES];
#endif // CONFIG_EXT_TX
+#if CONFIG_EXT_INTRA
+ int intra_filter_cost[INTRA_FILTERS + 1][INTRA_FILTERS];
+#endif // CONFIG_EXT_INTRA
+
+ int multi_arf_allowed;
+ int multi_arf_enabled;
+ int multi_arf_last_grp_enabled;
#if CONFIG_VP9_TEMPORAL_DENOISING
VP9_DENOISER denoiser;
#endif
vp10_ext_tx_tree);
}
#endif // CONFIG_EXT_TX
+#if CONFIG_EXT_INTRA
+ for (i = 0; i < INTRA_FILTERS + 1; ++i)
+ vp10_cost_tokens(cpi->intra_filter_cost[i], fc->intra_filter_probs[i],
+ vp10_intra_filter_tree);
+#endif // CONFIG_EXT_INTRA
}
static void fill_token_costs(vp10_coeff_cost *c,
#if CONFIG_EXT_INTRA
mic->mbmi.ext_intra_mode_info.use_ext_intra_mode[0] = 0;
+ mic->mbmi.intra_filter = INTRA_FILTER_LINEAR;
#endif // CONFIG_EXT_INTRA
// Pick modes for each sub-block (of size 4x4, 4x8, or 8x4) in an 8x8 block.
MODE_INFO *const mic = xd->mi[0];
MB_MODE_INFO *mbmi = &mic->mbmi;
int this_rate, this_rate_tokenonly, s;
- int angle_delta, best_angle_delta = 0;
+ int angle_delta, best_angle_delta = 0, p_angle;
+ const int intra_filter_ctx = vp10_get_pred_context_intra_interp(xd);
+ INTRA_FILTER filter, best_filter = INTRA_FILTER_LINEAR;
const double rd_adjust = 1.2;
int64_t this_distortion, this_rd, sse_dummy;
TX_SIZE best_tx_size = mic->mbmi.tx_size;
for (i = 0; i < level1; ++i) {
mic->mbmi.angle_delta[0] = deltas_level1[i];
- super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
- &s, NULL, bsize,
- (i == 0 && best_rd < INT64_MAX) ? best_rd * rd_adjust :
- best_rd);
- if (this_rate_tokenonly == INT_MAX) {
- if (i == 0)
- break;
- else
+ p_angle = mode_to_angle_map[mbmi->mode] +
+ mbmi->angle_delta[0] * ANGLE_STEP;
+ for (filter = INTRA_FILTER_LINEAR; filter < INTRA_FILTERS; ++filter) {
+ if (!pick_intra_filter(p_angle) && filter != INTRA_FILTER_LINEAR)
continue;
- }
- this_rate = this_rate_tokenonly + rate_overhead;
- this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
- if (i == 0 && best_rd < INT64_MAX && this_rd > best_rd * rd_adjust)
- break;
- if (this_rd < best_rd) {
- best_i = i;
- best_rd = this_rd;
- best_angle_delta = mbmi->angle_delta[0];
- best_tx_size = mbmi->tx_size;
- best_tx_type = mbmi->tx_type;
- *rate = this_rate;
- *rate_tokenonly = this_rate_tokenonly;
- *distortion = this_distortion;
- *skippable = s;
+ mic->mbmi.intra_filter = filter;
+ super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
+ &s, NULL, bsize,
+ (i == 0 && filter == INTRA_FILTER_LINEAR &&
+ best_rd < INT64_MAX) ? best_rd * rd_adjust : best_rd);
+ if (this_rate_tokenonly == INT_MAX) {
+ if (i == 0 && filter == INTRA_FILTER_LINEAR)
+ return best_rd;
+ else
+ continue;
+ }
+ this_rate = this_rate_tokenonly + rate_overhead +
+ cpi->intra_filter_cost[intra_filter_ctx][filter];
+ this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+ if (i == 0 && filter == INTRA_FILTER_LINEAR &&
+ best_rd < INT64_MAX && this_rd > best_rd * rd_adjust)
+ return best_rd;
+ if (this_rd < best_rd) {
+ best_i = i;
+ best_rd = this_rd;
+ best_angle_delta = mbmi->angle_delta[0];
+ best_tx_size = mbmi->tx_size;
+ best_filter = mbmi->intra_filter;
+ best_tx_type = mbmi->tx_type;
+ *rate = this_rate;
+ *rate_tokenonly = this_rate_tokenonly;
+ *distortion = this_distortion;
+ *skippable = s;
+ }
}
}
if (best_i >= 0) {
for (j = 0; j < level2; ++j) {
mic->mbmi.angle_delta[0] = deltas_level2[best_i][j];
+ p_angle = mode_to_angle_map[mbmi->mode] +
+ mbmi->angle_delta[0] * ANGLE_STEP;
+ for (filter = INTRA_FILTER_LINEAR; filter < INTRA_FILTERS; ++filter) {
+ mic->mbmi.intra_filter = filter;
+ if (!pick_intra_filter(p_angle) && filter != INTRA_FILTER_LINEAR)
+ continue;
+ super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
+ &s, NULL, bsize, best_rd);
+ if (this_rate_tokenonly == INT_MAX)
+ continue;
+ this_rate = this_rate_tokenonly + rate_overhead +
+ cpi->intra_filter_cost[intra_filter_ctx][filter];
+ this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+ if (this_rd < best_rd) {
+ best_rd = this_rd;
+ best_angle_delta = mbmi->angle_delta[0];
+ best_tx_size = mbmi->tx_size;
+ best_filter = mbmi->intra_filter;
+ best_tx_type = mbmi->tx_type;
+ *rate = this_rate;
+ *rate_tokenonly = this_rate_tokenonly;
+ *distortion = this_distortion;
+ *skippable = s;
+ }
+ }
+ }
+ }
+ } else {
+ for (angle_delta = -MAX_ANGLE_DELTAS; angle_delta <= MAX_ANGLE_DELTAS;
+ ++angle_delta) {
+ mbmi->angle_delta[0] = angle_delta;
+ p_angle = mode_to_angle_map[mbmi->mode] +
+ mbmi->angle_delta[0] * ANGLE_STEP;
+ for (filter = INTRA_FILTER_LINEAR; filter < INTRA_FILTERS; ++filter) {
+ mic->mbmi.intra_filter = filter;
+ if (!pick_intra_filter(p_angle) && filter != INTRA_FILTER_LINEAR)
+ continue;
super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
&s, NULL, bsize, best_rd);
if (this_rate_tokenonly == INT_MAX)
continue;
- this_rate = this_rate_tokenonly + rate_overhead;
+
+ this_rate = this_rate_tokenonly + rate_overhead +
+ cpi->intra_filter_cost[intra_filter_ctx][filter];
this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+
if (this_rd < best_rd) {
best_rd = this_rd;
best_angle_delta = mbmi->angle_delta[0];
best_tx_size = mbmi->tx_size;
+ best_filter = mbmi->intra_filter;
best_tx_type = mbmi->tx_type;
*rate = this_rate;
*rate_tokenonly = this_rate_tokenonly;
}
}
}
- } else {
- for (angle_delta = -MAX_ANGLE_DELTAS; angle_delta <= MAX_ANGLE_DELTAS;
- ++angle_delta) {
- mic->mbmi.angle_delta[0] = angle_delta;
-
- super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
- &s, NULL, bsize, best_rd);
- if (this_rate_tokenonly == INT_MAX)
- continue;
-
- this_rate = this_rate_tokenonly + rate_overhead;
- this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
-
- if (this_rd < best_rd) {
- best_rd = this_rd;
- best_angle_delta = mbmi->angle_delta[0];
- best_tx_size = mbmi->tx_size;
- best_tx_type = mbmi->tx_type;
- *rate = this_rate;
- *rate_tokenonly = this_rate_tokenonly;
- *distortion = this_distortion;
- *skippable = s;
- }
- }
}
mbmi->tx_size = best_tx_size;
mbmi->angle_delta[0] = best_angle_delta;
+ mic->mbmi.intra_filter = best_filter;
mbmi->tx_type = best_tx_type;
if (*rate_tokenonly < INT_MAX) {
int64_t this_distortion, this_rd;
TX_SIZE best_tx = TX_4X4;
#if CONFIG_EXT_INTRA
+ const int intra_filter_ctx = vp10_get_pred_context_intra_interp(xd);
EXT_INTRA_MODE_INFO ext_intra_mode_info;
int is_directional_mode, rate_overhead, best_angle_delta = 0;
+ INTRA_FILTER best_filter = INTRA_FILTER_LINEAR;
uint8_t directional_mode_skip_mask[INTRA_MODES];
const int src_stride = x->plane[0].src.stride;
const uint8_t *src = x->plane[0].src.buf;
#if CONFIG_EXT_INTRA
if (mode == DC_PRED && ALLOW_FILTER_INTRA_MODES)
this_rate += vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 0);
- if (is_directional_mode)
+ if (is_directional_mode) {
+ int p_angle;
this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1,
MAX_ANGLE_DELTAS +
mic->mbmi.angle_delta[0]);
+ p_angle = mode_to_angle_map[mic->mbmi.mode] +
+ mic->mbmi.angle_delta[0] * ANGLE_STEP;
+ if (pick_intra_filter(p_angle))
+ this_rate +=
+ cpi->intra_filter_cost[intra_filter_ctx][mic->mbmi.intra_filter];
+ }
#endif // CONFIG_EXT_INTRA
this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
best_tx = mic->mbmi.tx_size;
#if CONFIG_EXT_INTRA
best_angle_delta = mic->mbmi.angle_delta[0];
+ best_filter = mic->mbmi.intra_filter;
#endif // CONFIG_EXT_INTRA
best_tx_type = mic->mbmi.tx_type;
*rate = this_rate;
mic->mbmi.tx_size = best_tx;
#if CONFIG_EXT_INTRA
mic->mbmi.angle_delta[0] = best_angle_delta;
+ mic->mbmi.intra_filter = best_filter;
#endif // CONFIG_EXT_INTRA
mic->mbmi.tx_type = best_tx_type;
mic->mbmi.palette_mode_info.palette_size[0] =
rate2 = rate_y + intra_mode_cost[mbmi->mode] + rate_uv_intra[uv_tx];
#if CONFIG_EXT_INTRA
- if (is_directional_mode)
+ if (is_directional_mode) {
+ int p_angle;
+ const int intra_filter_ctx = vp10_get_pred_context_intra_interp(xd);
rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTAS + 1,
MAX_ANGLE_DELTAS +
mbmi->angle_delta[0]);
+ p_angle = mode_to_angle_map[mbmi->mode] +
+ mbmi->angle_delta[0] * ANGLE_STEP;
+ if (pick_intra_filter(p_angle))
+ rate2 += cpi->intra_filter_cost[intra_filter_ctx][mbmi->intra_filter];
+ }
if (mbmi->mode == DC_PRED && ALLOW_FILTER_INTRA_MODES) {
rate2 += vp10_cost_bit(cm->fc->ext_intra_probs[0],