Add intra-interp experiment flag
intra-interp experiment allows intra prediction to use different
interpolation filters. It was part of the ext-intra in the nextgenv2
branch.
Change-Id: I27ab692494dc79bb92e457dbf9a72988577f1c6d
diff --git a/av1/common/blockd.c b/av1/common/blockd.c
index e86338a..8a887f9 100644
--- a/av1/common/blockd.c
+++ b/av1/common/blockd.c
@@ -223,6 +223,7 @@
54, 49, 45, 40, 35, 31, 26, 22, 17, 13, 8, 4,
};
+#if CONFIG_INTRA_INTERP
int av1_is_intra_filter_switchable(int angle) {
assert(angle > 0 && angle < 270);
if (angle % 45 == 0) return 0;
@@ -234,4 +235,5 @@
0xFF) > 0;
}
}
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index 793561a..eb7f915 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -302,9 +302,12 @@
FILTER_INTRA_MODE_INFO filter_intra_mode_info;
#endif // CONFIG_FILTER_INTRA
#if CONFIG_EXT_INTRA
+ // The actual prediction angle is the base angle + (angle_delta * step).
int8_t angle_delta[2];
+#if CONFIG_INTRA_INTERP
// To-Do (huisu): this may be replaced by interp_filter
INTRA_FILTER intra_filter;
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
#if CONFIG_EXT_INTER
@@ -697,9 +700,11 @@
0, 90, 180, 45, 135, 111, 157, 203, 67, 0,
};
+#if CONFIG_INTRA_INTERP
// Returns whether filter selection is needed for a given
// intra prediction angle.
int av1_is_intra_filter_switchable(int angle);
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
#if CONFIG_EXT_TILE
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c
index cbad10a..09868dc 100644
--- a/av1/common/entropymode.c
+++ b/av1/common/entropymode.c
@@ -1636,6 +1636,7 @@
#endif // CONFIG_EXT_TX
#if CONFIG_EXT_INTRA
+#if CONFIG_INTRA_INTERP
static const aom_prob default_intra_filter_probs[INTRA_FILTERS + 1]
[INTRA_FILTERS - 1] = {
{ 98, 63, 60 },
@@ -1648,6 +1649,7 @@
-INTRA_FILTER_LINEAR, 2, -INTRA_FILTER_8TAP, 4, -INTRA_FILTER_8TAP_SHARP,
-INTRA_FILTER_8TAP_SMOOTH,
};
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
#if CONFIG_FILTER_INTRA
@@ -1723,7 +1725,9 @@
av1_copy(fc->seg.tree_probs, default_segment_tree_probs);
av1_copy(fc->seg.pred_probs, default_segment_pred_probs);
#if CONFIG_EXT_INTRA
+#if CONFIG_INTRA_INTERP
av1_copy(fc->intra_filter_probs, default_intra_filter_probs);
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
#if CONFIG_FILTER_INTRA
av1_copy(fc->filter_intra_probs, default_filter_intra_probs);
@@ -2036,10 +2040,12 @@
mode_mv_merge_probs(pre_fc->delta_q_prob[i], counts->delta_q[i]);
#endif
#if CONFIG_EXT_INTRA
+#if CONFIG_INTRA_INTERP
for (i = 0; i < INTRA_FILTERS + 1; ++i) {
aom_tree_merge_probs(av1_intra_filter_tree, pre_fc->intra_filter_probs[i],
counts->intra_filter[i], fc->intra_filter_probs[i]);
}
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
#if CONFIG_FILTER_INTRA
for (i = 0; i < PLANE_TYPES; ++i) {
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h
index dd753a1..63211dc 100644
--- a/av1/common/entropymode.h
+++ b/av1/common/entropymode.h
@@ -152,7 +152,9 @@
#endif // CONFIG_SUPERTX
struct segmentation_probs seg;
#if CONFIG_EXT_INTRA
+#if CONFIG_INTRA_INTERP
aom_prob intra_filter_probs[INTRA_FILTERS + 1][INTRA_FILTERS - 1];
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
#if CONFIG_FILTER_INTRA
aom_prob filter_intra_probs[PLANE_TYPES];
@@ -271,7 +273,9 @@
#endif // CONFIG_SUPERTX
struct seg_counts seg;
#if CONFIG_EXT_INTRA
+#if CONFIG_INTRA_INTERP
unsigned int intra_filter[INTRA_FILTERS + 1][INTRA_FILTERS];
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
#if CONFIG_FILTER_INTRA
unsigned int filter_intra[PLANE_TYPES][2];
@@ -328,7 +332,9 @@
#endif // CONFIG_PALETTE
extern const aom_tree_index av1_tx_size_tree[MAX_TX_DEPTH][TREE_SIZE(TX_SIZES)];
#if CONFIG_EXT_INTRA
+#if CONFIG_INTRA_INTERP
extern const aom_tree_index av1_intra_filter_tree[TREE_SIZE(INTRA_FILTERS)];
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
#if CONFIG_EXT_TX
extern const aom_tree_index av1_ext_tx_inter_tree[EXT_TX_SETS_INTER]
diff --git a/av1/common/filter.c b/av1/common/filter.c
index 3f1cdbb..0d6bc3b 100644
--- a/av1/common/filter.c
+++ b/av1/common/filter.c
@@ -194,12 +194,14 @@
#endif // CONFIG_EXT_INTERP
#if CONFIG_EXT_INTRA
+#if CONFIG_INTRA_INTERP
const InterpKernel *av1_intra_filter_kernels[INTRA_FILTERS] = {
bilinear_filters, // 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_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
#if CONFIG_EXT_INTERP
diff --git a/av1/common/filter.h b/av1/common/filter.h
index 44f8f02..020d7dd 100644
--- a/av1/common/filter.h
+++ b/av1/common/filter.h
@@ -64,6 +64,7 @@
typedef uint8_t InterpFilter;
#if CONFIG_EXT_INTRA
+#if CONFIG_INTRA_INTERP
typedef enum {
INTRA_FILTER_LINEAR,
INTRA_FILTER_8TAP,
@@ -73,6 +74,7 @@
} INTRA_FILTER;
extern const InterpKernel *av1_intra_filter_kernels[INTRA_FILTERS];
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
typedef struct InterpFilterParams {
diff --git a/av1/common/pred_common.c b/av1/common/pred_common.c
index e522725..bbf21c9 100644
--- a/av1/common/pred_common.c
+++ b/av1/common/pred_common.c
@@ -96,6 +96,7 @@
#endif
#if CONFIG_EXT_INTRA
+#if CONFIG_INTRA_INTERP
// Obtain the reference filter type from the above/left neighbor blocks.
static INTRA_FILTER get_ref_intra_filter(const MB_MODE_INFO *ref_mbmi) {
INTRA_FILTER ref_type = INTRA_FILTERS;
@@ -143,6 +144,7 @@
else
return INTRA_FILTERS;
}
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
// The mode info data structure has a one element border above and to the
diff --git a/av1/common/pred_common.h b/av1/common/pred_common.h
index 71865f2..49d09fc 100644
--- a/av1/common/pred_common.h
+++ b/av1/common/pred_common.h
@@ -74,7 +74,9 @@
#endif
#if CONFIG_EXT_INTRA
+#if CONFIG_INTRA_INTERP
int av1_get_pred_context_intra_interp(const MACROBLOCKD *xd);
+#endif // CONFIG_INTRA_INTERP
#endif // CONFIG_EXT_INTRA
int av1_get_intra_inter_context(const MACROBLOCKD *xd);
diff --git a/av1/common/reconintra.c b/av1/common/reconintra.c
index db44a23..5a6583b 100644
--- a/av1/common/reconintra.c
+++ b/av1/common/reconintra.c
@@ -407,6 +407,7 @@
}
#if CONFIG_EXT_INTRA
+#if CONFIG_INTRA_INTERP
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) {
@@ -435,11 +436,15 @@
return val;
}
+#endif // CONFIG_INTRA_INTERP
// 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) {
+ const uint8_t *above, const uint8_t *left,
+#if CONFIG_INTRA_INTERP
+ INTRA_FILTER filter_type,
+#endif // CONFIG_INTRA_INTERP
+ int dx, int dy) {
int r, c, x, base, shift, val;
(void)left;
@@ -447,6 +452,7 @@
assert(dy == 1);
assert(dx < 0);
+#if CONFIG_INTRA_INTERP
if (filter_type != INTRA_FILTER_LINEAR) {
const int pad_size = SUBPEL_TAPS >> 1;
int len;
@@ -505,8 +511,8 @@
}
return;
}
+#endif // CONFIG_INTRA_INTERP
- // For linear filter, C code is faster.
x = -dx;
for (r = 0; r < bs; ++r, dst += stride, x -= dx) {
base = x >> 8;
@@ -535,8 +541,11 @@
// 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) {
+ const uint8_t *above, const uint8_t *left,
+#if CONFIG_INTRA_INTERP
+ INTRA_FILTER filter_type,
+#endif // CONFIG_INTRA_INTERP
+ int dx, int dy) {
int r, c, x, y, shift1, shift2, val, base1, base2;
assert(dx > 0);
@@ -549,14 +558,24 @@
for (c = 0; c < bs; ++c, ++base1, y -= dy) {
if (base1 >= -1) {
shift1 = x & 0xFF;
+#if CONFIG_INTRA_INTERP
val =
intra_subpel_interp(base1, shift1, above, -1, bs - 1, filter_type);
+#else
+ val = above[base1] * (256 - shift1) + above[base1 + 1] * shift1;
+ val = ROUND_POWER_OF_TWO(val, 8);
+#endif // CONFIG_INTRA_INTERP
} else {
base2 = y >> 8;
if (base2 >= 0) {
shift2 = y & 0xFF;
+#if CONFIG_INTRA_INTERP
val =
intra_subpel_interp(base2, shift2, left, 0, bs - 1, filter_type);
+#else
+ val = left[base2] * (256 - shift2) + left[base2 + 1] * shift2;
+ val = ROUND_POWER_OF_TWO(val, 8);
+#endif // CONFIG_INTRA_INTERP
} else {
val = left[0];
}
@@ -568,8 +587,11 @@
// 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) {
+ const uint8_t *above, const uint8_t *left,
+#if CONFIG_INTRA_INTERP
+ INTRA_FILTER filter_type,
+#endif // CONFIG_INTRA_INTERP
+ int dx, int dy) {
int r, c, y, base, shift, val;
(void)above;
@@ -578,6 +600,7 @@
assert(dx == 1);
assert(dy < 0);
+#if CONFIG_INTRA_INTERP
if (filter_type != INTRA_FILTER_LINEAR) {
const int pad_size = SUBPEL_TAPS >> 1;
int len, i;
@@ -646,8 +669,8 @@
}
return;
}
+#endif // CONFIG_INTRA_INTERP
- // For linear filter, C code is faster.
y = -dy;
for (c = 0; c < bs; ++c, y -= dy) {
base = y >> 8;
@@ -697,19 +720,34 @@
}
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) {
+ const uint8_t *above, const uint8_t *left,
+#if CONFIG_INTRA_INTERP
+ INTRA_FILTER filter_type,
+#endif // CONFIG_INTRA_INTERP
+ int angle) {
const int dx = get_dx(angle);
const int dy = get_dy(angle);
const int bs = tx_size_wide[tx_size];
assert(angle > 0 && angle < 270);
if (angle > 0 && angle < 90) {
- dr_prediction_z1(dst, stride, bs, above, left, dx, dy, filter_type);
+ dr_prediction_z1(dst, stride, bs, above, left,
+#if CONFIG_INTRA_INTERP
+ filter_type,
+#endif // CONFIG_INTRA_INTERP
+ dx, dy);
} else if (angle > 90 && angle < 180) {
- dr_prediction_z2(dst, stride, bs, above, left, dx, dy, filter_type);
+ dr_prediction_z2(dst, stride, bs, above, left,
+#if CONFIG_INTRA_INTERP
+ filter_type,
+#endif // CONFIG_INTRA_INTERP
+ dx, dy);
} else if (angle > 180 && angle < 270) {
- dr_prediction_z3(dst, stride, bs, above, left, dx, dy, filter_type);
+ dr_prediction_z3(dst, stride, bs, above, left,
+#if CONFIG_INTRA_INTERP
+ filter_type,
+#endif // CONFIG_INTRA_INTERP
+ dx, dy);
} else if (angle == 90) {
pred[V_PRED][tx_size](dst, stride, above, left);
} else if (angle == 180) {
@@ -718,6 +756,7 @@
}
#if CONFIG_AOM_HIGHBITDEPTH
+#if CONFIG_INTRA_INTERP
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) {
@@ -746,12 +785,15 @@
return val;
}
+#endif // CONFIG_INTRA_INTERP
// 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) {
+#if CONFIG_INTRA_INTERP
+ INTRA_FILTER filter_type,
+#endif // CONFIG_INTRA_INTERP
+ int dx, int dy, int bd) {
int r, c, x, y, base, shift, val;
(void)left;
@@ -766,8 +808,13 @@
base = x >> 8;
shift = x & 0xFF;
if (base < 2 * bs - 1) {
+#if CONFIG_INTRA_INTERP
val = highbd_intra_subpel_interp(base, shift, above, 0, 2 * bs - 1,
filter_type);
+#else
+ val = above[base] * (256 - shift) + above[base + 1] * shift;
+ val = ROUND_POWER_OF_TWO(val, 8);
+#endif // CONFIG_INTRA_INTERP
dst[c] = clip_pixel_highbd(val, bd);
} else {
dst[c] = above[2 * bs - 1];
@@ -780,8 +827,10 @@
// 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) {
+#if CONFIG_INTRA_INTERP
+ INTRA_FILTER filter_type,
+#endif // CONFIG_INTRA_INTERP
+ int dx, int dy, int bd) {
int r, c, x, y, shift, val, base;
assert(dx > 0);
@@ -794,16 +843,26 @@
base = x >> 8;
if (base >= -1) {
shift = x & 0xFF;
+#if CONFIG_INTRA_INTERP
val = highbd_intra_subpel_interp(base, shift, above, -1, bs - 1,
filter_type);
+#else
+ val = above[base] * (256 - shift) + above[base + 1] * shift;
+ val = ROUND_POWER_OF_TWO(val, 8);
+#endif // CONFIG_INTRA_INTERP
} else {
x = c + 1;
y = (r << 8) - x * dy;
base = y >> 8;
if (base >= 0) {
shift = y & 0xFF;
+#if CONFIG_INTRA_INTERP
val = highbd_intra_subpel_interp(base, shift, left, 0, bs - 1,
filter_type);
+#else
+ val = left[base] * (256 - shift) + left[base + 1] * shift;
+ val = ROUND_POWER_OF_TWO(val, 8);
+#endif // CONFIG_INTRA_INTERP
} else {
val = left[0];
}
@@ -817,8 +876,10 @@
// 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) {
+#if CONFIG_INTRA_INTERP
+ INTRA_FILTER filter_type,
+#endif // CONFIG_INTRA_INTERP
+ int dx, int dy, int bd) {
int r, c, x, y, base, shift, val;
(void)above;
@@ -833,8 +894,13 @@
base = y >> 8;
shift = y & 0xFF;
if (base < 2 * bs - 1) {
+#if CONFIG_INTRA_INTERP
val = highbd_intra_subpel_interp(base, shift, left, 0, 2 * bs - 1,
filter_type);
+#else
+ val = left[base] * (256 - shift) + left[base + 1] * shift;
+ val = ROUND_POWER_OF_TWO(val, 8);
+#endif // CONFIG_INTRA_INTERP
dst[c] = clip_pixel_highbd(val, bd);
} else {
dst[c] = left[2 * bs - 1];
@@ -870,17 +936,32 @@
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) {
+#if CONFIG_INTRA_INTERP
+ INTRA_FILTER filter,
+#endif // CONFIG_INTRA_INTERP
+ int angle, int bd) {
const int dx = get_dx(angle);
const int dy = get_dy(angle);
assert(angle > 0 && angle < 270);
if (angle > 0 && angle < 90) {
- highbd_dr_prediction_z1(dst, stride, bs, above, left, dx, dy, bd, filter);
+ highbd_dr_prediction_z1(dst, stride, bs, above, left,
+#if CONFIG_INTRA_INTERP
+ filter,
+#endif // CONFIG_INTRA_INTERP
+ dx, dy, bd);
} else if (angle > 90 && angle < 180) {
- highbd_dr_prediction_z2(dst, stride, bs, above, left, dx, dy, bd, filter);
+ highbd_dr_prediction_z2(dst, stride, bs, above, left,
+#if CONFIG_INTRA_INTERP
+ filter,
+#endif // CONFIG_INTRA_INTERP
+ dx, dy, bd);
} else if (angle > 180 && angle < 270) {
- highbd_dr_prediction_z3(dst, stride, bs, above, left, dx, dy, bd, filter);
+ highbd_dr_prediction_z3(dst, stride, bs, above, left,
+#if CONFIG_INTRA_INTERP
+ filter,
+#endif // CONFIG_INTRA_INTERP
+ dx, dy, bd);
} else if (angle == 90) {
highbd_v_predictor(dst, stride, bs, above, left, bd);
} else if (angle == 180) {
@@ -1397,11 +1478,16 @@
#if CONFIG_EXT_INTRA
if (is_dr_mode) {
+#if CONFIG_INTRA_INTERP
INTRA_FILTER filter = INTRA_FILTER_LINEAR;
if (plane == 0 && av1_is_intra_filter_switchable(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);
+#endif // CONFIG_INTRA_INTERP
+ highbd_dr_predictor(dst, dst_stride, bs, const_above_row, left_col,
+#if CONFIG_INTRA_INTERP
+ filter,
+#endif // CONFIG_INTRA_INTERP
+ p_angle, xd->bd);
return;
}
#endif // CONFIG_EXT_INTRA
@@ -1555,11 +1641,16 @@
#endif // CONFIG_FILTER_INTRA
#if CONFIG_EXT_INTRA
if (is_dr_mode) {
+#if CONFIG_INTRA_INTERP
INTRA_FILTER filter = INTRA_FILTER_LINEAR;
if (plane == 0 && av1_is_intra_filter_switchable(p_angle))
filter = xd->mi[0]->mbmi.intra_filter;
- dr_predictor(dst, dst_stride, tx_size, const_above_row, left_col, p_angle,
- filter);
+#endif // CONFIG_INTRA_INTERP
+ dr_predictor(dst, dst_stride, tx_size, const_above_row, left_col,
+#if CONFIG_INTRA_INTERP
+ filter,
+#endif // CONFIG_INTRA_INTERP
+ p_angle);
return;
}
#endif // CONFIG_EXT_INTRA