* 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"
}
#endif
+#if CONFIG_EXT_INTRA
+#define PI 3.14159265
+#define FILTER_INTRA_PREC_BITS 10
+#define FILTER_INTRA_ROUND_VAL 511
+
+#if CONFIG_MISC_FIXES
+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
+};
+#else
+static const uint8_t ext_intra_extend_modes[FILTER_INTRA_MODES] = {
+ NEED_LEFT | NEED_ABOVERIGHT, // FILTER_DC
+ NEED_LEFT | NEED_ABOVERIGHT, // FILTER_V
+ NEED_LEFT | NEED_ABOVERIGHT, // FILTER_H
+ NEED_LEFT | NEED_ABOVERIGHT, // FILTER_D45
+ NEED_LEFT | NEED_ABOVERIGHT, // FILTER_D135
+ NEED_LEFT | NEED_ABOVERIGHT, // FILTER_D117
+ NEED_LEFT | NEED_ABOVERIGHT, // FILTER_D153
+ NEED_LEFT | NEED_ABOVERIGHT, // FILTER_D207
+ NEED_LEFT | NEED_ABOVERIGHT, // FILTER_D63
+ NEED_LEFT | NEED_ABOVERIGHT, // FILTER_TM
+};
+#endif // CONFIG_MISC_FIXES
+
+// 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 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 * 256 - y * dx;
+ base = x >> 8;
+ shift = x - base * 256;
+ if (base < 2 * bs - 1) {
+ val =
+ (above[base] * (256 - shift) + above[base + 1] * shift + 128) >> 8;
+ dst[c] = clip_pixel(val);
+ } else {
+ dst[c] = above[2 * bs - 1];
+ }
+ }
+ dst += stride;
+ }
+}
+
+// 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;
+
+ 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;
+ }
+ } else {
+ x = c + 1;
+ y = r * 256 - x * dy;
+ base = y >> 8;
+ if (base >= 0) {
+ val1 = left[base];
+ val2 = left[base + 1];
+ shift = y - base * 256;
+ } else {
+ val1 = val2 = left[0];
+ shift = 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 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;
+ base = y >> 8;
+ shift = y - base * 256;
+ if (base < bs - 1) {
+ val =
+ (left[base] * (256 - shift) + left[base + 1] * shift + 128) >> 8;
+ dst[c] = clip_pixel(val);
+ } else {
+ dst[c] = left[bs - 1];
+ }
+ }
+ dst += stride;
+ }
+}
+
+static INLINE void v_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
+ const uint8_t *above, const uint8_t *left) {
+ int r;
+ (void) left;
+
+ for (r = 0; r < bs; r++) {
+ memcpy(dst, above, bs);
+ dst += stride;
+ }
+}
+
+static INLINE void h_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
+ const uint8_t *above, const uint8_t *left) {
+ int r;
+ (void) above;
+
+ for (r = 0; r < bs; r++) {
+ memset(dst, left[r], bs);
+ dst += stride;
+ }
+}
+
+static void dr_predictor(uint8_t *dst, ptrdiff_t stride, int bs,
+ const uint8_t *above, const uint8_t *left, int angle) {
+ 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;
+ dr_prediction_z1(dst, stride, bs, above, left, dx, dy);
+ } 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);
+ } else if (angle > 180 && angle < 270) {
+ dx = 1;
+ dy = -((int)(256 * t));
+ dr_prediction_z3(dst, stride, bs, above, left, dx, dy);
+ } else if (angle == 90) {
+ v_predictor(dst, stride, bs, above, left);
+ } else if (angle == 180) {
+ h_predictor(dst, stride, bs, 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
+// 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 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 * 256 - y * dx;
+ base = x >> 8;
+ shift = x - base * 256;
+ if (base < 2 * bs - 1) {
+ val =
+ (above[base] * (256 - shift) + above[base + 1] * shift + 128) >> 8;
+ 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) {
+ int r, c, x, y, val1, val2, 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;
+ }
+ } else {
+ x = c + 1;
+ y = r * 256 - x * dy;
+ base = y >> 8;
+ if (base >= 0) {
+ val1 = left[base];
+ val2 = left[base + 1];
+ shift = y - base * 256;
+ } else {
+ val1 = val2 = left[0];
+ shift = 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 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;
+ base = y >> 8;
+ shift = y - base * 256;
+ if (base < bs - 1) {
+ val =
+ (left[base] * (256 - shift) + left[base + 1] * shift + 128) >> 8;
+ dst[c] = clip_pixel_highbd(val, bd);
+ } else {
+ dst[c] = left[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) {
+ 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);
+ } 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);
+ } else if (angle > 180 && angle < 270) {
+ dx = 1;
+ dy = -((int)(256 * t));
+ highbd_dr_prediction_z3(dst, stride, bs, above, left, dx, dy, bd);
+ } 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,
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;
+ int need_aboveright = extend_modes[mode] & NEED_ABOVERIGHT;
#if CONFIG_MISC_FIXES
const uint16_t *above_ref = ref - ref_stride;
#else
// 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];
+ const int angle =
+ prediction_angle_map(ext_intra_mode_info->ext_intra_angle[plane != 0]);
+
+ 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];
+ if (ext_intra_mode <= FILTER_TM_PRED) {
+ need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT;
+ need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE;
+ need_aboveright =
+ ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVERIGHT;
+ } else {
+ assert(angle > 0 && angle < 270);
+#if CONFIG_MISC_FIXES
+ if (angle <= 90)
+ need_above = 1, need_left = 0;
+ else if (angle < 180)
+ need_above = 1, need_left = 1;
+ else
+ need_above = 0, need_left = 1;
+#else
+ if (angle < 90)
+ need_above = 0, need_aboveright = 1, need_left = 0;
+ else if (angle == 90)
+ need_above = 1, need_aboveright = 0, need_left = 0;
+ else if (angle < 180)
+ need_above = 1, need_aboveright = 0, need_left = 1;
+ else
+ need_above = 0, need_aboveright = 0, need_left = 1;
+#endif // CONFIG_MISC_FIXES
+ }
+ }
+#endif // CONFIG_EXT_INTRA
+
#if CONFIG_MISC_FIXES
(void) x;
(void) y;
(void) plane;
// NEED_LEFT
- if (extend_modes[mode] & NEED_LEFT) {
+ if (need_left) {
+#if CONFIG_EXT_INTRA
+ int need_bottom;
+ if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
+ if (ext_intra_mode <= FILTER_TM_PRED)
+ need_bottom = 0;
+ else
+ need_bottom = 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++)
}
// NEED_ABOVE
- if (extend_modes[mode] & NEED_ABOVE) {
+ if (need_above) {
+#if CONFIG_EXT_INTRA
+ int need_right;
+ if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
+ if (ext_intra_mode <= FILTER_TM_PRED)
+ need_right = 1;
+ else
+ need_right = 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 (extend_modes[mode] & NEED_ABOVELEFT) {
+ (void)need_aboveright;
+#if CONFIG_EXT_INTRA
+ if (ext_intra_mode_info->use_ext_intra_mode[plane != 0] ||
+ (extend_modes[mode] & NEED_ABOVELEFT)) {
+ 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
#else
// Get current frame pointer, width and height.
if (plane == 0) {
x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
- // left
- if (left_available) {
- if (xd->mb_to_bottom_edge < 0) {
- /* slower path if the block needs border extension */
- if (y0 + bs <= frame_height) {
- for (i = 0; i < bs; ++i)
- left_col[i] = ref[i * ref_stride - 1];
+ // NEED_LEFT
+ if (need_left) {
+ if (left_available) {
+ if (xd->mb_to_bottom_edge < 0) {
+ /* slower path if the block needs border extension */
+ if (y0 + bs <= frame_height) {
+ for (i = 0; i < bs; ++i)
+ left_col[i] = ref[i * ref_stride - 1];
+ } else {
+ const int extend_bottom = frame_height - y0;
+ for (i = 0; i < extend_bottom; ++i)
+ left_col[i] = ref[i * ref_stride - 1];
+ for (; i < bs; ++i)
+ left_col[i] = ref[(extend_bottom - 1) * ref_stride - 1];
+ }
} else {
- const int extend_bottom = frame_height - y0;
- for (i = 0; i < extend_bottom; ++i)
+ /* faster path if the block does not need extension */
+ for (i = 0; i < bs; ++i)
left_col[i] = ref[i * ref_stride - 1];
- for (; i < bs; ++i)
- left_col[i] = ref[(extend_bottom - 1) * ref_stride - 1];
}
} else {
- /* faster path if the block does not need extension */
- for (i = 0; i < bs; ++i)
- left_col[i] = ref[i * ref_stride - 1];
+ // TODO(Peter): this value should probably change for high bitdepth
+ vpx_memset16(left_col, base + 1, bs);
}
- } else {
- // TODO(Peter): this value should probably change for high bitdepth
- vpx_memset16(left_col, base + 1, bs);
- }
-
- // TODO(hkuang) do not extend 2*bs pixels for all modes.
- // above
- if (up_available) {
- const uint16_t *above_ref = ref - ref_stride;
- if (xd->mb_to_right_edge < 0) {
- /* slower path if the block needs border extension */
- if (x0 + 2 * bs <= frame_width) {
- if (right_available && bs == 4) {
- memcpy(above_row, above_ref, 2 * bs * sizeof(above_row[0]));
+ }
+
+ // NEED_ABOVE
+ if (need_above) {
+ if (up_available) {
+ const uint16_t *above_ref = ref - ref_stride;
+ if (xd->mb_to_right_edge < 0) {
+ /* slower path if the block needs border extension */
+ if (x0 + bs <= frame_width) {
+ memcpy(above_row, above_ref, bs * sizeof(above_row[0]));
+ } else if (x0 <= frame_width) {
+ const int r = frame_width - x0;
+ memcpy(above_row, above_ref, r * sizeof(above_row[0]));
+ vpx_memset16(above_row + r, above_row[r - 1], x0 + bs - frame_width);
+ }
+ } else {
+ /* faster path if the block does not need extension */
+ if (bs == 4 && right_available && left_available) {
+ const_above_row = above_ref;
} else {
memcpy(above_row, above_ref, bs * sizeof(above_row[0]));
- vpx_memset16(above_row + bs, above_row[bs - 1], bs);
}
- } else if (x0 + bs <= frame_width) {
- const int r = frame_width - x0;
- if (right_available && bs == 4) {
+ }
+ above_row[-1] = left_available ? above_ref[-1] : (base + 1);
+ } else {
+ vpx_memset16(above_row, base - 1, bs);
+ above_row[-1] = base - 1;
+ }
+ }
+
+ // NEED_ABOVERIGHT
+ if (need_aboveright) {
+ if (up_available) {
+ const uint16_t *above_ref = ref - ref_stride;
+ if (xd->mb_to_right_edge < 0) {
+ /* slower path if the block needs border extension */
+ if (x0 + 2 * bs <= frame_width) {
+ if (right_available && bs == 4) {
+ memcpy(above_row, above_ref, 2 * bs * sizeof(above_row[0]));
+ } else {
+ memcpy(above_row, above_ref, bs * sizeof(above_row[0]));
+ vpx_memset16(above_row + bs, above_row[bs - 1], bs);
+ }
+ } else if (x0 + bs <= frame_width) {
+ const int r = frame_width - x0;
+ if (right_available && bs == 4) {
+ memcpy(above_row, above_ref, r * sizeof(above_row[0]));
+ vpx_memset16(above_row + r, above_row[r - 1],
+ x0 + 2 * bs - frame_width);
+ } else {
+ memcpy(above_row, above_ref, bs * sizeof(above_row[0]));
+ vpx_memset16(above_row + bs, above_row[bs - 1], bs);
+ }
+ } else if (x0 <= frame_width) {
+ const int r = frame_width - x0;
memcpy(above_row, above_ref, r * sizeof(above_row[0]));
vpx_memset16(above_row + r, above_row[r - 1],
x0 + 2 * bs - frame_width);
+ }
+ // TODO(Peter) this value should probably change for high bitdepth
+ above_row[-1] = left_available ? above_ref[-1] : (base + 1);
+ } else {
+ /* faster path if the block does not need extension */
+ if (bs == 4 && right_available && left_available) {
+ const_above_row = above_ref;
} else {
memcpy(above_row, above_ref, bs * sizeof(above_row[0]));
- vpx_memset16(above_row + bs, above_row[bs - 1], bs);
+ if (bs == 4 && right_available)
+ memcpy(above_row + bs, above_ref + bs, bs * sizeof(above_row[0]));
+ else
+ vpx_memset16(above_row + bs, above_row[bs - 1], bs);
+ // TODO(Peter): this value should probably change for high bitdepth
+ above_row[-1] = left_available ? above_ref[-1] : (base + 1);
}
- } else if (x0 <= frame_width) {
- const int r = frame_width - x0;
- memcpy(above_row, above_ref, r * sizeof(above_row[0]));
- vpx_memset16(above_row + r, above_row[r - 1],
- x0 + 2 * bs - frame_width);
}
- // TODO(Peter) this value should probably change for high bitdepth
- above_row[-1] = left_available ? above_ref[-1] : (base+1);
} else {
- /* faster path if the block does not need extension */
- if (bs == 4 && right_available && left_available) {
- const_above_row = above_ref;
- } else {
- memcpy(above_row, above_ref, bs * sizeof(above_row[0]));
- if (bs == 4 && right_available)
- memcpy(above_row + bs, above_ref + bs, bs * sizeof(above_row[0]));
- else
- vpx_memset16(above_row + bs, above_row[bs - 1], bs);
- // TODO(Peter): this value should probably change for high bitdepth
- above_row[-1] = left_available ? above_ref[-1] : (base+1);
- }
+ vpx_memset16(above_row, base - 1, bs * 2);
+ // TODO(Peter): this value should probably change for high bitdepth
+ above_row[-1] = base - 1;
}
- } else {
- vpx_memset16(above_row, base - 1, bs * 2);
- // TODO(Peter): this value should probably change for high bitdepth
- above_row[-1] = base - 1;
}
#endif
+#if CONFIG_EXT_INTRA
+ if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
+ if (ext_intra_mode <= FILTER_TM_PRED)
+ highbd_filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs,
+ const_above_row, left_col,
+ bd);
+ else
+ highbd_dr_predictor(dst, dst_stride, bs, const_above_row, left_col,
+ angle, bd);
+ return;
+ }
+#endif // CONFIG_EXT_INTRA
+
// predict
if (mode == DC_PRED) {
#if CONFIG_MISC_FIXES
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;
+ int need_aboveright = extend_modes[mode] & NEED_ABOVERIGHT;
+#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];
+ const int angle =
+ prediction_angle_map(ext_intra_mode_info->ext_intra_angle[plane != 0]);
+
+ 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];
+ if (ext_intra_mode <= FILTER_TM_PRED) {
+ need_left = ext_intra_extend_modes[ext_intra_mode] & NEED_LEFT;
+ need_above = ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVE;
+ need_aboveright =
+ ext_intra_extend_modes[ext_intra_mode] & NEED_ABOVERIGHT;
+ } else {
+ assert(angle > 0 && angle < 270);
+#if CONFIG_MISC_FIXES
+ if (angle <= 90)
+ need_above = 1, need_left = 0;
+ else if (angle < 180)
+ need_above = 1, need_left = 1;
+ else
+ need_above = 0, need_left = 1;
+#else
+ if (angle < 90)
+ need_above = 0, need_aboveright = 1, need_left = 0;
+ else if (angle == 90)
+ need_above = 1, need_aboveright = 0, need_left = 0;
+ else if (angle < 180)
+ need_above = 1, need_aboveright = 0, need_left = 1;
+ else
+ need_above = 0, need_aboveright = 0, need_left = 1;
+#endif // CONFIG_MISC_FIXES
+ }
+ }
+#endif // CONFIG_EXT_INTRA
// 127 127 127 .. 127 127 127 127 127 127
// 129 A B .. Y Z
#endif
// NEED_LEFT
- if (extend_modes[mode] & NEED_LEFT) {
+ if (need_left) {
#if CONFIG_MISC_FIXES
+#if CONFIG_EXT_INTRA
+ int need_bottom;
+ if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
+ if (ext_intra_mode <= FILTER_TM_PRED)
+ need_bottom = 0;
+ else
+ need_bottom = 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++)
}
// NEED_ABOVE
- if (extend_modes[mode] & NEED_ABOVE) {
+ if (need_above) {
#if CONFIG_MISC_FIXES
+#if CONFIG_EXT_INTRA
+ int need_right;
+ if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
+ if (ext_intra_mode <= FILTER_TM_PRED)
+ need_right = 1;
+ else
+ need_right = 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 CONFIG_MISC_FIXES
- if (extend_modes[mode] & NEED_ABOVELEFT) {
+ (void)need_aboveright;
+#if CONFIG_EXT_INTRA
+ if (ext_intra_mode_info->use_ext_intra_mode[plane != 0] ||
+ (extend_modes[mode] & NEED_ABOVELEFT)) {
+ 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
#else
// NEED_ABOVERIGHT
- if (extend_modes[mode] & NEED_ABOVERIGHT) {
+ if (need_aboveright) {
if (up_available) {
const uint8_t *above_ref = ref - ref_stride;
if (xd->mb_to_right_edge < 0) {
}
#endif
+#if CONFIG_EXT_INTRA
+ if (ext_intra_mode_info->use_ext_intra_mode[plane != 0]) {
+ if (ext_intra_mode <= FILTER_TM_PRED)
+ filter_intra_predictors[ext_intra_mode](dst, dst_stride, bs,
+ const_above_row, left_col);
+ else
+ dr_predictor(dst, dst_stride, bs, const_above_row, left_col, angle);
+ return;
+ }
+#endif // CONFIG_EXT_INTRA
+
// predict
if (mode == DC_PRED) {
#if CONFIG_MISC_FIXES
memcpy(t_above, xd->plane[0].above_context, sizeof(t_above));
memcpy(t_left, xd->plane[0].left_context, sizeof(t_left));
+#if CONFIG_EXT_INTRA
+ mic->mbmi.ext_intra_mode_info.use_ext_intra_mode[0] = 0;
+#endif // CONFIG_EXT_INTRA
+
// Pick modes for each sub-block (of size 4x4, 4x8, or 8x4) in an 8x8 block.
for (idy = 0; idy < 2; idy += num_4x4_blocks_high) {
for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
return RDCOST(mb->rdmult, mb->rddiv, cost, total_distortion);
}
+#if CONFIG_EXT_INTRA
+// Return 1 if an ext intra mode is selected; return 0 otherwise.
+static int rd_pick_ext_intra_sby(VP10_COMP *cpi, MACROBLOCK *x,
+ int *rate, int *rate_tokenonly,
+ int64_t *distortion, int *skippable,
+ BLOCK_SIZE bsize, int mode_cost,
+ int64_t *best_rd) {
+ MACROBLOCKD *const xd = &x->e_mbd;
+ MODE_INFO *const mic = xd->mi[0];
+ MB_MODE_INFO *mbmi = &mic->mbmi;
+ int this_rate, this_rate_tokenonly, s;
+ int ext_intra_selected_flag = 0;
+ int i, step, delta, angle, best_angle, best_angle_dir;
+ int deltas[3] = {25, 5, 1};
+ int branches[3] = {2, 2, 2};
+ int64_t this_distortion, this_rd, best_angle_rd = INT64_MAX;
+ EXT_INTRA_MODE mode;
+ TX_SIZE best_tx_size = TX_4X4;
+ EXT_INTRA_MODE_INFO ext_intra_mode_info;
+#if CONFIG_EXT_TX
+ TX_TYPE best_tx_type;
+#endif // CONFIG_EXT_TX
+
+ vp10_zero(ext_intra_mode_info);
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = 1;
+ mbmi->mode = DC_PRED;
+
+ if (!DR_ONLY) {
+ for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) {
+ mbmi->ext_intra_mode_info.ext_intra_mode[0] = mode;
+ 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 +
+ vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 1) +
+ vp10_cost_bit(DR_EXT_INTRA_PROB, 0) +
+ write_uniform_cost(FILTER_INTRA_MODES, mode) + mode_cost;
+ this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+
+ if (this_rd < *best_rd) {
+ *best_rd = this_rd;
+ best_tx_size = mic->mbmi.tx_size;
+ ext_intra_mode_info = mbmi->ext_intra_mode_info;
+#if CONFIG_EXT_TX
+ best_tx_type = mic->mbmi.tx_type;
+#endif // CONFIG_EXT_TX
+ *rate = this_rate;
+ *rate_tokenonly = this_rate_tokenonly;
+ *distortion = this_distortion;
+ *skippable = s;
+ ext_intra_selected_flag = 1;
+ }
+ }
+ }
+
+ mbmi->ext_intra_mode_info.ext_intra_mode[0] = EXT_DR_PRED;
+ if (ANGLE_FAST_SEARCH) {
+ best_angle = EXT_INTRA_ANGLES / 2;
+ for (step = 0; step < 3; ++step) {
+ delta = deltas[step];
+ for (i = -branches[step]; i <= branches[step]; ++i) {
+ int64_t rd_thresh;
+ if (i == 0 && step != 0)
+ continue;
+ angle = best_angle + i * delta;
+ if (angle < 0)
+ angle = 0;
+ if (angle >= EXT_INTRA_ANGLES)
+ angle = EXT_INTRA_ANGLES - 1;
+ if (angle == best_angle && step != 0)
+ continue;
+ mbmi->ext_intra_mode_info.ext_intra_angle[0] = angle;
+ if (*best_rd == INT64_MAX)
+ rd_thresh = best_angle_rd;
+ else
+ rd_thresh = VPXMIN(best_angle_rd, *best_rd * RD_ADJUSTER);
+ super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
+ &s, NULL, bsize, rd_thresh);
+ if (this_rate_tokenonly == INT_MAX)
+ continue;
+ this_rate = this_rate_tokenonly +
+ vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 1) +
+ (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) +
+ write_uniform_cost(EXT_INTRA_ANGLES, angle) + mode_cost;
+ this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+ if (this_rd < *best_rd) {
+ *best_rd = this_rd;
+ best_tx_size = mic->mbmi.tx_size;
+ ext_intra_mode_info = mbmi->ext_intra_mode_info;
+#if CONFIG_EXT_TX
+ best_tx_type = mic->mbmi.tx_type;
+#endif // CONFIG_EXT_TX
+ *rate = this_rate;
+ *rate_tokenonly = this_rate_tokenonly;
+ *distortion = this_distortion;
+ *skippable = s;
+ ext_intra_selected_flag = 1;
+ }
+ if (this_rd < best_angle_rd) {
+ best_angle_rd = this_rd;
+ best_angle_dir = i;
+ }
+ }
+
+ best_angle += best_angle_dir * delta;
+ if (best_angle < 0)
+ best_angle = 0;
+ if (best_angle >= EXT_INTRA_ANGLES)
+ best_angle = EXT_INTRA_ANGLES - 1;
+ if (*best_rd < best_angle_rd / RD_ADJUSTER)
+ break;
+ }
+ } else {
+ for (angle = 0; angle < EXT_INTRA_ANGLES; ++angle) {
+ mbmi->ext_intra_mode_info.ext_intra_angle[0] = angle;
+ if (prediction_angle_map(angle) == 90 ||
+ prediction_angle_map(angle) == 180)
+ 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 +
+ vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 1) +
+ (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) +
+ write_uniform_cost(EXT_INTRA_ANGLES, angle) + mode_cost;
+ this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+
+ if (this_rd < *best_rd) {
+ *best_rd = this_rd;
+ best_tx_size = mic->mbmi.tx_size;
+ ext_intra_mode_info = mbmi->ext_intra_mode_info;
+#if CONFIG_EXT_TX
+ best_tx_type = mic->mbmi.tx_type;
+#endif // CONFIG_EXT_TX
+ *rate = this_rate;
+ *rate_tokenonly = this_rate_tokenonly;
+ *distortion = this_distortion;
+ *skippable = s;
+ ext_intra_selected_flag = 1;
+ }
+ }
+ }
+
+ if (ext_intra_selected_flag) {
+ mbmi->mode = DC_PRED;
+ mbmi->tx_size = best_tx_size;
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[0] =
+ ext_intra_mode_info.use_ext_intra_mode[0];
+ mbmi->ext_intra_mode_info.ext_intra_mode[0] =
+ ext_intra_mode_info.ext_intra_mode[0];
+ mbmi->ext_intra_mode_info.ext_intra_angle[0] =
+ ext_intra_mode_info.ext_intra_angle[0];
+#if CONFIG_EXT_TX
+ mbmi->tx_type = best_tx_type;
+#endif // CONFIG_EXT_TX
+ return 1;
+ } else {
+ return 0;
+ }
+}
+#endif // CONFIG_EXT_INTRA
+
// This function is used only for intra_only frames
static int64_t rd_pick_intra_sby_mode(VP10_COMP *cpi, MACROBLOCK *x,
int *rate, int *rate_tokenonly,
int this_rate, this_rate_tokenonly, s;
int64_t this_distortion, this_rd;
TX_SIZE best_tx = TX_4X4;
+#if CONFIG_EXT_INTRA
+ EXT_INTRA_MODE_INFO ext_intra_mode_info;
+#endif // CONFIG_EXT_INTRA
#if CONFIG_EXT_TX
TX_TYPE best_tx_type = DCT_DCT;
#endif // CONFIG_EXT_TX
const PREDICTION_MODE L = vp10_left_block_mode(mic, left_mi, 0);
bmode_costs = cpi->y_mode_costs[A][L];
+#if CONFIG_EXT_INTRA
+ ext_intra_mode_info.use_ext_intra_mode[0] = 0;
+ mic->mbmi.ext_intra_mode_info.use_ext_intra_mode[0] = 0;
+#endif // CONFIG_EXT_INTRA
memset(x->skip_txfm, SKIP_TXFM_NONE, sizeof(x->skip_txfm));
palette_mode_info.palette_size[0] = 0;
mic->mbmi.palette_mode_info.palette_size[0] = 0;
palette_ctx += (left_mi->mbmi.palette_mode_info.palette_size[0] > 0);
/* Y Search for intra prediction mode */
- for (mode = DC_PRED; mode <= TM_PRED; mode++) {
+ for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
mic->mbmi.mode = mode;
super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
this_rate +=
vp10_cost_bit(vp10_default_palette_y_mode_prob[bsize - BLOCK_8X8]
[palette_ctx], 0);
+#if CONFIG_EXT_INTRA
+ if (mode == DC_PRED)
+ this_rate += vp10_cost_bit(cpi->common.fc->ext_intra_probs[0], 0);
+#endif // CONFIG_EXT_INTRA
this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
if (this_rd < best_rd) {
&palette_mode_info, best_palette_color_map,
&best_tx, &mode_selected, &best_rd);
+#if CONFIG_EXT_INTRA
+ if (!palette_mode_info.palette_size[0] > 0) {
+ if (rd_pick_ext_intra_sby(cpi, x, rate, rate_tokenonly, distortion,
+ skippable, bsize, bmode_costs[DC_PRED],
+ &best_rd)) {
+ mode_selected = mic->mbmi.mode;
+ best_tx = mic->mbmi.tx_size;
+ ext_intra_mode_info = mic->mbmi.ext_intra_mode_info;
+#if CONFIG_EXT_TX
+ best_tx_type = mic->mbmi.tx_type;
+#endif // CONFIG_EXT_TX
+ }
+ }
+
+ mic->mbmi.ext_intra_mode_info.use_ext_intra_mode[0] =
+ ext_intra_mode_info.use_ext_intra_mode[0];
+ if (ext_intra_mode_info.use_ext_intra_mode[0]) {
+ mic->mbmi.ext_intra_mode_info.ext_intra_mode[0] =
+ ext_intra_mode_info.ext_intra_mode[0];
+ mic->mbmi.ext_intra_mode_info.ext_intra_angle[0] =
+ ext_intra_mode_info.ext_intra_angle[0];
+ }
+#endif // CONFIG_EXT_INTRA
+
mic->mbmi.mode = mode_selected;
mic->mbmi.tx_size = best_tx;
#if CONFIG_EXT_TX
return is_cost_valid;
}
+#if CONFIG_EXT_INTRA
+// Return 1 if an ext intra mode is selected; return 0 otherwise.
+static int rd_pick_ext_intra_sbuv(VP10_COMP *cpi, MACROBLOCK *x,
+ PICK_MODE_CONTEXT *ctx,
+ int *rate, int *rate_tokenonly,
+ int64_t *distortion, int *skippable,
+ BLOCK_SIZE bsize, int64_t *best_rd) {
+ MACROBLOCKD *const xd = &x->e_mbd;
+ MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+ int ext_intra_selected_flag = 0;
+ int this_rate_tokenonly, this_rate, s;
+ int64_t this_distortion, this_sse, this_rd, best_angle_rd = INT64_MAX;
+ EXT_INTRA_MODE mode;
+ int i, step, delta, angle, best_angle, best_angle_dir;
+ int deltas[3] = {25, 5, 1};
+ int branches[3] = {2, 2, 2};
+ EXT_INTRA_MODE_INFO ext_intra_mode_info;
+
+ vp10_zero(ext_intra_mode_info);
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = 1;
+ mbmi->uv_mode = DC_PRED;
+
+ if (!DR_ONLY) {
+ for (mode = 0; mode < FILTER_INTRA_MODES; ++mode) {
+ mbmi->ext_intra_mode_info.ext_intra_mode[1] = mode;
+ if (!super_block_uvrd(cpi, x, &this_rate_tokenonly,
+ &this_distortion, &s, &this_sse, bsize, *best_rd))
+ continue;
+
+ this_rate = this_rate_tokenonly +
+ vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 1) +
+ vp10_cost_bit(DR_EXT_INTRA_PROB, 0) +
+ cpi->intra_uv_mode_cost[mbmi->uv_mode] +
+ write_uniform_cost(FILTER_INTRA_MODES, mode);
+ this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+ if (this_rd < *best_rd) {
+ *best_rd = this_rd;
+ *rate = this_rate;
+ *rate_tokenonly = this_rate_tokenonly;
+ *distortion = this_distortion;
+ *skippable = s;
+ ext_intra_mode_info = mbmi->ext_intra_mode_info;
+ ext_intra_selected_flag = 1;
+ if (!x->select_tx_size)
+ swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE);
+ }
+ }
+ }
+
+ mbmi->ext_intra_mode_info.ext_intra_mode[1] = EXT_DR_PRED;
+ if (ANGLE_FAST_SEARCH) {
+ best_angle = EXT_INTRA_ANGLES / 2;
+ for (step = 0; step < 3; ++step) {
+ delta = deltas[step];
+ for (i = -branches[step]; i <= branches[step]; ++i) {
+ int64_t rd_thresh;
+ if (i == 0 && step != 0)
+ continue;
+ angle = best_angle + i * delta;
+ if (angle < 0)
+ angle = 0;
+ if (angle >= EXT_INTRA_ANGLES)
+ angle = EXT_INTRA_ANGLES - 1;
+ if (angle == best_angle && step != 0)
+ continue;
+ mbmi->ext_intra_mode_info.ext_intra_angle[1] = angle;
+ if (*best_rd == INT64_MAX)
+ rd_thresh = best_angle_rd;
+ else
+ rd_thresh = VPXMIN(best_angle_rd, *best_rd * RD_ADJUSTER);
+ if (!super_block_uvrd(cpi, x, &this_rate_tokenonly, &this_distortion,
+ &s, &this_sse, bsize, rd_thresh))
+ continue;
+ this_rate = this_rate_tokenonly +
+ vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 1) +
+ (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) +
+ cpi->intra_uv_mode_cost[mbmi->uv_mode] +
+ write_uniform_cost(EXT_INTRA_ANGLES, angle);
+ this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+ if (this_rd < *best_rd) {
+ *best_rd = this_rd;
+ *rate = this_rate;
+ *rate_tokenonly = this_rate_tokenonly;
+ *distortion = this_distortion;
+ *skippable = s;
+ ext_intra_mode_info = mbmi->ext_intra_mode_info;
+ ext_intra_selected_flag = 1;
+ if (!x->select_tx_size)
+ swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE);
+ }
+ if (this_rd < best_angle_rd) {
+ best_angle_rd = this_rd;
+ best_angle_dir = i;
+ }
+ }
+ best_angle += best_angle_dir * delta;
+ if (best_angle < 0)
+ best_angle = 0;
+ if (best_angle >= EXT_INTRA_ANGLES)
+ best_angle = EXT_INTRA_ANGLES - 1;
+ if (*best_rd < best_angle_rd / RD_ADJUSTER)
+ break;
+ }
+ } else {
+ for (angle = 0; angle < EXT_INTRA_ANGLES; ++angle) {
+ mbmi->ext_intra_mode_info.ext_intra_angle[1] = angle;
+ if (prediction_angle_map(angle) == 90 ||
+ prediction_angle_map(angle) == 180)
+ continue;
+ if (!super_block_uvrd(cpi, x, &this_rate_tokenonly,
+ &this_distortion, &s, &this_sse, bsize, *best_rd))
+ continue;
+
+ this_rate = this_rate_tokenonly +
+ vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 1) +
+ (DR_ONLY ? 0: vp10_cost_bit(DR_EXT_INTRA_PROB, 1)) +
+ cpi->intra_uv_mode_cost[mbmi->uv_mode] +
+ write_uniform_cost(EXT_INTRA_ANGLES, angle);
+ this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
+ if (this_rd < *best_rd) {
+ *best_rd = this_rd;
+ *rate = this_rate;
+ *rate_tokenonly = this_rate_tokenonly;
+ *distortion = this_distortion;
+ *skippable = s;
+ ext_intra_mode_info = mbmi->ext_intra_mode_info;
+ ext_intra_selected_flag = 1;
+ if (!x->select_tx_size)
+ swap_block_ptr(x, ctx, 2, 0, 1, MAX_MB_PLANE);
+ }
+ }
+ }
+
+ if (ext_intra_selected_flag) {
+ mbmi->uv_mode = DC_PRED;
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[1] =
+ ext_intra_mode_info.use_ext_intra_mode[1];
+ mbmi->ext_intra_mode_info.ext_intra_mode[1] =
+ ext_intra_mode_info.ext_intra_mode[1];
+ mbmi->ext_intra_mode_info.ext_intra_angle[1] =
+ ext_intra_mode_info.ext_intra_angle[1];
+
+ return 1;
+ } else {
+ return 0;
+ }
+}
+#endif // CONFIG_EXT_INTRA
+
static int64_t rd_pick_intra_sbuv_mode(VP10_COMP *cpi, MACROBLOCK *x,
PICK_MODE_CONTEXT *ctx,
int *rate, int *rate_tokenonly,
int64_t *distortion, int *skippable,
BLOCK_SIZE bsize, TX_SIZE max_tx_size) {
MACROBLOCKD *xd = &x->e_mbd;
+ MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
PREDICTION_MODE mode;
PREDICTION_MODE mode_selected = DC_PRED;
int64_t best_rd = INT64_MAX, this_rd;
int this_rate_tokenonly, this_rate, s;
int64_t this_distortion, this_sse;
+#if CONFIG_EXT_INTRA
+ EXT_INTRA_MODE_INFO ext_intra_mode_info;
+ ext_intra_mode_info.use_ext_intra_mode[1] = 0;
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = 0;
+#endif // CONFIG_EXT_INTRA
memset(x->skip_txfm, SKIP_TXFM_NONE, sizeof(x->skip_txfm));
xd->mi[0]->mbmi.palette_mode_info.palette_size[1] = 0;
for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
if (!(cpi->sf.intra_uv_mode_mask[max_tx_size] & (1 << mode)))
continue;
- xd->mi[0]->mbmi.uv_mode = mode;
+ mbmi->uv_mode = mode;
if (!super_block_uvrd(cpi, x, &this_rate_tokenonly,
&this_distortion, &s, &this_sse, bsize, best_rd))
continue;
this_rate = this_rate_tokenonly + cpi->intra_uv_mode_cost[mode];
+#if CONFIG_EXT_INTRA
+ if (mode == DC_PRED)
+ this_rate += vp10_cost_bit(cpi->common.fc->ext_intra_probs[1], 0);
+#endif // CONFIG_EXT_INTRA
this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
if (this_rd < best_rd) {
}
}
- xd->mi[0]->mbmi.uv_mode = mode_selected;
+#if CONFIG_EXT_INTRA
+ if (mbmi->sb_type >= BLOCK_8X8) {
+ if (rd_pick_ext_intra_sbuv(cpi, x, ctx, rate, rate_tokenonly, distortion,
+ skippable, bsize, &best_rd)) {
+ mode_selected = mbmi->uv_mode;
+ ext_intra_mode_info = mbmi->ext_intra_mode_info;
+ }
+ }
+
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[1] =
+ ext_intra_mode_info.use_ext_intra_mode[1];
+ if (ext_intra_mode_info.use_ext_intra_mode[1])
+ mbmi->ext_intra_mode_info.ext_intra_mode[1] =
+ ext_intra_mode_info.ext_intra_mode[1];
+#endif // CONFIG_EXT_INTRA
+ mbmi->uv_mode = mode_selected;
return best_rd;
}
int64_t dist_uv[TX_SIZES];
int skip_uv[TX_SIZES];
PREDICTION_MODE mode_uv[TX_SIZES];
+#if CONFIG_EXT_INTRA
+ EXT_INTRA_MODE_INFO ext_intra_mode_info_uv[TX_SIZES];
+#endif // CONFIG_EXT_INTRA
const int intra_cost_penalty = vp10_get_intra_cost_penalty(
cm->base_qindex, cm->y_dc_delta_q, cm->bit_depth);
int best_skip2 = 0;
mbmi->uv_mode = DC_PRED;
mbmi->ref_frame[0] = ref_frame;
mbmi->ref_frame[1] = second_ref_frame;
+#if CONFIG_EXT_INTRA
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = 0;
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = 0;
+#endif // CONFIG_EXT_INTRA
// Evaluate all sub-pel filters irrespective of whether we can use
// them for this frame.
mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP
memset(x->skip_txfm, 0, sizeof(x->skip_txfm));
super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable,
NULL, bsize, best_rd);
+#if CONFIG_EXT_INTRA
+ // TODO(huisu): ext-intra is turned off in lossless mode for now to
+ // avoid a unit test failure
+ if (mbmi->mode == DC_PRED && !xd->lossless[mbmi->segment_id]) {
+ MB_MODE_INFO mbmi_copy = *mbmi;
+ int rate_dummy;
+
+ if (rate_y != INT_MAX) {
+ int this_rate = rate_y + cpi->mbmode_cost[mbmi->mode] +
+ vp10_cost_bit(cm->fc->ext_intra_probs[0], 0);
+ this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, distortion_y);
+ } else {
+ this_rd = best_rd;
+ }
+
+ if (!rd_pick_ext_intra_sby(cpi, x, &rate_dummy, &rate_y, &distortion_y,
+ &skippable, bsize,
+ cpi->mbmode_cost[mbmi->mode], &this_rd))
+ *mbmi = mbmi_copy;
+ }
+#endif // CONFIG_EXT_INTRA
if (rate_y == INT_MAX)
continue;
uv_tx = get_uv_tx_size_impl(mbmi->tx_size, bsize, pd->subsampling_x,
choose_intra_uv_mode(cpi, x, ctx, bsize, uv_tx,
&rate_uv_intra[uv_tx], &rate_uv_tokenonly[uv_tx],
&dist_uv[uv_tx], &skip_uv[uv_tx], &mode_uv[uv_tx]);
+#if CONFIG_EXT_INTRA
+ ext_intra_mode_info_uv[uv_tx] = mbmi->ext_intra_mode_info;
+#endif // CONFIG_EXT_INTRA
}
rate_uv = rate_uv_tokenonly[uv_tx];
distortion_uv = dist_uv[uv_tx];
skippable = skippable && skip_uv[uv_tx];
mbmi->uv_mode = mode_uv[uv_tx];
+#if CONFIG_EXT_INTRA
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[1] =
+ ext_intra_mode_info_uv[uv_tx].use_ext_intra_mode[1];
+ if (ext_intra_mode_info_uv[uv_tx].use_ext_intra_mode[1]) {
+ mbmi->ext_intra_mode_info.ext_intra_mode[1] =
+ ext_intra_mode_info_uv[uv_tx].ext_intra_mode[1];
+ mbmi->ext_intra_mode_info.ext_intra_angle[1] =
+ ext_intra_mode_info_uv[uv_tx].ext_intra_angle[1];
+ }
+#endif // CONFIG_EXT_INTRA
rate2 = rate_y + cpi->mbmode_cost[mbmi->mode] + rate_uv_intra[uv_tx];
+#if CONFIG_EXT_INTRA
+ if (mbmi->mode == DC_PRED) {
+ rate2 += vp10_cost_bit(cm->fc->ext_intra_probs[0],
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[0]);
+ if (mbmi->ext_intra_mode_info.use_ext_intra_mode[0]) {
+ EXT_INTRA_MODE ext_intra_mode =
+ mbmi->ext_intra_mode_info.ext_intra_mode[0];
+ int angle = mbmi->ext_intra_mode_info.ext_intra_angle[0];
+ if (!DR_ONLY)
+ rate2 += vp10_cost_bit(DR_EXT_INTRA_PROB,
+ ext_intra_mode > FILTER_TM_PRED);
+ if (ext_intra_mode > FILTER_TM_PRED)
+ rate2 += write_uniform_cost(EXT_INTRA_ANGLES, angle);
+ else
+ rate2 += write_uniform_cost(FILTER_INTRA_MODES, ext_intra_mode);
+ }
+ }
+#endif // CONFIG_EXT_INTRA
if (this_mode != DC_PRED && this_mode != TM_PRED)
rate2 += intra_cost_penalty;
distortion2 = distortion_y + distortion_uv;
mbmi->palette_mode_info.palette_size[0] = 0;
mbmi->palette_mode_info.palette_size[1] = 0;
+#if CONFIG_EXT_INTRA
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = 0;
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = 0;
+#endif // CONFIG_EXT_INTRA
mbmi->mode = ZEROMV;
mbmi->uv_mode = DC_PRED;
mbmi->ref_frame[0] = LAST_FRAME;
memset(x->zcoeff_blk[TX_4X4], 0, 4);
vp10_zero(best_mbmode);
+#if CONFIG_EXT_INTRA
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[0] = 0;
+ mbmi->ext_intra_mode_info.use_ext_intra_mode[1] = 0;
+#endif // CONFIG_EXT_INTRA
+
for (i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i)
filter_cache[i] = INT64_MAX;