[intra-edge] Convert 4x4 VP9 to ext-intra; upsample edge samples

Updates to intra-edge experiment

- Convert VP9-style intra pred to Ext-intra style
- Upsample edge predictors by 2x based on angle and edge size

BD-rate, 1-kf AWCY
  360p:  -0.11%
  720p:  -0.54
  1080p: -0.96

Change-Id: Ib73805d31d5d286e607a7ee7470fcbdf11edbbff
This commit is contained in:
Joe Young 2017-05-30 17:48:13 -07:00
Родитель 71adf5292a
Коммит 830d4ce495
5 изменённых файлов: 282 добавлений и 67 удалений

Просмотреть файл

@ -36,6 +36,14 @@ enum {
NEED_BOTTOMLEFT = 1 << 5,
};
#if CONFIG_INTRA_EDGE
#define INTRA_EDGE_FILT 3
#define INTRA_EDGE_TAPS 5
#if CONFIG_INTRA_EDGE_UPSAMPLE
#define MAX_UPSAMPLE_SZ 12
#endif
#endif
static const uint8_t extend_modes[INTRA_MODES] = {
NEED_ABOVE | NEED_LEFT, // DC
NEED_ABOVE, // V
@ -695,6 +703,9 @@ static void dr_prediction_z1(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
#if CONFIG_INTRA_INTERP
INTRA_FILTER filter_type,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
int upsample_above,
#endif
int dx, int dy) {
int r, c, x, base, shift, val;
@ -764,27 +775,32 @@ static void dr_prediction_z1(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
}
#endif // CONFIG_INTRA_INTERP
#if !CONFIG_INTRA_EDGE_UPSAMPLE
const int upsample_above = 0;
#endif
const int max_base_x = ((bw + bh) - 1) << upsample_above;
const int frac_bits = 8 - upsample_above;
const int base_inc = 1 << upsample_above;
x = dx;
for (r = 0; r < bh; ++r, dst += stride, x += dx) {
base = x >> 8;
shift = x & 0xFF;
base = x >> frac_bits;
shift = (x << upsample_above) & 0xFF;
if (base >= bw + bh - 1) {
int i;
for (i = r; i < bh; ++i) {
memset(dst, above[bw + bh - 1], bw * sizeof(dst[0]));
if (base >= max_base_x) {
for (int i = r; i < bh; ++i) {
memset(dst, above[max_base_x], bw * sizeof(dst[0]));
dst += stride;
}
return;
}
for (c = 0; c < bw; ++c, ++base) {
if (base < bw + bh - 1) {
for (c = 0; c < bw; ++c, base += base_inc) {
if (base < max_base_x) {
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[bw + bh - 1];
dst[c] = above[max_base_x];
}
}
}
@ -796,19 +812,30 @@ static void dr_prediction_z2(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
#if CONFIG_INTRA_INTERP
INTRA_FILTER filter_type,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
int upsample_above, int upsample_left,
#endif
int dx, int dy) {
int r, c, x, y, shift1, shift2, val, base1, base2;
assert(dx > 0);
assert(dy > 0);
#if !CONFIG_INTRA_EDGE_UPSAMPLE
const int upsample_above = 0;
const int upsample_left = 0;
#endif
const int min_base_x = -(1 << upsample_above);
const int frac_bits_x = 8 - upsample_above;
const int frac_bits_y = 8 - upsample_left;
const int base_inc_x = 1 << upsample_above;
x = -dx;
for (r = 0; r < bh; ++r, x -= dx, dst += stride) {
base1 = x >> 8;
base1 = x >> frac_bits_x;
y = (r << 8) - dy;
for (c = 0; c < bw; ++c, ++base1, y -= dy) {
if (base1 >= -1) {
shift1 = x & 0xFF;
for (c = 0; c < bw; ++c, base1 += base_inc_x, y -= dy) {
if (base1 >= min_base_x) {
shift1 = (x << upsample_above) & 0xFF;
#if CONFIG_INTRA_INTERP
val =
intra_subpel_interp(base1, shift1, above, -1, bw - 1, filter_type);
@ -817,9 +844,9 @@ static void dr_prediction_z2(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
val = ROUND_POWER_OF_TWO(val, 8);
#endif // CONFIG_INTRA_INTERP
} else {
base2 = y >> 8;
assert(base2 >= -1);
shift2 = y & 0xFF;
base2 = y >> frac_bits_y;
assert(base2 >= -(1 << upsample_left));
shift2 = (y << upsample_left) & 0xFF;
#if CONFIG_INTRA_INTERP
val = intra_subpel_interp(base2, shift2, left, -1, bh - 1, filter_type);
#else
@ -838,6 +865,9 @@ static void dr_prediction_z3(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
#if CONFIG_INTRA_INTERP
INTRA_FILTER filter_type,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
int upsample_left,
#endif
int dx, int dy) {
int r, c, y, base, shift, val;
@ -918,18 +948,24 @@ static void dr_prediction_z3(uint8_t *dst, ptrdiff_t stride, int bw, int bh,
}
#endif // CONFIG_INTRA_INTERP
#if !CONFIG_INTRA_EDGE_UPSAMPLE
const int upsample_left = 0;
#endif
const int max_base_y = (bw + bh - 1) << upsample_left;
const int frac_bits = 8 - upsample_left;
const int base_inc = 1 << upsample_left;
y = dy;
for (c = 0; c < bw; ++c, y += dy) {
base = y >> 8;
shift = y & 0xFF;
base = y >> frac_bits;
shift = (y << upsample_left) & 0xFF;
for (r = 0; r < bh; ++r, ++base) {
if (base < bw + bh - 1) {
for (r = 0; r < bh; ++r, base += base_inc) {
if (base < max_base_y) {
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 < bh; ++r) dst[r * stride + c] = left[bw + bh - 1];
for (; r < bh; ++r) dst[r * stride + c] = left[max_base_y];
break;
}
}
@ -971,6 +1007,9 @@ static void dr_predictor(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size,
#if CONFIG_INTRA_INTERP
INTRA_FILTER filter_type,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
int upsample_above, int upsample_left,
#endif
int angle) {
const int dx = get_dx(angle);
const int dy = get_dy(angle);
@ -983,18 +1022,27 @@ static void dr_predictor(uint8_t *dst, ptrdiff_t stride, TX_SIZE tx_size,
#if CONFIG_INTRA_INTERP
filter_type,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
upsample_above,
#endif
dx, dy);
} else if (angle > 90 && angle < 180) {
dr_prediction_z2(dst, stride, bw, bh, above, left,
#if CONFIG_INTRA_INTERP
filter_type,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
upsample_above, upsample_left,
#endif
dx, dy);
} else if (angle > 180 && angle < 270) {
dr_prediction_z3(dst, stride, bw, bh, above, left,
#if CONFIG_INTRA_INTERP
filter_type,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
upsample_left,
#endif
dx, dy);
} else if (angle == 90) {
pred[V_PRED][tx_size](dst, stride, above, left);
@ -1042,6 +1090,9 @@ static void highbd_dr_prediction_z1(uint16_t *dst, ptrdiff_t stride, int bw,
#if CONFIG_INTRA_INTERP
INTRA_FILTER filter_type,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
int upsample_above,
#endif
int dx, int dy, int bd) {
int r, c, x, base, shift, val;
@ -1050,22 +1101,27 @@ static void highbd_dr_prediction_z1(uint16_t *dst, ptrdiff_t stride, int bw,
assert(dy == 1);
assert(dx > 0);
#if !CONFIG_INTRA_EDGE_UPSAMPLE
const int upsample_above = 0;
#endif
const int max_base_x = ((bw + bh) - 1) << upsample_above;
const int frac_bits = 8 - upsample_above;
const int base_inc = 1 << upsample_above;
x = dx;
for (r = 0; r < bh; ++r, dst += stride, x += dx) {
base = x >> 8;
shift = x & 0xFF;
base = x >> frac_bits;
shift = (x << upsample_above) & 0xFF;
if (base >= bw + bh - 1) {
int i;
for (i = r; i < bh; ++i) {
aom_memset16(dst, above[bw + bh - 1], bw);
if (base >= max_base_x) {
for (int i = r; i < bh; ++i) {
aom_memset16(dst, above[max_base_x], bw);
dst += stride;
}
return;
}
for (c = 0; c < bw; ++c, ++base) {
if (base < bw + bh - 1) {
for (c = 0; c < bw; ++c, base += base_inc) {
if (base < max_base_x) {
#if CONFIG_INTRA_INTERP
val = highbd_intra_subpel_interp(base, shift, above, 0, bw + bh - 1,
filter_type);
@ -1075,7 +1131,7 @@ static void highbd_dr_prediction_z1(uint16_t *dst, ptrdiff_t stride, int bw,
#endif // CONFIG_INTRA_INTERP
dst[c] = clip_pixel_highbd(val, bd);
} else {
dst[c] = above[bw + bh - 1];
dst[c] = above[max_base_x];
}
}
}
@ -1088,19 +1144,29 @@ static void highbd_dr_prediction_z2(uint16_t *dst, ptrdiff_t stride, int bw,
#if CONFIG_INTRA_INTERP
INTRA_FILTER filter_type,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
int upsample_above, int upsample_left,
#endif
int dx, int dy, int bd) {
int r, c, x, y, shift, val, base;
assert(dx > 0);
assert(dy > 0);
#if !CONFIG_INTRA_EDGE_UPSAMPLE
const int upsample_above = 0;
const int upsample_left = 0;
#endif
const int min_base_x = -(1 << upsample_above);
const int frac_bits_x = 8 - upsample_above;
const int frac_bits_y = 8 - upsample_left;
for (r = 0; r < bh; ++r) {
for (c = 0; c < bw; ++c) {
y = r + 1;
x = (c << 8) - y * dx;
base = x >> 8;
if (base >= -1) {
shift = x & 0xFF;
base = x >> frac_bits_x;
if (base >= min_base_x) {
shift = (x << upsample_above) & 0xFF;
#if CONFIG_INTRA_INTERP
val = highbd_intra_subpel_interp(base, shift, above, -1, bw - 1,
filter_type);
@ -1111,8 +1177,8 @@ static void highbd_dr_prediction_z2(uint16_t *dst, ptrdiff_t stride, int bw,
} else {
x = c + 1;
y = (r << 8) - x * dy;
base = y >> 8;
shift = y & 0xFF;
base = y >> frac_bits_y;
shift = (y << upsample_left) & 0xFF;
#if CONFIG_INTRA_INTERP
val = highbd_intra_subpel_interp(base, shift, left, -1, bh - 1,
filter_type);
@ -1134,6 +1200,9 @@ static void highbd_dr_prediction_z3(uint16_t *dst, ptrdiff_t stride, int bw,
#if CONFIG_INTRA_INTERP
INTRA_FILTER filter_type,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
int upsample_left,
#endif
int dx, int dy, int bd) {
int r, c, y, base, shift, val;
@ -1142,13 +1211,19 @@ static void highbd_dr_prediction_z3(uint16_t *dst, ptrdiff_t stride, int bw,
assert(dx == 1);
assert(dy > 0);
#if !CONFIG_INTRA_EDGE_UPSAMPLE
const int upsample_left = 0;
#endif
const int max_base_y = (bw + bh - 1) << upsample_left;
const int frac_bits = 8 - upsample_left;
const int base_inc = 1 << upsample_left;
y = dy;
for (c = 0; c < bw; ++c, y += dy) {
base = y >> 8;
shift = y & 0xFF;
base = y >> frac_bits;
shift = (y << upsample_left) & 0xFF;
for (r = 0; r < bh; ++r, ++base) {
if (base < bw + bh - 1) {
for (r = 0; r < bh; ++r, base += base_inc) {
if (base < max_base_y) {
#if CONFIG_INTRA_INTERP
val = highbd_intra_subpel_interp(base, shift, left, 0, bw + bh - 1,
filter_type);
@ -1158,7 +1233,7 @@ static void highbd_dr_prediction_z3(uint16_t *dst, ptrdiff_t stride, int bw,
#endif // CONFIG_INTRA_INTERP
dst[r * stride + c] = clip_pixel_highbd(val, bd);
} else {
for (; r < bh; ++r) dst[r * stride + c] = left[bw + bh - 1];
for (; r < bh; ++r) dst[r * stride + c] = left[max_base_y];
break;
}
}
@ -1171,6 +1246,9 @@ static void highbd_dr_predictor(uint16_t *dst, ptrdiff_t stride,
#if CONFIG_INTRA_INTERP
INTRA_FILTER filter,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
int upsample_above, int upsample_left,
#endif
int angle, int bd) {
const int dx = get_dx(angle);
const int dy = get_dy(angle);
@ -1183,18 +1261,27 @@ static void highbd_dr_predictor(uint16_t *dst, ptrdiff_t stride,
#if CONFIG_INTRA_INTERP
filter,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
upsample_above,
#endif
dx, dy, bd);
} else if (angle > 90 && angle < 180) {
highbd_dr_prediction_z2(dst, stride, bw, bh, above, left,
#if CONFIG_INTRA_INTERP
filter,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
upsample_above, upsample_left,
#endif
dx, dy, bd);
} else if (angle > 180 && angle < 270) {
highbd_dr_prediction_z3(dst, stride, bw, bh, above, left,
#if CONFIG_INTRA_INTERP
filter,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
upsample_left,
#endif
dx, dy, bd);
} else if (angle == 90) {
pred_high[V_PRED][tx_size](dst, stride, above, left, bd);
@ -1851,7 +1938,13 @@ static int intra_edge_filter_strength(int bsz, int delta) {
const int d = abs(delta);
int strength = 0;
if (bsz == 8) {
if (bsz == 4) {
if (d < 56) {
strength = 0;
} else if (d < 90) {
strength = 1;
}
} else if (bsz == 8) {
if (d < 8) {
strength = 0;
} else if (d < 32) {
@ -1881,7 +1974,7 @@ static int intra_edge_filter_strength(int bsz, int delta) {
static void filter_intra_edge(uint8_t *p, int sz, int strength) {
if (!strength) return;
const int kernel[3][5] = {
const int kernel[INTRA_EDGE_FILT][INTRA_EDGE_TAPS] = {
{ 0, 4, 8, 4, 0 }, { 0, 5, 6, 5, 0 }, { 2, 4, 4, 4, 2 }
};
const int filt = strength - 1;
@ -1890,7 +1983,7 @@ static void filter_intra_edge(uint8_t *p, int sz, int strength) {
memcpy(edge, p, sz * sizeof(*p));
for (int i = 1; i < sz - 1; i++) {
int s = 0;
for (int j = 0; j < 5; j++) {
for (int j = 0; j < INTRA_EDGE_TAPS; j++) {
int k = i - 2 + j;
k = (k < 0) ? 0 : k;
k = (k > sz - 1) ? sz - 1 : k;
@ -1905,7 +1998,7 @@ static void filter_intra_edge(uint8_t *p, int sz, int strength) {
static void filter_intra_edge_high(uint16_t *p, int sz, int strength) {
if (!strength) return;
const int kernel[3][5] = {
const int kernel[INTRA_EDGE_FILT][INTRA_EDGE_TAPS] = {
{ 0, 4, 8, 4, 0 }, { 0, 5, 6, 5, 0 }, { 2, 4, 4, 4, 2 }
};
const int filt = strength - 1;
@ -1914,7 +2007,7 @@ static void filter_intra_edge_high(uint16_t *p, int sz, int strength) {
memcpy(edge, p, sz * sizeof(*p));
for (int i = 1; i < sz - 1; i++) {
int s = 0;
for (int j = 0; j < 5; j++) {
for (int j = 0; j < INTRA_EDGE_TAPS; j++) {
int k = i - 2 + j;
k = (k < 0) ? 0 : k;
k = (k > sz - 1) ? sz - 1 : k;
@ -1924,9 +2017,66 @@ static void filter_intra_edge_high(uint16_t *p, int sz, int strength) {
p[i] = s;
}
}
#endif // CONFIG_INTRA_EDGE
#endif // CONFIG_HIGHBITDEPTH
#if CONFIG_INTRA_EDGE_UPSAMPLE
static int use_intra_edge_upsample(int bsz, int delta) {
const int d = abs(delta);
return (bsz == 4 && d < 56);
}
static void upsample_intra_edge(uint8_t *p, int sz) {
// interpolate half-sample positions
assert(sz <= MAX_UPSAMPLE_SZ);
uint8_t in[MAX_UPSAMPLE_SZ + 3];
// copy p[-1..(sz-1)] and extend first and last samples
in[0] = p[-1];
in[1] = p[-1];
for (int i = 0; i < sz; i++) {
in[i + 2] = p[i];
}
in[sz + 2] = p[sz - 1];
// interpolate half-sample edge positions
p[-2] = in[0];
for (int i = 0; i < sz; i++) {
int s = -in[i] + (9 * in[i + 1]) + (9 * in[i + 2]) - in[i + 3];
s = clip_pixel((s + 8) >> 4);
p[2 * i - 1] = s;
p[2 * i] = in[i + 2];
}
}
#if CONFIG_HIGHBITDEPTH
static void upsample_intra_edge_high(uint16_t *p, int sz, int bd) {
// interpolate half-sample positions
assert(sz <= MAX_UPSAMPLE_SZ);
uint16_t in[MAX_UPSAMPLE_SZ + 3];
// copy p[-1..(sz-1)] and extend first and last samples
in[0] = p[-1];
in[1] = p[-1];
for (int i = 0; i < sz; i++) {
in[i + 2] = p[i];
}
in[sz + 2] = p[sz - 1];
// interpolate half-sample edge positions
p[-2] = in[0];
for (int i = 0; i < sz; i++) {
int s = -in[i] + (9 * in[i + 1]) + (9 * in[i + 2]) - in[i + 3];
s = (s + 8) >> 4;
s = clip_pixel_highbd(s, bd);
p[2 * i - 1] = s;
p[2 * i] = in[i + 2];
}
}
#endif // CONFIG_HIGHBITDEPTH
#endif // CONFIG_INTRA_EDGE_UPSAMPLE
#endif // CONFIG_INTRA_EDGE
#if CONFIG_HIGHBITDEPTH
static void build_intra_predictors_high(
const MACROBLOCKD *xd, const uint8_t *ref8, int ref_stride, uint8_t *dst8,
@ -2107,20 +2257,34 @@ static void build_intra_predictors_high(
}
#if CONFIG_EXT_INTRA && CONFIG_INTRA_EDGE
#if CONFIG_INTRA_EDGE_UPSAMPLE
const int upsample_above = use_intra_edge_upsample(txwpx, p_angle - 90);
const int upsample_left = use_intra_edge_upsample(txhpx, p_angle - 180);
#endif
const int need_right = p_angle < 90;
const int need_bottom = p_angle > 180;
if (is_dr_mode && p_angle != 90 && p_angle != 180) {
const int ab_le = need_above_left ? 1 : 0;
if (need_above && n_top_px > 0) {
const int strength = intra_edge_filter_strength(txwpx, p_angle - 90);
const int need_right = p_angle < 90;
const int n_px = n_top_px + ab_le + (need_right ? n_topright_px : 0);
filter_intra_edge_high(above_row - ab_le, n_px, strength);
}
if (need_left && n_left_px > 0) {
const int strength = intra_edge_filter_strength(txhpx, p_angle - 180);
const int need_bottom = p_angle > 180;
const int n_px = n_left_px + ab_le + (need_bottom ? n_bottomleft_px : 0);
filter_intra_edge_high(left_col - ab_le, n_px, strength);
}
#if CONFIG_INTRA_EDGE_UPSAMPLE
if (upsample_above) {
const int n_px = txwpx + (need_right ? txhpx : 0);
upsample_intra_edge_high(above_row, n_px, xd->bd);
}
if (upsample_left) {
const int n_px = txhpx + (need_bottom ? txwpx : 0);
upsample_intra_edge_high(left_col, n_px, xd->bd);
}
#endif
}
#endif
@ -2144,6 +2308,9 @@ static void build_intra_predictors_high(
#if CONFIG_INTRA_INTERP
filter,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
upsample_above, upsample_left,
#endif
p_angle, xd->bd);
return;
}
@ -2337,20 +2504,34 @@ static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref,
}
#if CONFIG_EXT_INTRA && CONFIG_INTRA_EDGE
#if CONFIG_INTRA_EDGE_UPSAMPLE
const int upsample_above = use_intra_edge_upsample(txwpx, p_angle - 90);
const int upsample_left = use_intra_edge_upsample(txhpx, p_angle - 180);
#endif
const int need_right = p_angle < 90;
const int need_bottom = p_angle > 180;
if (is_dr_mode && p_angle != 90 && p_angle != 180) {
const int ab_le = need_above_left ? 1 : 0;
if (need_above && n_top_px > 0) {
const int strength = intra_edge_filter_strength(txwpx, p_angle - 90);
const int need_right = p_angle < 90;
const int n_px = n_top_px + ab_le + (need_right ? n_topright_px : 0);
filter_intra_edge(above_row - ab_le, n_px, strength);
}
if (need_left && n_left_px > 0) {
const int strength = intra_edge_filter_strength(txhpx, p_angle - 180);
const int need_bottom = p_angle > 180;
const int n_px = n_left_px + ab_le + (need_bottom ? n_bottomleft_px : 0);
filter_intra_edge(left_col - ab_le, n_px, strength);
}
#if CONFIG_INTRA_EDGE_UPSAMPLE
if (upsample_above) {
const int n_px = txwpx + (need_right ? txhpx : 0);
upsample_intra_edge(above_row, n_px);
}
if (upsample_left) {
const int n_px = txhpx + (need_bottom ? txwpx : 0);
upsample_intra_edge(left_col, n_px);
}
#endif
}
#endif
@ -2373,6 +2554,9 @@ static void build_intra_predictors(const MACROBLOCKD *xd, const uint8_t *ref,
#if CONFIG_INTRA_INTERP
filter,
#endif // CONFIG_INTRA_INTERP
#if CONFIG_INTRA_EDGE_UPSAMPLE
upsample_above, upsample_left,
#endif
p_angle);
return;
}

Просмотреть файл

@ -73,10 +73,27 @@ static const INTERINTRA_MODE intra_to_interintra_mode[INTRA_MODES] = {
#define FILTER_INTRA_PREC_BITS 10
#endif // CONFIG_FILTER_INTRA
#define CONFIG_INTRA_EDGE_UPSAMPLE CONFIG_INTRA_EDGE
#define CONFIG_USE_ANGLE_DELTA_SUB8X8 0
#if CONFIG_EXT_INTRA
static INLINE int av1_is_directional_mode(PREDICTION_MODE mode,
BLOCK_SIZE bsize) {
#if CONFIG_INTRA_EDGE_UPSAMPLE
(void)bsize;
return mode >= V_PRED && mode <= D63_PRED;
#else
return mode >= V_PRED && mode <= D63_PRED && bsize >= BLOCK_8X8;
#endif
}
static INLINE int av1_use_angle_delta(BLOCK_SIZE bsize) {
(void)bsize;
#if CONFIG_USE_ANGLE_DELTA_SUB8X8
return 1;
#else
return bsize >= BLOCK_8X8;
#endif
}
#endif // CONFIG_EXT_INTRA

Просмотреть файл

@ -866,7 +866,11 @@ static void read_intra_angle_info(AV1_COMMON *const cm, MACROBLOCKD *const xd,
#endif // CONFIG_INTRA_INTERP
(void)cm;
if (bsize < BLOCK_8X8) return;
mbmi->angle_delta[0] = 0;
mbmi->angle_delta[1] = 0;
if (!av1_use_angle_delta(bsize)) return;
if (av1_is_directional_mode(mbmi->mode, bsize)) {
mbmi->angle_delta[0] =
@ -1160,6 +1164,9 @@ static void read_intra_frame_mode_info(AV1_COMMON *const cm,
#endif // CONFIG_CFL
#if CONFIG_CB4X4
} else {
// Avoid decoding angle_info if there is is no chroma prediction
mbmi->uv_mode = DC_PRED;
}
#endif

Просмотреть файл

@ -1451,7 +1451,7 @@ static void write_intra_angle_info(const MACROBLOCKD *xd,
#endif // CONFIG_INTRA_INTERP
(void)ec_ctx;
if (bsize < BLOCK_8X8) return;
if (!av1_use_angle_delta(bsize)) return;
if (av1_is_directional_mode(mbmi->mode, bsize)) {
write_uniform(w, 2 * MAX_ANGLE_DELTA + 1,

Просмотреть файл

@ -2458,7 +2458,8 @@ static int64_t intra_model_yrd(const AV1_COMP *const cpi, MACROBLOCK *const x,
model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &this_rd_stats.rate,
&this_rd_stats.dist, &this_rd_stats.skip, &temp_sse);
#if CONFIG_EXT_INTRA
if (av1_is_directional_mode(mbmi->mode, bsize)) {
if (av1_is_directional_mode(mbmi->mode, bsize) &&
av1_use_angle_delta(bsize)) {
mode_cost += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
}
@ -3579,8 +3580,8 @@ static void angle_estimation(const uint8_t *src, int src_stride, int rows,
uint8_t *directional_mode_skip_mask) {
memset(directional_mode_skip_mask, 0,
INTRA_MODES * sizeof(*directional_mode_skip_mask));
// Sub-8x8 blocks do not use extra directions.
if (bsize < BLOCK_8X8) return;
// Check if angle_delta is used
if (!av1_use_angle_delta(bsize)) return;
uint64_t hist[DIRECTIONAL_MODES];
memset(hist, 0, DIRECTIONAL_MODES * sizeof(hist[0]));
src += src_stride;
@ -3634,8 +3635,8 @@ static void highbd_angle_estimation(const uint8_t *src8, int src_stride,
uint8_t *directional_mode_skip_mask) {
memset(directional_mode_skip_mask, 0,
INTRA_MODES * sizeof(*directional_mode_skip_mask));
// Sub-8x8 blocks do not use extra directions.
if (bsize < BLOCK_8X8) return;
// Check if angle_delta is used
if (!av1_use_angle_delta(bsize)) return;
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
uint64_t hist[DIRECTIONAL_MODES];
memset(hist, 0, DIRECTIONAL_MODES * sizeof(hist[0]));
@ -3791,7 +3792,7 @@ static int64_t rd_pick_intra_sby_mode(const AV1_COMP *const cpi, MACROBLOCK *x,
#if CONFIG_EXT_INTRA
is_directional_mode = av1_is_directional_mode(mbmi->mode, bsize);
if (is_directional_mode && directional_mode_skip_mask[mbmi->mode]) continue;
if (is_directional_mode) {
if (is_directional_mode && av1_use_angle_delta(bsize)) {
this_rd_stats.rate = INT_MAX;
rd_pick_intra_angle_sby(cpi, x, &this_rate, &this_rd_stats, bsize,
bmode_costs[mbmi->mode], best_rd, &best_model_rd);
@ -3837,8 +3838,10 @@ static int64_t rd_pick_intra_sby_mode(const AV1_COMP *const cpi, MACROBLOCK *x,
this_rate +=
cpi->intra_filter_cost[intra_filter_ctx][mbmi->intra_filter];
#endif // CONFIG_INTRA_INTERP
this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
if (av1_use_angle_delta(bsize)) {
this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
}
}
#endif // CONFIG_EXT_INTRA
this_rd = RDCOST(x->rdmult, this_rate, this_distortion);
@ -4921,7 +4924,7 @@ static int64_t rd_pick_intra_sbuv_mode(const AV1_COMP *const cpi, MACROBLOCK *x,
mbmi->uv_mode = mode;
#if CONFIG_EXT_INTRA
mbmi->angle_delta[1] = 0;
if (is_directional_mode) {
if (is_directional_mode && av1_use_angle_delta(mbmi->sb_type)) {
const int rate_overhead = cpi->intra_uv_mode_cost[mbmi->mode][mode] +
write_uniform_cost(2 * MAX_ANGLE_DELTA + 1, 0);
if (!rd_pick_intra_angle_sbuv(cpi, x, bsize, rate_overhead, best_rd,
@ -4942,7 +4945,7 @@ static int64_t rd_pick_intra_sbuv_mode(const AV1_COMP *const cpi, MACROBLOCK *x,
tokenonly_rd_stats.rate + cpi->intra_uv_mode_cost[mbmi->mode][mode];
#if CONFIG_EXT_INTRA
if (is_directional_mode) {
if (is_directional_mode && av1_use_angle_delta(mbmi->sb_type)) {
this_rate += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
}
@ -9013,7 +9016,8 @@ static void pick_filter_intra_interframe(
rate2 += write_uniform_cost(
FILTER_INTRA_MODES, mbmi->filter_intra_mode_info.filter_intra_mode[0]);
#if CONFIG_EXT_INTRA
if (av1_is_directional_mode(mbmi->uv_mode, bsize)) {
if (av1_is_directional_mode(mbmi->uv_mode, bsize) &&
av1_use_angle_delta(bsize)) {
rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
}
@ -9760,7 +9764,7 @@ void av1_rd_pick_inter_mode_sb(const AV1_COMP *cpi, TileDataEnc *tile_data,
struct macroblockd_plane *const pd = &xd->plane[1];
#if CONFIG_EXT_INTRA
is_directional_mode = av1_is_directional_mode(mbmi->mode, bsize);
if (is_directional_mode) {
if (is_directional_mode && av1_use_angle_delta(bsize)) {
int rate_dummy;
int64_t model_rd = INT64_MAX;
if (!angle_stats_ready) {
@ -9873,10 +9877,13 @@ void av1_rd_pick_inter_mode_sb(const AV1_COMP *cpi, TileDataEnc *tile_data,
if (av1_is_intra_filter_switchable(p_angle))
rate2 += cpi->intra_filter_cost[intra_filter_ctx][mbmi->intra_filter];
#endif // CONFIG_INTRA_INTERP
rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
if (av1_use_angle_delta(bsize)) {
rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
MAX_ANGLE_DELTA + mbmi->angle_delta[0]);
}
}
if (mbmi->uv_mode != DC_PRED && mbmi->uv_mode != TM_PRED) {
if (av1_is_directional_mode(mbmi->uv_mode, bsize) &&
av1_use_angle_delta(bsize)) {
rate2 += write_uniform_cost(2 * MAX_ANGLE_DELTA + 1,
MAX_ANGLE_DELTA + mbmi->angle_delta[1]);
}