multiple_arf
spatial_svc
denoising
+ masked_interinter
+ interintra
+ masked_interintra
+ filterintra
+ ext_tx
"
CONFIG_LIST="
external_build
return mi_width_log2_lookup[sb_type];
}
+#if CONFIG_MASKED_INTERINTER
+#define MASK_BITS_SML 3
+#define MASK_BITS_MED 4
+#define MASK_BITS_BIG 5
+#define MASK_NONE -1
+
+static inline int get_mask_bits(BLOCK_SIZE sb_type) {
+ if (sb_type < BLOCK_8X8)
+ return 0;
+ if (sb_type <= BLOCK_8X8)
+ return MASK_BITS_SML;
+ else if (sb_type <= BLOCK_32X32)
+ return MASK_BITS_MED;
+ else
+ return MASK_BITS_BIG;
+}
+#endif
+
+#if CONFIG_INTERINTRA
+static INLINE TX_SIZE intra_size_log2_for_interintra(int bs) {
+ switch (bs) {
+ case 4:
+ return TX_4X4;
+ break;
+ case 8:
+ return TX_8X8;
+ break;
+ case 16:
+ return TX_16X16;
+ break;
+ case 32:
+ return TX_32X32;
+ break;
+ default:
+ return TX_32X32;
+ break;
+ }
+}
+
+static INLINE int is_interintra_allowed(BLOCK_SIZE sb_type) {
+ return ((sb_type >= BLOCK_8X8) && (sb_type < BLOCK_64X64));
+}
+
+#if CONFIG_MASKED_INTERINTRA
+#define MASK_BITS_SML_INTERINTRA 3
+#define MASK_BITS_MED_INTERINTRA 4
+#define MASK_BITS_BIG_INTERINTRA 5
+#define MASK_NONE_INTERINTRA -1
+static INLINE int get_mask_bits_interintra(BLOCK_SIZE sb_type) {
+ if (sb_type == BLOCK_4X4)
+ return 0;
+ if (sb_type <= BLOCK_8X8)
+ return MASK_BITS_SML_INTERINTRA;
+ else if (sb_type <= BLOCK_32X32)
+ return MASK_BITS_MED_INTERINTRA;
+ else
+ return MASK_BITS_BIG_INTERINTRA;
+}
+#endif
+#endif
+
// This structure now relates to 8x8 block regions.
typedef struct {
// Common for both INTER and INTRA blocks
BLOCK_SIZE sb_type;
PREDICTION_MODE mode;
+#if CONFIG_FILTERINTRA
+ int filterbit, uv_filterbit;
+#endif
TX_SIZE tx_size;
uint8_t skip;
uint8_t segment_id;
int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
uint8_t mode_context[MAX_REF_FRAMES];
INTERP_FILTER interp_filter;
+
+#if CONFIG_EXT_TX
+ EXT_TX_TYPE ext_txfrm;
+#endif
+
+#if CONFIG_MASKED_INTERINTER
+ int use_masked_interinter;
+ int mask_index;
+#endif
+#if CONFIG_INTERINTRA
+ PREDICTION_MODE interintra_mode, interintra_uv_mode;
+#if CONFIG_MASKED_INTERINTRA
+ int interintra_mask_index;
+ int interintra_uv_mask_index;
+ int use_masked_interintra;
+#endif
+#endif
} MB_MODE_INFO;
typedef struct {
MB_MODE_INFO mbmi;
+#if CONFIG_FILTERINTRA
+ int b_filter_info[4];
+#endif
b_mode_info bmi[4];
} MODE_INFO;
: mi->mbmi.mode;
}
+#if CONFIG_FILTERINTRA
+static INLINE int is_filter_allowed(PREDICTION_MODE mode) {
+ return 1;
+}
+
+static INLINE int is_filter_enabled(TX_SIZE txsize) {
+ return (txsize <= TX_32X32);
+}
+#endif
+
static INLINE int is_inter_block(const MB_MODE_INFO *mbmi) {
return mbmi->ref_frame[0] > INTRA_FRAME;
}
const MACROBLOCKD *xd) {
const MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
+#if !CONFIG_EXT_TX
if (plane_type != PLANE_TYPE_Y || is_inter_block(mbmi))
return DCT_DCT;
+#else
+ if (plane_type != PLANE_TYPE_Y)
+ return DCT_DCT;
+
+ if (is_inter_block(mbmi)) {
+ if (mbmi->ext_txfrm == NORM || mbmi->tx_size >= TX_32X32)
+ return DCT_DCT;
+ else
+ return ADST_ADST;
+ }
+#endif
return intra_mode_to_tx_type_lookup[mbmi->mode];
}
const MACROBLOCKD *xd, int ib) {
const MODE_INFO *const mi = xd->mi[0];
+#if !CONFIG_EXT_TX
if (plane_type != PLANE_TYPE_Y || xd->lossless || is_inter_block(&mi->mbmi))
return DCT_DCT;
+#else
+ if (plane_type != PLANE_TYPE_Y || xd->lossless)
+ return DCT_DCT;
+
+ if (is_inter_block(&mi->mbmi)) {
+ if (mi->mbmi.ext_txfrm == NORM)
+ return DCT_DCT;
+ else
+ return ADST_ADST;
+ }
+#endif
return intra_mode_to_tx_type_lookup[get_y_mode(mi, ib)];
}
#include "vp9/common/vp9_onyxc_int.h"
#include "vp9/common/vp9_seg_common.h"
+#if CONFIG_MASKED_INTERINTER
+static const vp9_prob default_masked_interinter_prob[BLOCK_SIZES] = {
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
+};
+#endif
+
+#if CONFIG_INTERINTRA
+static const vp9_prob default_interintra_prob[BLOCK_SIZES] = {
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
+};
+#if CONFIG_MASKED_INTERINTRA
+static const vp9_prob default_masked_interintra_prob[BLOCK_SIZES] = {
+ 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192
+};
+#endif
+#endif
+
+#if CONFIG_FILTERINTRA
+const vp9_prob default_filterintra_prob[TX_SIZES][INTRA_MODES] = {
+ // DC V H D45 D135 D117 D153 D207 D63 TM
+ {153, 171, 147, 150, 129, 101, 100, 153, 132, 111},
+ {171, 173, 185, 131, 70, 53, 70, 148, 127, 114},
+ {175, 203, 213, 86, 45, 71, 41, 150, 125, 154},
+ {235, 230, 154, 202, 154, 205, 37, 128, 0, 202}
+};
+#endif
+
+#if CONFIG_EXT_TX
+const vp9_prob default_ext_tx_prob = 178; // 0.6 = 153, 0.7 = 178, 0.8 = 204
+#endif
+
const vp9_prob vp9_kf_y_mode_prob[INTRA_MODES][INTRA_MODES][INTRA_MODES - 1] = {
{ // above = dc
{ 137, 30, 42, 148, 151, 207, 70, 52, 91 }, // left = dc
fc->tx_probs = default_tx_probs;
vp9_copy(fc->skip_probs, default_skip_probs);
vp9_copy(fc->inter_mode_probs, default_inter_mode_probs);
+#if CONFIG_MASKED_INTERINTER
+ vp9_copy(fc->masked_interinter_prob, default_masked_interinter_prob);
+#endif
+#if CONFIG_INTERINTRA
+ vp9_copy(fc->interintra_prob, default_interintra_prob);
+#if CONFIG_MASKED_INTERINTRA
+ vp9_copy(fc->masked_interintra_prob, default_masked_interintra_prob);
+#endif
+#endif
+#if CONFIG_FILTERINTRA
+ vp9_copy(fc->filterintra_prob, default_filterintra_prob);
+#endif
+#if CONFIG_EXT_TX
+ fc->ext_tx_prob = default_ext_tx_prob;
+#endif
}
const vp9_tree_index vp9_switchable_interp_tree
for (i = 0; i < SKIP_CONTEXTS; ++i)
fc->skip_probs[i] = adapt_prob(pre_fc->skip_probs[i], counts->skip[i]);
+
+#if CONFIG_MASKED_INTERINTER
+ if (cm->use_masked_interinter) {
+ for (i = 0; i < BLOCK_SIZES; ++i) {
+ if (get_mask_bits(i))
+ fc->masked_interinter_prob[i] = adapt_prob
+ (pre_fc->masked_interinter_prob[i],
+ counts->masked_interinter[i]);
+ }
+ }
+#endif
+
+#if CONFIG_INTERINTRA
+ if (cm->use_interintra) {
+ for (i = 0; i < BLOCK_SIZES; ++i) {
+ if (is_interintra_allowed(i))
+ fc->interintra_prob[i] = adapt_prob(pre_fc->interintra_prob[i],
+ counts->interintra[i]);
+ }
+#if CONFIG_MASKED_INTERINTRA
+ if (cm->use_masked_interintra) {
+ for (i = 0; i < BLOCK_SIZES; ++i) {
+ if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
+ fc->masked_interintra_prob[i] = adapt_prob(
+ pre_fc->masked_interintra_prob[i],
+ counts->masked_interintra[i]);
+ }
+ }
+#endif
+ }
+#endif
+
+#if CONFIG_FILTERINTRA
+ for (i = 0; i < TX_SIZES; ++i)
+ for (j = 0; j < INTRA_MODES; ++j)
+ fc->filterintra_prob[i][j] = adapt_prob(pre_fc->filterintra_prob[i][j],
+ counts->filterintra[i][j]);
+#endif
+
+#if CONFIG_EXT_TX
+ fc->ext_tx_prob = adapt_prob(pre_fc->ext_tx_prob, counts->ext_tx);
+#endif
}
static void set_default_lf_deltas(struct loopfilter *lf) {
struct tx_probs tx_probs;
vp9_prob skip_probs[SKIP_CONTEXTS];
nmv_context nmvc;
+#if CONFIG_MASKED_INTERINTER
+ vp9_prob masked_interinter_prob[BLOCK_SIZES];
+#endif
+#if CONFIG_INTERINTRA
+ vp9_prob interintra_prob[BLOCK_SIZES];
+#if CONFIG_MASKED_INTERINTRA
+ vp9_prob masked_interintra_prob[BLOCK_SIZES];
+#endif
+#endif
+#if CONFIG_FILTERINTRA
+ vp9_prob filterintra_prob[TX_SIZES][INTRA_MODES];
+#endif
+#if CONFIG_EXT_TX
+ vp9_prob ext_tx_prob;
+#endif
} FRAME_CONTEXT;
typedef struct {
struct tx_counts tx;
unsigned int skip[SKIP_CONTEXTS][2];
nmv_context_counts mv;
+#if CONFIG_MASKED_INTERINTER
+ unsigned int masked_interinter[BLOCK_SIZES][2];
+#endif
+#if CONFIG_INTERINTRA
+ unsigned int interintra[BLOCK_SIZES][2];
+#if CONFIG_MASKED_INTERINTRA
+ unsigned int masked_interintra[BLOCK_SIZES][2];
+#endif
+#endif
+#if CONFIG_FILTERINTRA
+ unsigned int filterintra[TX_SIZES][INTRA_MODES][2];
+#endif
+#if CONFIG_EXT_TX
+ unsigned int ext_tx[2];
+#endif
} FRAME_COUNTS;
extern const vp9_prob vp9_kf_uv_mode_prob[INTRA_MODES][INTRA_MODES - 1];
TX_TYPES = 4
} TX_TYPE;
+#if CONFIG_EXT_TX
+typedef enum {
+ NORM = 0,
+ ALT = 1,
+ EXT_TX_TYPES = 2
+} EXT_TX_TYPE;
+#endif
+
typedef enum {
UNKNOWN = 0,
BT_601 = 1, // YUV
PARTITION_CONTEXT *above_seg_context;
ENTROPY_CONTEXT *above_context;
+
+#if CONFIG_MASKED_INTERINTER
+ int use_masked_interinter;
+#endif
+#if CONFIG_INTERINTRA
+ int use_interintra;
+#if CONFIG_MASKED_INTERINTRA
+ int use_masked_interintra;
+#endif
+#endif
} VP9_COMMON;
static INLINE YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) {
return clamped_mv;
}
+#if CONFIG_MASKED_INTERINTER
+#define MASK_WEIGHT_BITS 6
+
+static int get_masked_weight(int m) {
+ #define SMOOTHER_LEN 32
+ static const uint8_t smoothfn[2 * SMOOTHER_LEN + 1] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 2, 2, 3, 4, 5, 6,
+ 8, 9, 12, 14, 17, 21, 24, 28,
+ 32,
+ 36, 40, 43, 47, 50, 52, 55, 56,
+ 58, 59, 60, 61, 62, 62, 63, 63,
+ 63, 63, 63, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64,
+ };
+ if (m < -SMOOTHER_LEN)
+ return 0;
+ else if (m > SMOOTHER_LEN)
+ return (1 << MASK_WEIGHT_BITS);
+ else
+ return smoothfn[m + SMOOTHER_LEN];
+}
+
+static int get_hard_mask(int m) {
+ return m > 0;
+}
+
+// Equation of line: f(x, y) = a[0]*(x - a[2]*w/4) + a[1]*(y - a[3]*h/4) = 0
+// The soft mask is obtained by computing f(x, y) and then calling
+// get_masked_weight(f(x, y)).
+static const int mask_params_sml[1 << MASK_BITS_SML][4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+};
+
+static const int mask_params_med_hgtw[1 << MASK_BITS_MED][4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ {-1, 2, 2, 1},
+ { 1, -2, 2, 1},
+ {-1, 2, 2, 3},
+ { 1, -2, 2, 3},
+ { 1, 2, 2, 1},
+ {-1, -2, 2, 1},
+ { 1, 2, 2, 3},
+ {-1, -2, 2, 3},
+};
+
+static const int mask_params_med_hltw[1 << MASK_BITS_MED][4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ {-2, 1, 1, 2},
+ { 2, -1, 1, 2},
+ {-2, 1, 3, 2},
+ { 2, -1, 3, 2},
+ { 2, 1, 1, 2},
+ {-2, -1, 1, 2},
+ { 2, 1, 3, 2},
+ {-2, -1, 3, 2},
+};
+
+static const int mask_params_med_heqw[1 << MASK_BITS_MED][4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ { 0, 2, 0, 1},
+ { 0, -2, 0, 1},
+ { 0, 2, 0, 3},
+ { 0, -2, 0, 3},
+ { 2, 0, 1, 0},
+ {-2, 0, 1, 0},
+ { 2, 0, 3, 0},
+ {-2, 0, 3, 0},
+};
+
+static const int mask_params_big_hgtw[1 << MASK_BITS_BIG][4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ {-1, 2, 2, 1},
+ { 1, -2, 2, 1},
+ {-1, 2, 2, 3},
+ { 1, -2, 2, 3},
+ { 1, 2, 2, 1},
+ {-1, -2, 2, 1},
+ { 1, 2, 2, 3},
+ {-1, -2, 2, 3},
+
+ {-2, 1, 1, 2},
+ { 2, -1, 1, 2},
+ {-2, 1, 3, 2},
+ { 2, -1, 3, 2},
+ { 2, 1, 1, 2},
+ {-2, -1, 1, 2},
+ { 2, 1, 3, 2},
+ {-2, -1, 3, 2},
+
+ { 0, 2, 0, 1},
+ { 0, -2, 0, 1},
+ { 0, 2, 0, 2},
+ { 0, -2, 0, 2},
+ { 0, 2, 0, 3},
+ { 0, -2, 0, 3},
+ { 2, 0, 2, 0},
+ {-2, 0, 2, 0},
+};
+
+static const int mask_params_big_hltw[1 << MASK_BITS_BIG][4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ {-1, 2, 2, 1},
+ { 1, -2, 2, 1},
+ {-1, 2, 2, 3},
+ { 1, -2, 2, 3},
+ { 1, 2, 2, 1},
+ {-1, -2, 2, 1},
+ { 1, 2, 2, 3},
+ {-1, -2, 2, 3},
+
+ {-2, 1, 1, 2},
+ { 2, -1, 1, 2},
+ {-2, 1, 3, 2},
+ { 2, -1, 3, 2},
+ { 2, 1, 1, 2},
+ {-2, -1, 1, 2},
+ { 2, 1, 3, 2},
+ {-2, -1, 3, 2},
+
+ { 0, 2, 0, 2},
+ { 0, -2, 0, 2},
+ { 2, 0, 1, 0},
+ {-2, 0, 1, 0},
+ { 2, 0, 2, 0},
+ {-2, 0, 2, 0},
+ { 2, 0, 3, 0},
+ {-2, 0, 3, 0},
+};
+
+static const int mask_params_big_heqw[1 << MASK_BITS_BIG][4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ {-1, 2, 2, 1},
+ { 1, -2, 2, 1},
+ {-1, 2, 2, 3},
+ { 1, -2, 2, 3},
+ { 1, 2, 2, 1},
+ {-1, -2, 2, 1},
+ { 1, 2, 2, 3},
+ {-1, -2, 2, 3},
+
+ {-2, 1, 1, 2},
+ { 2, -1, 1, 2},
+ {-2, 1, 3, 2},
+ { 2, -1, 3, 2},
+ { 2, 1, 1, 2},
+ {-2, -1, 1, 2},
+ { 2, 1, 3, 2},
+ {-2, -1, 3, 2},
+
+ { 0, 2, 0, 1},
+ { 0, -2, 0, 1},
+ { 0, 2, 0, 3},
+ { 0, -2, 0, 3},
+ { 2, 0, 1, 0},
+ {-2, 0, 1, 0},
+ { 2, 0, 3, 0},
+ {-2, 0, 3, 0},
+};
+
+static const int *get_mask_params(int mask_index,
+ BLOCK_SIZE sb_type,
+ int h, int w) {
+ const int *a;
+ const int mask_bits = get_mask_bits(sb_type);
+
+ if (mask_index == MASK_NONE)
+ return NULL;
+
+ if (mask_bits == MASK_BITS_SML) {
+ a = mask_params_sml[mask_index];
+ } else if (mask_bits == MASK_BITS_MED) {
+ if (h > w)
+ a = mask_params_med_hgtw[mask_index];
+ else if (h < w)
+ a = mask_params_med_hltw[mask_index];
+ else
+ a = mask_params_med_heqw[mask_index];
+ } else if (mask_bits == MASK_BITS_BIG) {
+ if (h > w)
+ a = mask_params_big_hgtw[mask_index];
+ else if (h < w)
+ a = mask_params_big_hltw[mask_index];
+ else
+ a = mask_params_big_heqw[mask_index];
+ } else {
+ assert(0);
+ }
+ return a;
+}
+
+void vp9_generate_masked_weight(int mask_index,
+ BLOCK_SIZE sb_type,
+ int h, int w,
+ uint8_t *mask, int stride) {
+ int i, j;
+ const int *a = get_mask_params(mask_index, sb_type, h, w);
+ if (!a) return;
+ for (i = 0; i < h; ++i)
+ for (j = 0; j < w; ++j) {
+ int x = (j - (a[2] * w) / 4);
+ int y = (i - (a[3] * h) / 4);
+ int m = a[0] * x + a[1] * y;
+ mask[i * stride + j] = get_masked_weight(m);
+ }
+}
+
+void vp9_generate_hard_mask(int mask_index, BLOCK_SIZE sb_type,
+ int h, int w, uint8_t *mask, int stride) {
+ int i, j;
+ const int *a = get_mask_params(mask_index, sb_type, h, w);
+ if (!a) return;
+ for (i = 0; i < h; ++i)
+ for (j = 0; j < w; ++j) {
+ int x = (j - (a[2] * w) / 4);
+ int y = (i - (a[3] * h) / 4);
+ int m = a[0] * x + a[1] * y;
+ mask[i * stride + j] = get_hard_mask(m);
+ }
+}
+
+static void build_masked_compound(uint8_t *dst, int dst_stride,
+ uint8_t *dst2, int dst2_stride,
+ int mask_index, BLOCK_SIZE sb_type,
+ int h, int w) {
+ int i, j;
+ uint8_t mask[4096];
+ vp9_generate_masked_weight(mask_index, sb_type, h, w, mask, 64);
+ for (i = 0; i < h; ++i)
+ for (j = 0; j < w; ++j) {
+ int m = mask[i * 64 + j];
+ dst[i * dst_stride + j] = (dst[i * dst_stride + j] * m +
+ dst2[i * dst2_stride + j] *
+ ((1 << MASK_WEIGHT_BITS) - m) +
+ (1 << (MASK_WEIGHT_BITS - 1))) >>
+ MASK_WEIGHT_BITS;
+ }
+}
+#endif
+
static void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
int bw, int bh,
int x, int y, int w, int h,
pre += (scaled_mv.row >> SUBPEL_BITS) * pre_buf->stride
+ (scaled_mv.col >> SUBPEL_BITS);
+#if CONFIG_MASKED_INTERINTER
+ if (ref && get_mask_bits(mi->mbmi.sb_type)
+ && mi->mbmi.use_masked_interinter) {
+ uint8_t tmp_dst[4096];
+ inter_predictor(pre, pre_buf->stride, tmp_dst, 64,
+ subpel_x, subpel_y, sf, w, h, 0, kernel, xs, ys);
+ build_masked_compound(dst, dst_buf->stride, tmp_dst, 64,
+ mi->mbmi.mask_index, mi->mbmi.sb_type, h, w);
+ } else {
+#endif
inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
subpel_x, subpel_y, sf, w, h, ref, kernel, xs, ys);
+#if CONFIG_MASKED_INTERINTER
+ }
+#endif
}
}
void vp9_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0);
+#if CONFIG_INTERINTRA
+ if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
+ is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
+ vp9_build_interintra_predictors_sby(xd, xd->plane[0].dst.buf,
+ xd->plane[0].dst.stride, bsize);
+#endif
}
void vp9_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1,
MAX_MB_PLANE - 1);
+#if CONFIG_INTERINTRA
+ if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
+ is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
+ vp9_build_interintra_predictors_sbuv(xd, xd->plane[1].dst.buf,
+ xd->plane[2].dst.buf,
+ xd->plane[1].dst.stride,
+ xd->plane[2].dst.stride, bsize);
+#endif
}
void vp9_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0,
MAX_MB_PLANE - 1);
+#if CONFIG_INTERINTRA
+ if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
+ is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
+ vp9_build_interintra_predictors(xd, xd->plane[0].dst.buf,
+ xd->plane[1].dst.buf, xd->plane[2].dst.buf,
+ xd->plane[0].dst.stride,
+ xd->plane[1].dst.stride,
+ xd->plane[2].dst.stride, bsize);
+#endif
}
// TODO(jingning): This function serves as a placeholder for decoder prediction
}
}
+#if CONFIG_MASKED_INTERINTER
+ if (ref && get_mask_bits(mi->mbmi.sb_type)
+ && mi->mbmi.use_masked_interinter) {
+ uint8_t tmp_dst[4096];
+ inter_predictor(buf_ptr, buf_stride, tmp_dst, 64,
+ subpel_x, subpel_y, sf, w, h, 0, kernel, xs, ys);
+ build_masked_compound(dst, dst_buf->stride, tmp_dst, 64,
+ mi->mbmi.mask_index, mi->mbmi.sb_type, h, w);
+ } else {
+#endif
inter_predictor(buf_ptr, buf_stride, dst, dst_buf->stride, subpel_x,
subpel_y, sf, w, h, ref, kernel, xs, ys);
+#if CONFIG_MASKED_INTERINTER
+ }
+#endif
}
}
0, 0, bw, bh, mi_x, mi_y);
}
}
+#if CONFIG_INTERINTRA
+ if (xd->mi[0]->mbmi.ref_frame[1] == INTRA_FRAME &&
+ is_interintra_allowed(xd->mi[0]->mbmi.sb_type))
+ vp9_build_interintra_predictors(xd, xd->plane[0].dst.buf,
+ xd->plane[1].dst.buf, xd->plane[2].dst.buf,
+ xd->plane[0].dst.stride,
+ xd->plane[1].dst.stride,
+ xd->plane[2].dst.stride, bsize);
+#endif
}
void vp9_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE],
const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
const struct scale_factors *sf);
+#if CONFIG_MASKED_INTERINTER
+void vp9_generate_masked_weight(int mask_index, BLOCK_SIZE sb_type,
+ int h, int w, uint8_t *mask, int stride);
+void vp9_generate_hard_mask(int mask_index, BLOCK_SIZE sb_type,
+ int h, int w, uint8_t *mask, int stride);
+#endif
+
#ifdef __cplusplus
} // extern "C"
#endif
}
}
+#if CONFIG_FILTERINTRA
+static void filter_intra_predictors_4tap(uint8_t *ypred_ptr, int y_stride,
+ int bs,
+ const uint8_t *yabove_row,
+ const uint8_t *yleft_col,
+ int mode) {
+ static const int prec_bits = 10;
+ static const int round_val = 511;
+
+ int k, r, c;
+ int pred[33][33];
+ int mean, ipred;
+
+ int taps4_4[10][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}
+ };
+ int taps4_8[10][4] = {
+ {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}
+ };
+ int taps4_16[10][4] = {
+ {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}
+ };
+ int taps4_32[10][4] = {
+ {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}
+ };
+
+ const int c1 = (bs >= 32) ? taps4_32[mode][0] : ((bs >= 16) ?
+ taps4_16[mode][0] : ((bs >= 8) ? taps4_8[mode][0] : taps4_4[mode][0]));
+ const int c2 = (bs >= 32) ? taps4_32[mode][1] : ((bs >= 16) ?
+ taps4_16[mode][1] : ((bs >= 8) ? taps4_8[mode][1] : taps4_4[mode][1]));
+ const int c3 = (bs >= 32) ? taps4_32[mode][2] : ((bs >= 16) ?
+ taps4_16[mode][2] : ((bs >= 8) ? taps4_8[mode][2] : taps4_4[mode][2]));
+ const int c4 = (bs >= 32) ? taps4_32[mode][3] : ((bs >= 16) ?
+ taps4_16[mode][3] : ((bs >= 8) ? taps4_8[mode][3] : taps4_4[mode][3]));
+
+ k = 0;
+ mean = 0;
+ while (k < bs) {
+ mean = mean + (int)yleft_col[k];
+ mean = mean + (int)yabove_row[k];
+ k++;
+ }
+ mean = (mean + bs) / (2 * bs);
+
+ for (r = 0; r < bs; r++)
+ pred[r + 1][0] = (int)yleft_col[r] - mean;
+
+ for (c = 0; c < 2 * bs + 1; c++)
+ pred[0][c] = (int)yabove_row[c - 1] - mean;
+
+ for (r = 1; r < bs + 1; r++)
+ for (c = 1; c < 2 * bs + 1 - r; c++) {
+ ipred = c1 * pred[r - 1][c] + c2 * pred[r][c - 1]
+ + c3 * pred[r - 1][c - 1] + c4 * pred[r - 1][c + 1];
+ pred[r][c] = ipred < 0 ? -((-ipred + round_val) >> prec_bits) :
+ ((ipred + round_val) >> prec_bits);
+ }
+
+ for (r = 0; r < bs; r++) {
+ for (c = 0; c < bs; c++) {
+ ipred = pred[r + 1][c + 1] + mean;
+ ypred_ptr[c] = clip_pixel(ipred);
+ }
+ ypred_ptr += y_stride;
+ }
+}
+
+static void build_filter_intra_predictors(const MACROBLOCKD *xd,
+ const uint8_t *ref, int ref_stride,
+ uint8_t *dst, int dst_stride,
+ PREDICTION_MODE mode, TX_SIZE tx_size,
+ int up_available, int left_available,
+ int right_available, int x, int y,
+ int plane) {
+ int i;
+ DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
+ DECLARE_ALIGNED_ARRAY(16, uint8_t, above_data, 128 + 16);
+ uint8_t *above_row = above_data + 16;
+ const uint8_t *const_above_row = above_row;
+ const int bs = 4 << tx_size;
+ int frame_width, frame_height;
+ int x0, y0;
+ const struct macroblockd_plane *const pd = &xd->plane[plane];
+
+ // Get current frame pointer, width and height.
+ if (plane == 0) {
+ frame_width = xd->cur_buf->y_width;
+ frame_height = xd->cur_buf->y_height;
+ } else {
+ frame_width = xd->cur_buf->uv_width;
+ frame_height = xd->cur_buf->uv_height;
+ }
+
+ // Get block position in current frame.
+ x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
+ y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
+
+ vpx_memset(left_col, 129, 64);
+
+ // 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 {
+ /* faster path if the block does not need extension */
+ for (i = 0; i < bs; ++i)
+ left_col[i] = ref[i * ref_stride - 1];
+ }
+ }
+
+ // TODO(hkuang) do not extend 2*bs pixels for all modes.
+ // above
+ if (up_available) {
+ const uint8_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) {
+ vpx_memcpy(above_row, above_ref, 2 * bs);
+ } else {
+ vpx_memcpy(above_row, above_ref, bs);
+ vpx_memset(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) {
+ vpx_memcpy(above_row, above_ref, r);
+ vpx_memset(above_row + r, above_row[r - 1],
+ x0 + 2 * bs - frame_width);
+ } else {
+ vpx_memcpy(above_row, above_ref, bs);
+ vpx_memset(above_row + bs, above_row[bs - 1], bs);
+ }
+ } else if (x0 <= frame_width) {
+ const int r = frame_width - x0;
+ if (right_available && bs == 4) {
+ vpx_memcpy(above_row, above_ref, r);
+ vpx_memset(above_row + r, above_row[r - 1],
+ x0 + 2 * bs - frame_width);
+ } else {
+ vpx_memcpy(above_row, above_ref, r);
+ vpx_memset(above_row + r, above_row[r - 1],
+ x0 + 2 * bs - frame_width);
+ }
+ }
+ above_row[-1] = left_available ? above_ref[-1] : 129;
+ } else {
+ /* faster path if the block does not need extension */
+ if (bs == 4 && right_available && left_available) {
+ const_above_row = above_ref;
+ } else {
+ vpx_memcpy(above_row, above_ref, bs);
+ if (bs == 4 && right_available)
+ vpx_memcpy(above_row + bs, above_ref + bs, bs);
+ else
+ vpx_memset(above_row + bs, above_row[bs - 1], bs);
+ above_row[-1] = left_available ? above_ref[-1] : 129;
+ }
+ }
+ } else {
+ vpx_memset(above_row, 127, bs * 2);
+ above_row[-1] = 127;
+ }
+
+ // predict
+ filter_intra_predictors_4tap(dst, dst_stride, bs, const_above_row, left_col,
+ mode);
+}
+#endif
+
void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
TX_SIZE tx_size, PREDICTION_MODE mode,
+#if CONFIG_FILTERINTRA
+ int filterbit,
+#endif
const uint8_t *ref, int ref_stride,
uint8_t *dst, int dst_stride,
int aoff, int loff, int plane) {
const int have_right = ((block_idx & wmask) != wmask);
const int x = aoff * 4;
const int y = loff * 4;
+#if CONFIG_FILTERINTRA
+ const int filterflag = is_filter_allowed(mode) && is_filter_enabled(tx_size)
+ && filterbit;
+#endif
assert(bwl >= 0);
+#if CONFIG_FILTERINTRA
+ if (!filterflag) {
+#endif
build_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode, tx_size,
have_top, have_left, have_right, x, y, plane);
+#if CONFIG_FILTERINTRA
+ } else {
+ build_filter_intra_predictors(xd, ref, ref_stride, dst, dst_stride, mode,
+ tx_size, have_top, have_left, have_right, x, y, plane);
+ }
+#endif
+}
+
+#if CONFIG_INTERINTRA
+#if CONFIG_MASKED_INTERINTRA
+#define MASK_WEIGHT_BITS_INTERINTRA 6
+
+static int get_masked_weight_interintra(int m) {
+ #define SMOOTHER_LEN_INTERINTRA 32
+ static const uint8_t smoothfn[2 * SMOOTHER_LEN_INTERINTRA + 1] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 2, 2, 3, 4, 5, 6,
+ 8, 9, 12, 14, 17, 21, 24, 28,
+ 32,
+ 36, 40, 43, 47, 50, 52, 55, 56,
+ 58, 59, 60, 61, 62, 62, 63, 63,
+ 63, 63, 63, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64,
+ };
+ if (m < -SMOOTHER_LEN_INTERINTRA)
+ return 0;
+ else if (m > SMOOTHER_LEN_INTERINTRA)
+ return (1 << MASK_WEIGHT_BITS_INTERINTRA);
+ else
+ return smoothfn[m + SMOOTHER_LEN_INTERINTRA];
+}
+
+static int get_hard_mask_interintra(int m) {
+ return m > 0;
+}
+
+// Equation of line: f(x, y) = a[0]*(x - a[2]*w/4) + a[1]*(y - a[3]*h/4) = 0
+// The soft mask is obtained by computing f(x, y) and then calling
+// get_masked_weight(f(x, y)).
+static const int mask_params_sml_interintra[1 << MASK_BITS_SML_INTERINTRA]
+ [4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+};
+
+static const int mask_params_med_hgtw_interintra[1 << MASK_BITS_MED_INTERINTRA]
+ [4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ {-1, 2, 2, 1},
+ { 1, -2, 2, 1},
+ {-1, 2, 2, 3},
+ { 1, -2, 2, 3},
+ { 1, 2, 2, 1},
+ {-1, -2, 2, 1},
+ { 1, 2, 2, 3},
+ {-1, -2, 2, 3},
+};
+
+static const int mask_params_med_hltw_interintra[1 << MASK_BITS_MED_INTERINTRA]
+ [4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ {-2, 1, 1, 2},
+ { 2, -1, 1, 2},
+ {-2, 1, 3, 2},
+ { 2, -1, 3, 2},
+ { 2, 1, 1, 2},
+ {-2, -1, 1, 2},
+ { 2, 1, 3, 2},
+ {-2, -1, 3, 2},
+};
+
+static const int mask_params_med_heqw_interintra[1 << MASK_BITS_MED_INTERINTRA]
+ [4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ { 0, 2, 0, 1},
+ { 0, -2, 0, 1},
+ { 0, 2, 0, 3},
+ { 0, -2, 0, 3},
+ { 2, 0, 1, 0},
+ {-2, 0, 1, 0},
+ { 2, 0, 3, 0},
+ {-2, 0, 3, 0},
+};
+
+static const int mask_params_big_hgtw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
+ [4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ {-1, 2, 2, 1},
+ { 1, -2, 2, 1},
+ {-1, 2, 2, 3},
+ { 1, -2, 2, 3},
+ { 1, 2, 2, 1},
+ {-1, -2, 2, 1},
+ { 1, 2, 2, 3},
+ {-1, -2, 2, 3},
+
+ {-2, 1, 1, 2},
+ { 2, -1, 1, 2},
+ {-2, 1, 3, 2},
+ { 2, -1, 3, 2},
+ { 2, 1, 1, 2},
+ {-2, -1, 1, 2},
+ { 2, 1, 3, 2},
+ {-2, -1, 3, 2},
+
+ { 0, 2, 0, 1},
+ { 0, -2, 0, 1},
+ { 0, 2, 0, 2},
+ { 0, -2, 0, 2},
+ { 0, 2, 0, 3},
+ { 0, -2, 0, 3},
+ { 2, 0, 2, 0},
+ {-2, 0, 2, 0},
+};
+
+static const int mask_params_big_hltw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
+ [4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ {-1, 2, 2, 1},
+ { 1, -2, 2, 1},
+ {-1, 2, 2, 3},
+ { 1, -2, 2, 3},
+ { 1, 2, 2, 1},
+ {-1, -2, 2, 1},
+ { 1, 2, 2, 3},
+ {-1, -2, 2, 3},
+
+ {-2, 1, 1, 2},
+ { 2, -1, 1, 2},
+ {-2, 1, 3, 2},
+ { 2, -1, 3, 2},
+ { 2, 1, 1, 2},
+ {-2, -1, 1, 2},
+ { 2, 1, 3, 2},
+ {-2, -1, 3, 2},
+
+ { 0, 2, 0, 2},
+ { 0, -2, 0, 2},
+ { 2, 0, 1, 0},
+ {-2, 0, 1, 0},
+ { 2, 0, 2, 0},
+ {-2, 0, 2, 0},
+ { 2, 0, 3, 0},
+ {-2, 0, 3, 0},
+};
+
+static const int mask_params_big_heqw_interintra[1 << MASK_BITS_BIG_INTERINTRA]
+ [4] = {
+ {-1, 2, 2, 2},
+ { 1, -2, 2, 2},
+ {-2, 1, 2, 2},
+ { 2, -1, 2, 2},
+ { 2, 1, 2, 2},
+ {-2, -1, 2, 2},
+ { 1, 2, 2, 2},
+ {-1, -2, 2, 2},
+
+ {-1, 2, 2, 1},
+ { 1, -2, 2, 1},
+ {-1, 2, 2, 3},
+ { 1, -2, 2, 3},
+ { 1, 2, 2, 1},
+ {-1, -2, 2, 1},
+ { 1, 2, 2, 3},
+ {-1, -2, 2, 3},
+
+ {-2, 1, 1, 2},
+ { 2, -1, 1, 2},
+ {-2, 1, 3, 2},
+ { 2, -1, 3, 2},
+ { 2, 1, 1, 2},
+ {-2, -1, 1, 2},
+ { 2, 1, 3, 2},
+ {-2, -1, 3, 2},
+
+ { 0, 2, 0, 1},
+ { 0, -2, 0, 1},
+ { 0, 2, 0, 3},
+ { 0, -2, 0, 3},
+ { 2, 0, 1, 0},
+ {-2, 0, 1, 0},
+ { 2, 0, 3, 0},
+ {-2, 0, 3, 0},
+};
+
+static const int *get_mask_params_interintra(int mask_index,
+ BLOCK_SIZE sb_type,
+ int h, int w) {
+ const int *a;
+ const int mask_bits = get_mask_bits_interintra(sb_type);
+
+ if (mask_index == MASK_NONE_INTERINTRA)
+ return NULL;
+
+ if (mask_bits == MASK_BITS_SML_INTERINTRA) {
+ a = mask_params_sml_interintra[mask_index];
+ } else if (mask_bits == MASK_BITS_MED_INTERINTRA) {
+ if (h > w)
+ a = mask_params_med_hgtw_interintra[mask_index];
+ else if (h < w)
+ a = mask_params_med_hltw_interintra[mask_index];
+ else
+ a = mask_params_med_heqw_interintra[mask_index];
+ } else if (mask_bits == MASK_BITS_BIG_INTERINTRA) {
+ if (h > w)
+ a = mask_params_big_hgtw_interintra[mask_index];
+ else if (h < w)
+ a = mask_params_big_hltw_interintra[mask_index];
+ else
+ a = mask_params_big_heqw_interintra[mask_index];
+ } else {
+ assert(0);
+ }
+ return a;
+}
+
+void vp9_generate_masked_weight_interintra(int mask_index,
+ BLOCK_SIZE sb_type,
+ int h, int w,
+ uint8_t *mask, int stride) {
+ int i, j;
+ const int *a = get_mask_params_interintra(mask_index, sb_type, h, w);
+ if (!a) return;
+ for (i = 0; i < h; ++i)
+ for (j = 0; j < w; ++j) {
+ int x = (j - (a[2] * w) / 4);
+ int y = (i - (a[3] * h) / 4);
+ int m = a[0] * x + a[1] * y;
+ mask[i * stride + j] = get_masked_weight_interintra(m);
+ }
+}
+
+void vp9_generate_hard_mask_interintra(int mask_index, BLOCK_SIZE sb_type,
+ int h, int w, uint8_t *mask, int stride) {
+ int i, j;
+ const int *a = get_mask_params_interintra(mask_index, sb_type, h, w);
+ if (!a) return;
+ for (i = 0; i < h; ++i)
+ for (j = 0; j < w; ++j) {
+ int x = (j - (a[2] * w) / 4);
+ int y = (i - (a[3] * h) / 4);
+ int m = a[0] * x + a[1] * y;
+ mask[i * stride + j] = get_hard_mask_interintra(m);
+ }
+}
+#endif
+
+static void combine_interintra(PREDICTION_MODE mode,
+#if CONFIG_MASKED_INTERINTRA
+ int use_masked_interintra,
+ int mask_index,
+ BLOCK_SIZE bsize,
+#endif
+ uint8_t *comppred,
+ int compstride,
+ uint8_t *interpred,
+ int interstride,
+ uint8_t *intrapred,
+ int intrastride,
+ int bw, int bh) {
+ static const int scale_bits = 8;
+ static const int scale_max = 256;
+ static const int scale_round = 127;
+ static const int weights1d[64] = {
+ 128, 125, 122, 119, 116, 114, 111, 109,
+ 107, 105, 103, 101, 99, 97, 96, 94,
+ 93, 91, 90, 89, 88, 86, 85, 84,
+ 83, 82, 81, 81, 80, 79, 78, 78,
+ 77, 76, 76, 75, 75, 74, 74, 73,
+ 73, 72, 72, 71, 71, 71, 70, 70,
+ 70, 70, 69, 69, 69, 69, 68, 68,
+ 68, 68, 68, 67, 67, 67, 67, 67,
+ };
+
+ int size = MAX(bw, bh);
+ int size_scale = (size >= 64 ? 1 :
+ size == 32 ? 2 :
+ size == 16 ? 4 :
+ size == 8 ? 8 : 16);
+ int i, j;
+
+#if CONFIG_MASKED_INTERINTRA
+ if (use_masked_interintra && get_mask_bits_interintra(bsize)) {
+ uint8_t mask[4096];
+ vp9_generate_masked_weight_interintra(mask_index, bsize, bh, bw, mask, bw);
+ for (i = 0; i < bh; ++i) {
+ for (j = 0; j < bw; ++j) {
+ int m = mask[i * bw + j];
+ comppred[i * compstride + j] =
+ (intrapred[i * intrastride + j] * m +
+ interpred[i * interstride + j] *
+ ((1 << MASK_WEIGHT_BITS_INTERINTRA) - m) +
+ (1 << (MASK_WEIGHT_BITS_INTERINTRA - 1))) >>
+ MASK_WEIGHT_BITS_INTERINTRA;
+ }
+ }
+ return;
+ }
+#endif
+
+ switch (mode) {
+ case V_PRED:
+ for (i = 0; i < bh; ++i) {
+ for (j = 0; j < bw; ++j) {
+ int scale = weights1d[i * size_scale];
+ comppred[i * compstride + j] =
+ ((scale_max - scale) * interpred[i * interstride + j] +
+ scale * intrapred[i * intrastride + j] + scale_round)
+ >> scale_bits;
+ }
+ }
+ break;
+
+ case H_PRED:
+ for (i = 0; i < bh; ++i) {
+ for (j = 0; j < bw; ++j) {
+ int scale = weights1d[j * size_scale];
+ comppred[i * compstride + j] =
+ ((scale_max - scale) * interpred[i * interstride + j] +
+ scale * intrapred[i * intrastride + j] + scale_round)
+ >> scale_bits;
+ }
+ }
+ break;
+
+ case D63_PRED:
+ case D117_PRED:
+ for (i = 0; i < bh; ++i) {
+ for (j = 0; j < bw; ++j) {
+ int scale = (weights1d[i * size_scale] * 3 +
+ weights1d[j * size_scale]) >> 2;
+ comppred[i * compstride + j] =
+ ((scale_max - scale) * interpred[i * interstride + j] +
+ scale * intrapred[i * intrastride + j] + scale_round)
+ >> scale_bits;
+ }
+ }
+ break;
+
+ case D207_PRED:
+ case D153_PRED:
+ for (i = 0; i < bh; ++i) {
+ for (j = 0; j < bw; ++j) {
+ int scale = (weights1d[j * size_scale] * 3 +
+ weights1d[i * size_scale]) >> 2;
+ comppred[i * compstride + j] =
+ ((scale_max - scale) * interpred[i * interstride + j] +
+ scale * intrapred[i * intrastride + j] + scale_round)
+ >> scale_bits;
+ }
+ }
+ break;
+
+ case D135_PRED:
+ for (i = 0; i < bh; ++i) {
+ for (j = 0; j < bw; ++j) {
+ int scale = weights1d[(i < j ? i : j) * size_scale];
+ comppred[i * compstride + j] =
+ ((scale_max - scale) * interpred[i * interstride + j] +
+ scale * intrapred[i * intrastride + j] + scale_round)
+ >> scale_bits;
+ }
+ }
+ break;
+
+ case D45_PRED:
+ for (i = 0; i < bh; ++i) {
+ for (j = 0; j < bw; ++j) {
+ int scale = (weights1d[i * size_scale] +
+ weights1d[j * size_scale]) >> 1;
+ comppred[i * compstride + j] =
+ ((scale_max - scale) * interpred[i * interstride + j] +
+ scale * intrapred[i * intrastride + j] + scale_round)
+ >> scale_bits;
+ }
+ }
+ break;
+
+ case TM_PRED:
+ case DC_PRED:
+ default:
+ for (i = 0; i < bh; ++i) {
+ for (j = 0; j < bw; ++j) {
+ comppred[i * compstride + j] = (interpred[i * interstride + j] +
+ intrapred[i * intrastride + j]) >> 1;
+ }
+ }
+ break;
+ }
+}
+
+
+static void build_intra_predictors_for_2nd_block_interintra
+ (const MACROBLOCKD *xd, const uint8_t *ref,
+ int ref_stride, uint8_t *dst, int dst_stride,
+ PREDICTION_MODE mode, TX_SIZE tx_size,
+ int up_available, int left_available,
+ int right_available, int bwltbh,
+ int x, int y, int plane) {
+ int i;
+ DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
+ DECLARE_ALIGNED_ARRAY(16, uint8_t, above_data, 128 + 16);
+ uint8_t *above_row = above_data + 16;
+ const uint8_t *const_above_row = above_row;
+ const int bs = 4 << tx_size;
+ int frame_width, frame_height;
+ int x0, y0;
+ const struct macroblockd_plane *const pd = &xd->plane[plane];
+ const uint8_t *ref_fi;
+ int ref_stride_fi;
+
+ // 127 127 127 .. 127 127 127 127 127 127
+ // 129 A B .. Y Z
+ // 129 C D .. W X
+ // 129 E F .. U V
+ // 129 G H .. S T T T T T
+ // ..
+
+ once(init_intra_pred_fn_ptrs);
+
+ // Get current frame pointer, width and height.
+ if (plane == 0) {
+ frame_width = xd->cur_buf->y_width;
+ frame_height = xd->cur_buf->y_height;
+ } else {
+ frame_width = xd->cur_buf->uv_width;
+ frame_height = xd->cur_buf->uv_height;
+ }
+
+ // Get block position in current frame.
+ x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
+ y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
+
+ vpx_memset(left_col, 129, 64);
+
+ // left
+ if (left_available) {
+ if (bwltbh) {
+ ref_fi = ref;
+ ref_stride_fi = ref_stride;
+ } else {
+ ref_fi = dst;
+ ref_stride_fi = dst_stride;
+ }
+ 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_fi[i * ref_stride_fi - 1];
+ } else {
+ const int extend_bottom = frame_height - y0;
+ assert(extend_bottom >= 0);
+ for (i = 0; i < extend_bottom; ++i)
+ left_col[i] = ref_fi[i * ref_stride_fi - 1];
+ for (; i < bs; ++i)
+ left_col[i] = ref_fi[(extend_bottom - 1) * ref_stride_fi - 1];
+ }
+ } else {
+ /* faster path if the block does not need extension */
+ for (i = 0; i < bs; ++i)
+ left_col[i] = ref_fi[i * ref_stride_fi - 1];
+ }
+ }
+
+ // TODO(hkuang) do not extend 2*bs pixels for all modes.
+ // above
+ if (up_available) {
+ const uint8_t *above_ref;
+ if (bwltbh) {
+ ref_fi = dst;
+ ref_stride_fi = dst_stride;
+ above_row[-1] = left_available ? ref[-ref_stride-1] : 129;
+ } else {
+ ref_fi = ref;
+ ref_stride_fi = ref_stride;
+ above_row[-1] = ref[-ref_stride-1];
+ }
+ above_ref = ref_fi - ref_stride_fi;
+ 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) {
+ vpx_memcpy(above_row, above_ref, 2 * bs);
+ } else {
+ vpx_memcpy(above_row, above_ref, bs);
+ vpx_memset(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) {
+ vpx_memcpy(above_row, above_ref, r);
+ vpx_memset(above_row + r, above_row[r - 1],
+ x0 + 2 * bs - frame_width);
+ } else {
+ vpx_memcpy(above_row, above_ref, bs);
+ vpx_memset(above_row + bs, above_row[bs - 1], bs);
+ }
+ } else if (x0 <= frame_width) {
+ const int r = frame_width - x0;
+ assert(r >= 0);
+ if (right_available && bs == 4) {
+ vpx_memcpy(above_row, above_ref, r);
+ vpx_memset(above_row + r, above_row[r - 1],
+ x0 + 2 * bs - frame_width);
+ } else {
+ vpx_memcpy(above_row, above_ref, r);
+ vpx_memset(above_row + r, above_row[r - 1],
+ x0 + 2 * 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 {
+ vpx_memcpy(above_row, above_ref, bs);
+ if (bs == 4 && right_available)
+ vpx_memcpy(above_row + bs, above_ref + bs, bs);
+ else
+ vpx_memset(above_row + bs, above_row[bs - 1], bs);
+ }
+ }
+ } else {
+ vpx_memset(above_row, 127, bs * 2);
+ above_row[-1] = 127;
+ }
+
+ // predict
+ if (mode == DC_PRED) {
+ dc_pred[left_available][up_available][tx_size](dst, dst_stride,
+ const_above_row, left_col);
+ } else {
+ pred[mode][tx_size](dst, dst_stride, const_above_row, left_col);
+ }
+}
+
+// Break down rectangular intra prediction for joint spatio-temporal prediction
+// into two square intra predictions.
+static void build_intra_predictors_for_interintra(MACROBLOCKD *xd,
+ uint8_t *src, int src_stride,
+ uint8_t *pred_ptr, int stride,
+ PREDICTION_MODE mode,
+ int bw, int bh,
+ int up_available, int left_available,
+ int right_available, int plane) {
+ if (bw == bh) {
+ build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
+ mode, intra_size_log2_for_interintra(bw),
+ up_available, left_available, right_available,
+ 0, 0, plane);
+ } else if (bw < bh) {
+ uint8_t *src_bottom = src + bw * src_stride;
+ uint8_t *pred_ptr_bottom = pred_ptr + bw * stride;
+ build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
+ mode, intra_size_log2_for_interintra(bw),
+ up_available, left_available, right_available,
+ 0, 0, plane);
+ build_intra_predictors_for_2nd_block_interintra(xd, src_bottom, src_stride,
+ pred_ptr_bottom, stride,
+ mode, intra_size_log2_for_interintra(bw),
+ up_available, left_available, 0, 1,
+ 0, bw, plane);
+ } else {
+ uint8_t *src_right = src + bh;
+ uint8_t *pred_ptr_right = pred_ptr + bh;
+ build_intra_predictors(xd, src, src_stride, pred_ptr, stride,
+ mode, intra_size_log2_for_interintra(bh),
+ up_available, left_available, 1,
+ 0, 0, plane);
+ build_intra_predictors_for_2nd_block_interintra(xd, src_right, src_stride,
+ pred_ptr_right, stride,
+ mode, intra_size_log2_for_interintra(bh),
+ up_available, left_available, right_available, 0,
+ bh, 0, plane);
+ }
+}
+
+void vp9_build_interintra_predictors_sby(MACROBLOCKD *xd,
+ uint8_t *ypred,
+ int ystride,
+ BLOCK_SIZE bsize) {
+ int bw = 4 << b_width_log2(bsize);
+ int bh = 4 << b_height_log2(bsize);
+ uint8_t intrapredictor[4096];
+ build_intra_predictors_for_interintra(
+ xd, xd->plane[0].dst.buf, xd->plane[0].dst.stride,
+ intrapredictor, bw,
+ xd->mi[0]->mbmi.interintra_mode, bw, bh,
+ xd->up_available, xd->left_available, 0, 0);
+ combine_interintra(xd->mi[0]->mbmi.interintra_mode,
+#if CONFIG_MASKED_INTERINTRA
+ xd->mi[0]->mbmi.use_masked_interintra,
+ xd->mi[0]->mbmi.interintra_mask_index,
+ bsize,
+#endif
+ xd->plane[0].dst.buf, xd->plane[0].dst.stride,
+ ypred, ystride, intrapredictor, bw, bw, bh);
+}
+
+void vp9_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
+ uint8_t *upred,
+ uint8_t *vpred,
+ int ustride, int vstride,
+ BLOCK_SIZE bsize) {
+ int bwl = b_width_log2(bsize), bw = 2 << bwl;
+ int bhl = b_height_log2(bsize), bh = 2 << bhl;
+ uint8_t uintrapredictor[1024];
+ uint8_t vintrapredictor[1024];
+ build_intra_predictors_for_interintra(
+ xd, xd->plane[1].dst.buf, xd->plane[1].dst.stride,
+ uintrapredictor, bw,
+ xd->mi[0]->mbmi.interintra_uv_mode, bw, bh,
+ xd->up_available, xd->left_available, 0, 1);
+ build_intra_predictors_for_interintra(
+ xd, xd->plane[2].dst.buf, xd->plane[1].dst.stride,
+ vintrapredictor, bw,
+ xd->mi[0]->mbmi.interintra_uv_mode, bw, bh,
+ xd->up_available, xd->left_available, 0, 2);
+ combine_interintra(xd->mi[0]->mbmi.interintra_uv_mode,
+#if CONFIG_MASKED_INTERINTRA
+ xd->mi[0]->mbmi.use_masked_interintra,
+ xd->mi[0]->mbmi.interintra_uv_mask_index,
+ bsize,
+#endif
+ xd->plane[1].dst.buf, xd->plane[1].dst.stride,
+ upred, ustride, uintrapredictor, bw, bw, bh);
+ combine_interintra(xd->mi[0]->mbmi.interintra_uv_mode,
+#if CONFIG_MASKED_INTERINTRA
+ xd->mi[0]->mbmi.use_masked_interintra,
+ xd->mi[0]->mbmi.interintra_uv_mask_index,
+ bsize,
+#endif
+ xd->plane[2].dst.buf, xd->plane[2].dst.stride,
+ vpred, vstride, vintrapredictor, bw, bw, bh);
+}
+
+void vp9_build_interintra_predictors(MACROBLOCKD *xd,
+ uint8_t *ypred,
+ uint8_t *upred,
+ uint8_t *vpred,
+ int ystride, int ustride, int vstride,
+ BLOCK_SIZE bsize) {
+ vp9_build_interintra_predictors_sby(xd, ypred, ystride, bsize);
+ vp9_build_interintra_predictors_sbuv(xd, upred, vpred,
+ ustride, vstride, bsize);
}
+#endif
void vp9_predict_intra_block(const MACROBLOCKD *xd, int block_idx, int bwl_in,
TX_SIZE tx_size, PREDICTION_MODE mode,
+#if CONFIG_FILTERINTRA
+ int filterbit,
+#endif
const uint8_t *ref, int ref_stride,
uint8_t *dst, int dst_stride,
int aoff, int loff, int plane);
+#if CONFIG_INTERINTRA
+void vp9_build_interintra_predictors(MACROBLOCKD *xd,
+ uint8_t *ypred,
+ uint8_t *upred,
+ uint8_t *vpred,
+ int ystride,
+ int ustride,
+ int vstride,
+ BLOCK_SIZE bsize);
+void vp9_build_interintra_predictors_sby(MACROBLOCKD *xd,
+ uint8_t *ypred,
+ int ystride,
+ BLOCK_SIZE bsize);
+void vp9_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
+ uint8_t *upred,
+ uint8_t *vpred,
+ int ustride, int vstride,
+ BLOCK_SIZE bsize);
+#if CONFIG_MASKED_INTERINTRA
+void vp9_generate_masked_weight_interintra(int mask_index,
+ BLOCK_SIZE sb_type,
+ int h, int w,
+ uint8_t *mask, int stride);
+#endif
+#endif
#ifdef __cplusplus
} // extern "C"
#endif
add_proto qw/unsigned int vp9_sub_pixel_avg_variance8x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse, const uint8_t *second_pred";
specialize qw/vp9_sub_pixel_avg_variance8x8/, "$sse2_x86inc", "$ssse3_x86inc";
+if ((vpx_config("CONFIG_MASKED_INTERINTER") eq "yes") || ((vpx_config("CONFIG_INTERINTRA") eq "yes") && (vpx_config("CONFIG_MASKED_INTERINTRA") eq "yes"))) {
+add_proto qw/unsigned int vp9_masked_variance32x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance32x16/;
+
+add_proto qw/unsigned int vp9_masked_variance16x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masdctked_variance16x32/;
+
+add_proto qw/unsigned int vp9_masked_variance64x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance64x32/;
+
+add_proto qw/unsigned int vp9_masked_variance32x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance32x64/;
+
+add_proto qw/unsigned int vp9_masked_variance32x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance32x32/;
+
+add_proto qw/unsigned int vp9_masked_variance64x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance64x64/;
+
+add_proto qw/unsigned int vp9_masked_variance16x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance16x16/;
+
+add_proto qw/unsigned int vp9_masked_variance16x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance16x8/;
+
+add_proto qw/unsigned int vp9_masked_variance8x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance8x16/;
+
+add_proto qw/unsigned int vp9_masked_variance8x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance8x8/;
+
+add_proto qw/unsigned int vp9_masked_variance8x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance8x4/;
+
+add_proto qw/unsigned int vp9_masked_variance4x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance4x8/;
+
+add_proto qw/unsigned int vp9_masked_variance4x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_variance4x4/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance64x64/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance64x64/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x64/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance32x64/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance64x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance64x32/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance32x16/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance16x32/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance32x32/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance32x32/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance16x16/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x16/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance8x16/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance16x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance16x8/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance8x8/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance8x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance8x4/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance4x8/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance4x8/;
+
+add_proto qw/unsigned int vp9_masked_sub_pixel_variance4x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride, unsigned int *sse";
+specialize qw/vp9_masked_sub_pixel_variance4x4/;
+
+add_proto qw/unsigned int vp9_masked_sad64x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad64x64/;
+
+add_proto qw/unsigned int vp9_masked_sad32x64/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad32x64/;
+
+add_proto qw/unsigned int vp9_masked_sad64x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad64x32/;
+
+add_proto qw/unsigned int vp9_masked_sad32x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad32x16/;
+
+add_proto qw/unsigned int vp9_masked_sad16x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad16x32/;
+
+add_proto qw/unsigned int vp9_masked_sad32x32/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad32x32/;
+
+add_proto qw/unsigned int vp9_masked_sad16x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad16x16/;
+
+add_proto qw/unsigned int vp9_masked_sad16x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad16x8/;
+
+add_proto qw/unsigned int vp9_masked_sad8x16/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad8x16/;
+
+add_proto qw/unsigned int vp9_masked_sad8x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad8x8/;
+
+add_proto qw/unsigned int vp9_masked_sad8x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad8x4/;
+
+add_proto qw/unsigned int vp9_masked_sad4x8/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad4x8/;
+
+add_proto qw/unsigned int vp9_masked_sad4x4/, "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, const uint8_t *mask, int mask_stride";
+specialize qw/vp9_masked_sad4x4/;
+}
+
# TODO(jingning): need to convert 8x4/4x8 functions into mmx/sse form
add_proto qw/unsigned int vp9_sub_pixel_variance8x4/, "const uint8_t *src_ptr, int source_stride, int xoffset, int yoffset, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse";
specialize qw/vp9_sub_pixel_variance8x4/, "$sse2_x86inc", "$ssse3_x86inc";
: mi->mbmi.uv_mode;
int x, y;
uint8_t *dst;
+#if CONFIG_FILTERINTRA
+ int fbit;
+ if (plane == 0)
+ if (mi->mbmi.sb_type < BLOCK_8X8)
+ fbit = mi->b_filter_info[block];
+ else
+ fbit = is_filter_enabled(tx_size) ? mi->mbmi.filterbit : 0;
+ else
+ fbit = is_filter_enabled(tx_size) ? mi->mbmi.uv_filterbit : 0;
+#endif
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &x, &y);
dst = &pd->dst.buf[4 * y * pd->dst.stride + 4 * x];
vp9_predict_intra_block(xd, block >> (tx_size << 1),
b_width_log2(plane_bsize), tx_size, mode,
+#if CONFIG_FILTERINTRA
+ fbit,
+#endif
dst, pd->dst.stride, dst, pd->dst.stride,
x, y, plane);
vp9_diff_update_prob(&r, &fc->partition_prob[j][i]);
read_mv_probs(nmvc, cm->allow_high_precision_mv, &r);
+
+#if CONFIG_EXT_TX
+ vp9_diff_update_prob(&r, &fc->ext_tx_prob);
+#endif
+
+#if CONFIG_MASKED_INTERINTER
+ if (cm->reference_mode != SINGLE_REFERENCE) {
+ cm->use_masked_interinter = vp9_read_bit(&r);
+ if (cm->use_masked_interinter) {
+ for (i = 0; i < BLOCK_SIZES; i++) {
+ if (get_mask_bits(i))
+ vp9_diff_update_prob(&r, &fc->masked_interinter_prob[i]);
+ }
+ }
+ } else {
+ cm->use_masked_interinter = 0;
+ }
+#endif
+
+#if CONFIG_INTERINTRA
+ if (cm->reference_mode != COMPOUND_REFERENCE) {
+ cm->use_interintra = vp9_read_bit(&r);
+ if (cm->use_interintra) {
+ for (i = 0; i < BLOCK_SIZES; i++) {
+ if (is_interintra_allowed(i)) {
+ vp9_diff_update_prob(&r, &fc->interintra_prob[i]);
+ }
+ }
+#if CONFIG_MASKED_INTERINTRA
+ cm->use_masked_interintra = vp9_read_bit(&r);
+ if (cm->use_masked_interintra) {
+ for (i = 0; i < BLOCK_SIZES; i++) {
+ if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
+ vp9_diff_update_prob(&r, &fc->masked_interintra_prob[i]);
+ }
+ }
+ } else {
+ cm->use_masked_interintra = 0;
+#endif
+ }
+ } else {
+ cm->use_interintra = 0;
+#if CONFIG_MASKED_INTERINTRA
+ cm->use_masked_interintra = 0;
+#endif
+ }
+#endif
}
return vp9_reader_has_error(&r);
assert(!memcmp(&cm->counts.tx, &zero_counts.tx, sizeof(cm->counts.tx)));
assert(!memcmp(cm->counts.skip, zero_counts.skip, sizeof(cm->counts.skip)));
assert(!memcmp(&cm->counts.mv, &zero_counts.mv, sizeof(cm->counts.mv)));
+#if CONFIG_EXT_TX
+ assert(!memcmp(cm->counts.ext_tx, zero_counts.ext_tx,
+ sizeof(cm->counts.ext_tx)));
+#endif
}
#endif // NDEBUG
switch (bsize) {
case BLOCK_4X4:
+#if !CONFIG_FILTERINTRA
for (i = 0; i < 4; ++i)
+#else
+ for (i = 0; i < 4; ++i) {
+#endif
mi->bmi[i].as_mode =
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, i));
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[i].as_mode))
+ mi->b_filter_info[i] =
+ vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[i].as_mode]);
+ else
+ mi->b_filter_info[i] = 0;
+ }
+ mbmi->filterbit = mi->b_filter_info[3];
+#endif
mbmi->mode = mi->bmi[3].as_mode;
break;
case BLOCK_4X8:
mi->bmi[0].as_mode = mi->bmi[2].as_mode =
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0));
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[0].as_mode))
+ mi->b_filter_info[0] = mi->b_filter_info[2] =
+ vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
+ else
+ mi->b_filter_info[0] = mi->b_filter_info[2] = 0;
+#endif
mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode =
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 1));
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[1].as_mode))
+ mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit =
+ vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[1].as_mode]);
+ else
+ mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit = 0;
+#endif
break;
case BLOCK_8X4:
mi->bmi[0].as_mode = mi->bmi[1].as_mode =
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 0));
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[0].as_mode))
+ mi->b_filter_info[0] = mi->b_filter_info[1] =
+ vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
+ else
+ mi->b_filter_info[0] = mi->b_filter_info[1] = 0;
+#endif
mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode =
read_intra_mode(r, get_y_mode_probs(mi, above_mi, left_mi, 2));
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[2].as_mode))
+ mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit =
+ vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[2].as_mode]);
+ else
+ mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit = 0;
+#endif
break;
default:
mbmi->mode = read_intra_mode(r,
get_y_mode_probs(mi, above_mi, left_mi, 0));
+#if CONFIG_FILTERINTRA
+ if (is_filter_enabled(mbmi->tx_size) && is_filter_allowed(mbmi->mode))
+ mbmi->filterbit = vp9_read(r,
+ cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
+ else
+ mbmi->filterbit = 0;
+#endif
}
mbmi->uv_mode = read_intra_mode(r, vp9_kf_uv_mode_prob[mbmi->mode]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_enabled(get_uv_tx_size(mbmi)) &&
+ is_filter_allowed(mbmi->uv_mode))
+ mbmi->uv_filterbit = vp9_read(r,
+ cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
+ else
+ mbmi->uv_filterbit = 0;
+#endif
}
static int read_mv_component(vp9_reader *r,
switch (bsize) {
case BLOCK_4X4:
+#if !CONFIG_FILTERINTRA
for (i = 0; i < 4; ++i)
+#else
+ for (i = 0; i < 4; ++i) {
+#endif
mi->bmi[i].as_mode = read_intra_mode_y(cm, r, 0);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[i].as_mode)) {
+ mi->b_filter_info[i] =
+ vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[i].as_mode]);
+ cm->counts.filterintra[0][mi->bmi[i].as_mode]
+ [mi->b_filter_info[i]]++;
+ } else {
+ mi->b_filter_info[i] = 0;
+ }
+ }
+ mbmi->filterbit = mi->b_filter_info[3];
+#endif
mbmi->mode = mi->bmi[3].as_mode;
break;
case BLOCK_4X8:
mi->bmi[0].as_mode = mi->bmi[2].as_mode = read_intra_mode_y(cm, r, 0);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[0].as_mode)) {
+ mi->b_filter_info[0] = mi->b_filter_info[2] =
+ vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
+ cm->counts.filterintra[0][mi->bmi[0].as_mode][mi->b_filter_info[0]]++;
+ } else {
+ mi->b_filter_info[0] = mi->b_filter_info[2] = 0;
+ }
+#endif
mi->bmi[1].as_mode = mi->bmi[3].as_mode = mbmi->mode =
read_intra_mode_y(cm, r, 0);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[1].as_mode)) {
+ mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit =
+ vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[1].as_mode]);
+ cm->counts.filterintra[0][mi->bmi[1].as_mode][mi->b_filter_info[1]]++;
+ } else {
+ mi->b_filter_info[1] = mi->b_filter_info[3] = mbmi->filterbit = 0;
+ }
+#endif
break;
case BLOCK_8X4:
mi->bmi[0].as_mode = mi->bmi[1].as_mode = read_intra_mode_y(cm, r, 0);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[0].as_mode)) {
+ mi->b_filter_info[0] = mi->b_filter_info[1] =
+ vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[0].as_mode]);
+ cm->counts.filterintra[0][mi->bmi[0].as_mode][mi->b_filter_info[0]]++;
+ } else {
+ mi->b_filter_info[0] = mi->b_filter_info[1] = 0;
+ }
+#endif
mi->bmi[2].as_mode = mi->bmi[3].as_mode = mbmi->mode =
read_intra_mode_y(cm, r, 0);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[2].as_mode)) {
+ mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit =
+ vp9_read(r, cm->fc.filterintra_prob[0][mi->bmi[2].as_mode]);
+ cm->counts.filterintra[0][mi->bmi[2].as_mode][mi->b_filter_info[2]]++;
+ } else {
+ mi->b_filter_info[2] = mi->b_filter_info[3] = mbmi->filterbit = 0;
+ }
+#endif
break;
default:
mbmi->mode = read_intra_mode_y(cm, r, size_group_lookup[bsize]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size)) {
+ mbmi->filterbit = vp9_read(r,
+ cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
+ cm->counts.filterintra[mbmi->tx_size][mbmi->mode][mbmi->filterbit]++;
+ } else {
+ mbmi->filterbit = 0;
+ }
+#endif
}
mbmi->uv_mode = read_intra_mode_uv(cm, r, mbmi->mode);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mbmi->uv_mode) &&
+ is_filter_enabled(get_uv_tx_size(mbmi))) {
+ mbmi->uv_filterbit = vp9_read(r,
+ cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
+ cm->counts.filterintra[get_uv_tx_size(mbmi)]
+ [mbmi->uv_mode][mbmi->uv_filterbit]++;
+ } else {
+ mbmi->uv_filterbit = 0;
+ }
+#endif
}
static INLINE int is_mv_valid(const MV *mv) {
read_ref_frames(cm, xd, r, mbmi->segment_id, mbmi->ref_frame);
is_compound = has_second_ref(mbmi);
+#if CONFIG_EXT_TX
+ if (mbmi->tx_size <= TX_16X16 &&
+ bsize >= BLOCK_8X8 &&
+ !vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP) &&
+ !mbmi->skip) {
+ mbmi->ext_txfrm = vp9_read(r, cm->fc.ext_tx_prob);
+ if (!cm->frame_parallel_decoding_mode)
+ ++cm->counts.ext_tx[mbmi->ext_txfrm];
+ } else {
+ mbmi->ext_txfrm = NORM;
+ }
+#endif
+
for (ref = 0; ref < 1 + is_compound; ++ref) {
const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
vp9_find_mv_refs(cm, xd, tile, mi, frame, mbmi->ref_mvs[frame],
? read_switchable_interp_filter(cm, xd, r)
: cm->interp_filter;
+#if CONFIG_INTERINTRA
+ if ((cm->use_interintra) &&
+ is_interintra_allowed(bsize) &&
+ is_inter_mode(mbmi->mode) &&
+ (mbmi->ref_frame[1] <= INTRA_FRAME)) {
+ mbmi->ref_frame[1] = vp9_read(r, cm->fc.interintra_prob[bsize]) ?
+ INTRA_FRAME : NONE;
+ cm->counts.interintra[bsize][mbmi->ref_frame[1] == INTRA_FRAME]++;
+#if CONFIG_MASKED_INTERINTRA
+ mbmi->use_masked_interintra = 0;
+#endif
+ if (mbmi->ref_frame[1] == INTRA_FRAME) {
+ mbmi->interintra_mode =
+ read_intra_mode_y(cm, r, size_group_lookup[bsize]);
+ mbmi->interintra_uv_mode = mbmi->interintra_mode;
+#if CONFIG_MASKED_INTERINTRA
+ if (cm->use_masked_interintra && get_mask_bits_interintra(bsize)) {
+ mbmi->use_masked_interintra = vp9_read(r,
+ cm->fc.masked_interintra_prob[bsize]);
+ cm->counts.masked_interintra[bsize][mbmi->use_masked_interintra]++;
+ if (mbmi->use_masked_interintra) {
+ mbmi->interintra_mask_index = vp9_read_literal(r,
+ get_mask_bits_interintra(bsize));
+ mbmi->interintra_uv_mask_index = mbmi->interintra_mask_index;
+ }
+ }
+#endif
+ }
+ }
+#endif
+
if (bsize < BLOCK_8X8) {
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize]; // 1 or 2
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize]; // 1 or 2
xd->corrupted |= !assign_mv(cm, mbmi->mode, mbmi->mv, nearestmv,
nearestmv, nearmv, is_compound, allow_hp, r);
}
+#if CONFIG_MASKED_INTERINTER
+ mbmi->use_masked_interinter = 0;
+ if (cm->use_masked_interinter &&
+ cm->reference_mode != SINGLE_REFERENCE &&
+ is_inter_mode(mbmi->mode) &&
+ get_mask_bits(bsize) &&
+ mbmi->ref_frame[1] > INTRA_FRAME) {
+ mbmi->use_masked_interinter =
+ vp9_read(r, cm->fc.masked_interinter_prob[bsize]);
+ cm->counts.masked_interinter[bsize][mbmi->use_masked_interinter]++;
+ if (mbmi->use_masked_interinter) {
+ mbmi->mask_index = vp9_read_literal(r, get_mask_bits(bsize));
+ }
+ }
+#endif
}
static void read_inter_frame_mode_info(VP9_COMMON *const cm,
if (!is_inter) {
if (bsize >= BLOCK_8X8) {
write_intra_mode(w, mode, cm->fc.y_mode_prob[size_group_lookup[bsize]]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mode) && is_filter_enabled(mbmi->tx_size)) {
+ vp9_write(w, mbmi->filterbit,
+ cm->fc.filterintra_prob[mbmi->tx_size][mode]);
+ }
+#endif
} else {
int idx, idy;
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
for (idx = 0; idx < 2; idx += num_4x4_w) {
const PREDICTION_MODE b_mode = mi->bmi[idy * 2 + idx].as_mode;
write_intra_mode(w, b_mode, cm->fc.y_mode_prob[0]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(b_mode)) {
+ vp9_write(w, mi->b_filter_info[idy * 2 + idx],
+ cm->fc.filterintra_prob[0][b_mode]);
+ }
+#endif
}
}
}
write_intra_mode(w, mbmi->uv_mode, cm->fc.uv_mode_prob[mode]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mbmi->uv_mode) &&
+ is_filter_enabled(get_uv_tx_size(mbmi))) {
+ vp9_write(w, mbmi->uv_filterbit,
+ cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
+ }
+#endif
} else {
const int mode_ctx = mbmi->mode_context[mbmi->ref_frame[0]];
const vp9_prob *const inter_probs = cm->fc.inter_mode_probs[mode_ctx];
write_ref_frames(cpi, w);
+#if CONFIG_EXT_TX
+ if (mbmi->tx_size <= TX_16X16 &&
+ bsize >= BLOCK_8X8 &&
+ !mbmi->skip &&
+ !vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
+ vp9_write(w, mbmi->ext_txfrm, cm->fc.ext_tx_prob);
+ }
+#endif
+
// If segment skip is not enabled code the mode.
if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)) {
if (bsize >= BLOCK_8X8) {
assert(mbmi->interp_filter == cm->interp_filter);
}
+#if CONFIG_INTERINTRA
+ if ((cm->use_interintra) &&
+ cpi->common.reference_mode != COMPOUND_REFERENCE &&
+ is_interintra_allowed(bsize) &&
+ is_inter_mode(mode) &&
+ (mbmi->ref_frame[1] <= INTRA_FRAME)) {
+ vp9_write(w, mbmi->ref_frame[1] == INTRA_FRAME,
+ cm->fc.interintra_prob[bsize]);
+ if (mbmi->ref_frame[1] == INTRA_FRAME) {
+ write_intra_mode(w, mbmi->interintra_mode,
+ cm->fc.y_mode_prob[size_group_lookup[bsize]]);
+#if CONFIG_MASKED_INTERINTRA
+ if (get_mask_bits_interintra(bsize) &&
+ cm->use_masked_interintra) {
+ vp9_write(w, mbmi->use_masked_interintra,
+ cm->fc.masked_interintra_prob[bsize]);
+ if (mbmi->use_masked_interintra) {
+ vp9_write_literal(w, mbmi->interintra_mask_index,
+ get_mask_bits_interintra(bsize));
+ }
+ }
+#endif
+ }
+ }
+#endif
+
if (bsize < BLOCK_8X8) {
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
allow_hp);
}
}
+#if CONFIG_MASKED_INTERINTER
+ if (cm->use_masked_interinter &&
+ cm->reference_mode != SINGLE_REFERENCE &&
+ is_inter_mode(mode) &&
+ get_mask_bits(mbmi->sb_type) &&
+ mbmi->ref_frame[1] > INTRA_FRAME) {
+ vp9_write(w, mbmi->use_masked_interinter,
+ cm->fc.masked_interinter_prob[bsize]);
+ if (mbmi->use_masked_interinter)
+ vp9_write_literal(w, mbmi->mask_index, get_mask_bits(mbmi->sb_type));
+ }
+#endif
}
}
if (bsize >= BLOCK_8X8) {
write_intra_mode(w, mbmi->mode, get_y_mode_probs(mi, above_mi, left_mi, 0));
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size))
+ vp9_write(w, mbmi->filterbit,
+ cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode]);
+#endif
} else {
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
const int block = idy * 2 + idx;
write_intra_mode(w, mi->bmi[block].as_mode,
get_y_mode_probs(mi, above_mi, left_mi, block));
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[block].as_mode))
+ vp9_write(w, mi->b_filter_info[block],
+ cm->fc.filterintra_prob[0][mi->bmi[block].as_mode]);
+#endif
}
}
}
write_intra_mode(w, mbmi->uv_mode, vp9_kf_uv_mode_prob[mbmi->mode]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mbmi->uv_mode) &&
+ is_filter_enabled(get_uv_tx_size(mbmi)))
+ vp9_write(w, mbmi->uv_filterbit,
+ cm->fc.filterintra_prob[get_uv_tx_size(mbmi)][mbmi->uv_mode]);
+#endif
}
static void write_modes_b(VP9_COMP *cpi, const TileInfo *const tile,
cm->counts.partition[i], PARTITION_TYPES, &header_bc);
vp9_write_nmv_probs(cm, cm->allow_high_precision_mv, &header_bc);
+
+#if CONFIG_EXT_TX
+ vp9_cond_prob_diff_update(&header_bc, &fc->ext_tx_prob, cm->counts.ext_tx);
+#endif
+
+#if CONFIG_MASKED_INTERINTER
+ if (cm->reference_mode != SINGLE_REFERENCE) {
+ if (!cpi->dummy_packing && cm->use_masked_interinter) {
+ cm->use_masked_interinter = 0;
+ for (i = 0; i < BLOCK_SIZES; i++)
+ if (get_mask_bits(i) && (cm->counts.masked_interinter[i][1] > 0)) {
+ cm->use_masked_interinter = 1;
+ break;
+ }
+ }
+ vp9_write_bit(&header_bc, cm->use_masked_interinter);
+ if (cm->use_masked_interinter) {
+ for (i = 0; i < BLOCK_SIZES; i++)
+ if (get_mask_bits(i))
+ vp9_cond_prob_diff_update(&header_bc,
+ &fc->masked_interinter_prob[i],
+ cm->counts.masked_interinter[i]);
+ } else {
+ vp9_zero(cm->counts.masked_interinter);
+ }
+ } else {
+ if (!cpi->dummy_packing)
+ cm->use_masked_interinter = 0;
+ vp9_zero(cm->counts.masked_interinter);
+ }
+#endif
+
+#if CONFIG_INTERINTRA
+ if (cm->reference_mode != COMPOUND_REFERENCE) {
+ if (!cpi->dummy_packing && cm->use_interintra) {
+ cm->use_interintra = 0;
+ for (i = 0; i < BLOCK_SIZES; i++) {
+ if (is_interintra_allowed(i) && (cm->counts.interintra[i][1] > 0)) {
+ cm->use_interintra = 1;
+ break;
+ }
+ }
+ }
+ vp9_write_bit(&header_bc, cm->use_interintra);
+ if (cm->use_interintra) {
+ for (i = 0; i < BLOCK_SIZES; i++) {
+ if (is_interintra_allowed(i)) {
+ vp9_cond_prob_diff_update(&header_bc,
+ &fc->interintra_prob[i],
+ cm->counts.interintra[i]);
+ }
+ }
+#if CONFIG_MASKED_INTERINTRA
+ if (!cpi->dummy_packing && cm->use_masked_interintra) {
+ cm->use_masked_interintra = 0;
+ for (i = 0; i < BLOCK_SIZES; i++) {
+ if (is_interintra_allowed(i) && get_mask_bits_interintra(i) &&
+ (cm->counts.masked_interintra[i][1] > 0)) {
+ cm->use_masked_interintra = 1;
+ break;
+ }
+ }
+ }
+ vp9_write_bit(&header_bc, cm->use_masked_interintra);
+ if (cm->use_masked_interintra) {
+ for (i = 0; i < BLOCK_SIZES; i++) {
+ if (is_interintra_allowed(i) && get_mask_bits_interintra(i))
+ vp9_cond_prob_diff_update(&header_bc,
+ &fc->masked_interintra_prob[i],
+ cm->counts.masked_interintra[i]);
+ }
+ } else {
+ vp9_zero(cm->counts.masked_interintra);
+ }
+#endif
+ } else {
+ vp9_zero(cm->counts.interintra);
+ }
+ } else {
+ if (!cpi->dummy_packing)
+ cm->use_interintra = 0;
+ vp9_zero(cm->counts.interintra);
+#if CONFIG_MASKED_INTERINTRA
+ if (!cpi->dummy_packing)
+ cm->use_masked_interintra = 0;
+ vp9_zero(cm->counts.masked_interintra);
+#endif
+ }
+#endif
}
vp9_stop_encode(&header_bc);
vp9_setup_pre_planes(xd, 0, yv12, mi_row, mi_col, sf);
xd->mi[0]->mbmi.ref_frame[0] = LAST_FRAME;
+#if CONFIG_INTERINTRA
+ xd->mi[0]->mbmi.ref_frame[1] = NONE;
+#endif
xd->mi[0]->mbmi.sb_type = BLOCK_64X64;
vp9_find_best_ref_mvs(xd, cm->allow_high_precision_mv,
xd->mi[0]->mbmi.ref_mvs[LAST_FRAME],
const int ctx = vp9_get_pred_context_switchable_interp(xd);
++cm->counts.switchable_interp[ctx][mbmi->interp_filter];
}
+#if CONFIG_MASKED_INTERINTER
+ if (cm->use_masked_interinter &&
+ cm->reference_mode != SINGLE_REFERENCE &&
+ get_mask_bits(bsize) &&
+ mbmi->ref_frame[1] > INTRA_FRAME)
+ ++cm->counts.masked_interinter[bsize][mbmi->use_masked_interinter];
+#endif
+
+#if CONFIG_INTERINTRA
+ if (cm->use_interintra &&
+ is_interintra_allowed(bsize) &&
+ is_inter_mode(mbmi->mode) &&
+ (mbmi->ref_frame[1] <= INTRA_FRAME)) {
+ if (mbmi->ref_frame[1] == INTRA_FRAME) {
+ ++cm->counts.y_mode[size_group_lookup[bsize]][mbmi->interintra_mode];
+ ++cm->counts.interintra[bsize][1];
+#if CONFIG_MASKED_INTERINTRA
+ if (cm->use_masked_interintra && get_mask_bits_interintra(bsize))
+ ++cm->counts.masked_interintra[bsize][mbmi->use_masked_interintra];
+#endif
+ } else {
+ ++cm->counts.interintra[bsize][0];
+ }
+ }
+#endif
}
rd_opt->comp_pred_diff[SINGLE_REFERENCE] += ctx->single_pred_diff;
2 * aligned_mi_cols * MAX_MB_PLANE);
vpx_memset(xd->above_seg_context, 0,
sizeof(*xd->above_seg_context) * aligned_mi_cols);
+
+#if CONFIG_MASKED_INTERINTER
+ vp9_zero(cpi->masked_interinter_select_counts);
+#endif
+#if CONFIG_INTERINTRA
+ vp9_zero(cpi->interintra_select_count);
+#if CONFIG_MASKED_INTERINTRA
+ vp9_zero(cpi->masked_interintra_select_count);
+#endif
+#endif
}
static int check_dual_ref_flags(VP9_COMP *cpi) {
const PREDICTION_MODE y_mode = mi->mbmi.mode;
const PREDICTION_MODE uv_mode = mi->mbmi.uv_mode;
const BLOCK_SIZE bsize = mi->mbmi.sb_type;
+#if CONFIG_FILTERINTRA
+ const int uv_fbit = mi->mbmi.uv_filterbit;
+ int fbit = mi->mbmi.filterbit;
+#endif
if (bsize < BLOCK_8X8) {
int idx, idy;
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
for (idy = 0; idy < 2; idy += num_4x4_h)
for (idx = 0; idx < 2; idx += num_4x4_w)
+#if CONFIG_FILTERINTRA
+ {
+#endif
++counts->y_mode[0][mi->bmi[idy * 2 + idx].as_mode];
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->bmi[idy * 2 + idx].as_mode)) {
+ fbit = mi->b_filter_info[idy * 2 + idx];
+ ++counts->filterintra[0][mi->bmi[idy * 2 + idx].as_mode][fbit];
+ }
+ }
+#endif
} else {
++counts->y_mode[size_group_lookup[bsize]][y_mode];
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(y_mode) && is_filter_enabled(mi->mbmi.tx_size))
+ ++counts->filterintra[mi->mbmi.tx_size][y_mode][fbit];
+#endif
}
++counts->uv_mode[y_mode][uv_mode];
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(uv_mode) &&
+ is_filter_enabled(get_uv_tx_size(&(mi->mbmi))))
+ ++counts->filterintra[get_uv_tx_size(&(mi->mbmi))][uv_mode][uv_fbit];
+#endif
}
static int get_zbin_mode_boost(const MB_MODE_INFO *mbmi, int enabled) {
if (mi_col + x < cm->mi_cols && mi_row + y < cm->mi_rows)
mi_8x8[mis * y + x]->mbmi.tx_size = tx_size;
}
+
+#if CONFIG_EXT_TX
+ if (mbmi->tx_size <= TX_16X16 &&
+ is_inter_block(mbmi) &&
+ bsize >= BLOCK_8X8 &&
+ !mbmi->skip &&
+ !vp9_segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
+ ++cm->counts.ext_tx[mbmi->ext_txfrm];
+ }
+#endif
}
}
const int diff_stride = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
int i, j;
const int16_t *src_diff;
+#if CONFIG_EXT_TX
+ MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+#endif
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
src_diff = &p->src_diff[4 * (j * diff_stride + i)];
scan_order->iscan);
break;
case TX_16X16:
+#if CONFIG_EXT_TX
+ if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
vp9_fdct16x16(src_diff, coeff, diff_stride);
+#if CONFIG_EXT_TX
+ } else {
+ vp9_fht16x16(src_diff, coeff, diff_stride, ADST_ADST);
+ }
+#endif
vp9_quantize_b(coeff, 256, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, p->zbin_extra, eob,
scan_order->scan, scan_order->iscan);
break;
case TX_8X8:
+#if CONFIG_EXT_TX
+ if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
vp9_fdct8x8(src_diff, coeff, diff_stride);
+#if CONFIG_EXT_TX
+ } else {
+ vp9_fht8x8(src_diff, coeff, diff_stride, ADST_ADST);
+ }
+#endif
vp9_quantize_b(coeff, 64, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, p->zbin_extra, eob,
scan_order->scan, scan_order->iscan);
break;
case TX_4X4:
+#if CONFIG_EXT_TX
+ if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
x->fwd_txm4x4(src_diff, coeff, diff_stride);
+#if CONFIG_EXT_TX
+ } else {
+ vp9_fht4x4(src_diff, coeff, diff_stride, ADST_ADST);
+ }
+#endif
vp9_quantize_b(coeff, 16, x->skip_block, p->zbin, p->round,
p->quant, p->quant_shift, qcoeff, dqcoeff,
pd->dequant, p->zbin_extra, eob,
int i, j;
uint8_t *dst;
ENTROPY_CONTEXT *a, *l;
+#if CONFIG_EXT_TX
+ MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+#endif
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
dst = &pd->dst.buf[4 * j * pd->dst.stride + 4 * i];
a = &ctx->ta[plane][i];
vp9_idct32x32_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
break;
case TX_16X16:
+#if CONFIG_EXT_TX
+ if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
vp9_idct16x16_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
+#if CONFIG_EXT_TX
+ } else {
+ vp9_iht16x16_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
+ p->eobs[block]);
+ }
+#endif
break;
case TX_8X8:
+#if CONFIG_EXT_TX
+ if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
vp9_idct8x8_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
+#if CONFIG_EXT_TX
+ } else {
+ vp9_iht8x8_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
+ p->eobs[block]);
+ }
+#endif
break;
case TX_4X4:
+#if CONFIG_EXT_TX
+ if (plane != 0 || mbmi->ext_txfrm == NORM) {
+#endif
// this is like vp9_short_idct4x4 but has a special case around eob<=1
// which is significant (not just an optimization) for the lossless
// case.
x->itxm_add(dqcoeff, dst, pd->dst.stride, p->eobs[block]);
+#if CONFIG_EXT_TX
+ } else {
+ vp9_iht4x4_add(ADST_ADST, dqcoeff, dst, pd->dst.stride,
+ p->eobs[block]);
+ }
+#endif
break;
default:
assert(0 && "Invalid transform size");
int16_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
int i, j;
uint8_t *dst;
+#if CONFIG_EXT_TX
+ MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+ mbmi->ext_txfrm = NORM;
+#endif
txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &i, &j);
dst = &pd->dst.buf[4 * j * pd->dst.stride + 4 * i];
const scan_order *scan_order;
TX_TYPE tx_type;
PREDICTION_MODE mode;
+#if CONFIG_FILTERINTRA
+ int fbit = 0;
+#endif
const int bwl = b_width_log2(plane_bsize);
const int diff_stride = 4 * (1 << bwl);
uint8_t *src, *dst;
src = &p->src.buf[4 * (j * src_stride + i)];
src_diff = &p->src_diff[4 * (j * diff_stride + i)];
+#if CONFIG_FILTERINTRA
+ if (mbmi->sb_type < BLOCK_8X8 && plane == 0)
+ fbit = xd->mi[0]->b_filter_info[block];
+ else
+ fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
+#endif
switch (tx_size) {
case TX_32X32:
scan_order = &vp9_default_scan_orders[TX_32X32];
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
vp9_predict_intra_block(xd, block >> 6, bwl, TX_32X32, mode,
+#if CONFIG_FILTERINTRA
+ fbit,
+#endif
x->skip_encode ? src : dst,
x->skip_encode ? src_stride : dst_stride,
dst, dst_stride, i, j, plane);
scan_order = &vp9_scan_orders[TX_16X16][tx_type];
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
vp9_predict_intra_block(xd, block >> 4, bwl, TX_16X16, mode,
+#if CONFIG_FILTERINTRA
+ fbit,
+#endif
x->skip_encode ? src : dst,
x->skip_encode ? src_stride : dst_stride,
dst, dst_stride, i, j, plane);
scan_order = &vp9_scan_orders[TX_8X8][tx_type];
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
vp9_predict_intra_block(xd, block >> 2, bwl, TX_8X8, mode,
+#if CONFIG_FILTERINTRA
+ fbit,
+#endif
x->skip_encode ? src : dst,
x->skip_encode ? src_stride : dst_stride,
dst, dst_stride, i, j, plane);
scan_order = &vp9_scan_orders[TX_4X4][tx_type];
mode = plane == 0 ? get_y_mode(xd->mi[0], block) : mbmi->uv_mode;
vp9_predict_intra_block(xd, block, bwl, TX_4X4, mode,
+#if CONFIG_FILTERINTRA
+ fbit,
+#endif
x->skip_encode ? src : dst,
x->skip_encode ? src_stride : dst_stride,
dst, dst_stride, i, j, plane);
vp9_sub_pixel_avg_variance4x4,
vp9_sad4x4x3, vp9_sad4x4x8, vp9_sad4x4x4d)
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+ CONFIG_MASKED_INTERINTER)
+#define MBFP(BT, MSDF, MVF, MSVF) \
+ cpi->fn_ptr[BT].msdf = MSDF; \
+ cpi->fn_ptr[BT].mvf = MVF; \
+ cpi->fn_ptr[BT].msvf = MSVF;
+
+ MBFP(BLOCK_64X64, vp9_masked_sad64x64, vp9_masked_variance64x64,
+ vp9_masked_sub_pixel_variance64x64)
+ MBFP(BLOCK_64X32, vp9_masked_sad64x32, vp9_masked_variance64x32,
+ vp9_masked_sub_pixel_variance64x32)
+ MBFP(BLOCK_32X64, vp9_masked_sad32x64, vp9_masked_variance32x64,
+ vp9_masked_sub_pixel_variance32x64)
+ MBFP(BLOCK_32X32, vp9_masked_sad32x32, vp9_masked_variance32x32,
+ vp9_masked_sub_pixel_variance32x32)
+ MBFP(BLOCK_32X16, vp9_masked_sad32x16, vp9_masked_variance32x16,
+ vp9_masked_sub_pixel_variance32x16)
+ MBFP(BLOCK_16X32, vp9_masked_sad16x32, vp9_masked_variance16x32,
+ vp9_masked_sub_pixel_variance16x32)
+ MBFP(BLOCK_16X16, vp9_masked_sad16x16, vp9_masked_variance16x16,
+ vp9_masked_sub_pixel_variance16x16)
+ MBFP(BLOCK_16X8, vp9_masked_sad16x8, vp9_masked_variance16x8,
+ vp9_masked_sub_pixel_variance16x8)
+ MBFP(BLOCK_8X16, vp9_masked_sad8x16, vp9_masked_variance8x16,
+ vp9_masked_sub_pixel_variance8x16)
+ MBFP(BLOCK_8X8, vp9_masked_sad8x8, vp9_masked_variance8x8,
+ vp9_masked_sub_pixel_variance8x8)
+ MBFP(BLOCK_4X8, vp9_masked_sad4x8, vp9_masked_variance4x8,
+ vp9_masked_sub_pixel_variance4x8)
+ MBFP(BLOCK_8X4, vp9_masked_sad8x4, vp9_masked_variance8x4,
+ vp9_masked_sub_pixel_variance8x4)
+ MBFP(BLOCK_4X4, vp9_masked_sad4x4, vp9_masked_variance4x4,
+ vp9_masked_sub_pixel_variance4x4)
+#endif
+
cpi->full_search_sad = vp9_full_search_sad;
cpi->diamond_search_sad = vp9_diamond_search_sad;
cpi->refining_search_sad = vp9_refining_search_sad;
}
}
+#if CONFIG_MASKED_INTERINTER
+static void select_masked_interinter_mode(VP9_COMP *cpi) {
+ static const double threshold = 1/128.0;
+ VP9_COMMON *cm = &cpi->common;
+ int sum = cpi->masked_interinter_select_counts[1] +
+ cpi->masked_interinter_select_counts[0];
+ if (sum) {
+ double fraction = (double) cpi->masked_interinter_select_counts[1] / sum;
+ cm->use_masked_interinter = (fraction > threshold);
+ }
+}
+#endif
+
+#if CONFIG_INTERINTRA
+static void select_interintra_mode(VP9_COMP *cpi) {
+ static const double threshold = 0.007;
+ VP9_COMMON *cm = &cpi->common;
+ int sum = cpi->interintra_select_count[1] + cpi->interintra_select_count[0];
+ if (sum) {
+ double fraction = (double)cpi->interintra_select_count[1] / (double)sum;
+ cm->use_interintra = (fraction > threshold);
+ }
+}
+
+#if CONFIG_MASKED_INTERINTRA
+static void select_masked_interintra_mode(VP9_COMP *cpi) {
+ static const double threshold = 1/100.0;
+ VP9_COMMON *cm = &cpi->common;
+ int sum = cpi->masked_interintra_select_count[1] +
+ cpi->masked_interintra_select_count[0];
+ if (sum) {
+ double fraction = (double)cpi->masked_interintra_select_count[1] /
+ (double)sum;
+ cm->use_masked_interintra = (fraction > threshold);
+ }
+}
+#endif
+#endif
+
static void encode_frame_to_data_rate(VP9_COMP *cpi,
size_t *size,
uint8_t *dest,
vp9_set_high_precision_mv(cpi, q < HIGH_PRECISION_MV_QTHRESH);
}
+#if CONFIG_MASKED_INTERINTER
+ if (cm->current_video_frame == 0)
+ cm->use_masked_interinter = 0;
+#endif
+
+#if CONFIG_INTERINTRA
+ if (cm->current_video_frame == 0) {
+ cm->use_interintra = 1;
+#if CONFIG_MASKED_INTERINTRA
+ cm->use_masked_interintra = 1;
+#endif
+ }
+#endif
+
if (cpi->sf.recode_loop == DISALLOW_RECODE) {
encode_without_recode_loop(cpi, q);
} else {
vp9_adapt_mode_probs(cm);
vp9_adapt_mv_probs(cm, cm->allow_high_precision_mv);
}
+#if CONFIG_MASKED_INTERINTER
+ select_masked_interinter_mode(cpi);
+#endif
+#if CONFIG_INTERINTRA
+ select_interintra_mode(cpi);
+#if CONFIG_MASKED_INTERINTRA
+ if (cpi->common.use_interintra)
+ select_masked_interintra_mode(cpi);
+ else
+ cpi->common.use_masked_interintra = 0;
+#endif
+#endif
}
if (cpi->refresh_golden_frame == 1)
FRAME_CONTEXT fc;
} CODING_CONTEXT;
-
typedef enum {
// encode_breakout is disabled.
ENCODE_BREAKOUT_DISABLED = 0,
#if CONFIG_DENOISING
VP9_DENOISER denoiser;
#endif
+
+#if CONFIG_MASKED_INTERINTER
+ unsigned int masked_interinter_select_counts[2];
+#endif
+#if CONFIG_INTERINTRA
+ unsigned int interintra_select_count[2];
+#if CONFIG_MASKED_INTERINTRA
+ unsigned int masked_interintra_select_count[2];
+#endif
+#endif
} VP9_COMP;
void vp9_initialize_enc();
xd->mi[0]->mbmi.mode = NEWMV;
xd->mi[0]->mbmi.mv[0].as_mv = *dst_mv;
+#if CONFIG_INTERINTRA
+ xd->mi[0]->mbmi.ref_frame[1] = NONE;
+#endif
vp9_build_inter_predictors_sby(xd, mb_row, mb_col, BLOCK_16X16);
/* restore UMV window */
xd->mi[0]->mbmi.mode = mode;
vp9_predict_intra_block(xd, 0, 2, TX_16X16, mode,
+#if CONFIG_FILTERINTRA
+ 0,
+#endif
x->plane[0].src.buf, x->plane[0].src.stride,
xd->plane[0].dst.buf, xd->plane[0].dst.stride,
0, 0, 0);
return var;
}
+
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+ CONFIG_MASKED_INTERINTER)
+/* returns subpixel variance error function */
+#define DIST(r, c) \
+ vfp->msvf(pre(y, y_stride, r, c), y_stride, sp(c), sp(r), z, \
+ src_stride, mask, mask_stride, &sse)
+
+/* checks if (r, c) has better score than previous best */
+
+#define MVC(r, c) \
+ (mvcost ? \
+ ((mvjcost[((r) != rr) * 2 + ((c) != rc)] + \
+ mvcost[0][((r) - rr)] + mvcost[1][((c) - rc)]) * \
+ error_per_bit + 4096) >> 13 : 0)
+
+#define CHECK_BETTER(v, r, c) \
+ if (c >= minc && c <= maxc && r >= minr && r <= maxr) { \
+ thismse = (DIST(r, c)); \
+ if ((v = MVC(r, c) + thismse) < besterr) { \
+ besterr = v; \
+ br = r; \
+ bc = c; \
+ *distortion = thismse; \
+ *sse1 = sse; \
+ } \
+ } else { \
+ v = INT_MAX; \
+ }
+
+int vp9_find_best_masked_sub_pixel_tree(const MACROBLOCK *x,
+ uint8_t *mask, int mask_stride,
+ MV *bestmv, const MV *ref_mv,
+ int allow_hp,
+ int error_per_bit,
+ const vp9_variance_fn_ptr_t *vfp,
+ int forced_stop,
+ int iters_per_step,
+ int *mvjcost, int *mvcost[2],
+ int *distortion,
+ unsigned int *sse1, int is_second) {
+ const uint8_t *const z = x->plane[0].src.buf;
+ const int src_stride = x->plane[0].src.stride;
+ const MACROBLOCKD *xd = &x->e_mbd;
+ unsigned int besterr = INT_MAX;
+ unsigned int sse;
+ unsigned int whichdir;
+ int thismse;
+ unsigned int halfiters = iters_per_step;
+ unsigned int quarteriters = iters_per_step;
+ unsigned int eighthiters = iters_per_step;
+
+ const int y_stride = xd->plane[0].pre[is_second].stride;
+ const int offset = bestmv->row * y_stride + bestmv->col;
+ const uint8_t *const y = xd->plane[0].pre[is_second].buf;
+
+ int rr = ref_mv->row;
+ int rc = ref_mv->col;
+ int br = bestmv->row * 8;
+ int bc = bestmv->col * 8;
+ int hstep = 4;
+ const int minc = MAX(x->mv_col_min * 8, ref_mv->col - MV_MAX);
+ const int maxc = MIN(x->mv_col_max * 8, ref_mv->col + MV_MAX);
+ const int minr = MAX(x->mv_row_min * 8, ref_mv->row - MV_MAX);
+ const int maxr = MIN(x->mv_row_max * 8, ref_mv->row + MV_MAX);
+
+ int tr = br;
+ int tc = bc;
+
+ // central mv
+ bestmv->row *= 8;
+ bestmv->col *= 8;
+
+ // calculate central point error
+ besterr = vfp->mvf(y + offset, y_stride, z, src_stride, mask, mask_stride,
+ sse1);
+ *distortion = besterr;
+ besterr += mv_err_cost(bestmv, ref_mv, mvjcost, mvcost, error_per_bit);
+
+ // 1/2 pel
+ FIRST_LEVEL_CHECKS;
+ if (halfiters > 1) {
+ SECOND_LEVEL_CHECKS;
+ }
+ tr = br;
+ tc = bc;
+
+ // Note forced_stop: 0 - full, 1 - qtr only, 2 - half only
+ if (forced_stop != 2) {
+ hstep >>= 1;
+ FIRST_LEVEL_CHECKS;
+ if (quarteriters > 1) {
+ SECOND_LEVEL_CHECKS;
+ }
+ tr = br;
+ tc = bc;
+ }
+
+ if (allow_hp && vp9_use_mv_hp(ref_mv) && forced_stop == 0) {
+ hstep >>= 1;
+ FIRST_LEVEL_CHECKS;
+ if (eighthiters > 1) {
+ SECOND_LEVEL_CHECKS;
+ }
+ tr = br;
+ tc = bc;
+ }
+ // These lines insure static analysis doesn't warn that
+ // tr and tc aren't used after the above point.
+ (void) tr;
+ (void) tc;
+
+ bestmv->row = br;
+ bestmv->col = bc;
+
+ if ((abs(bestmv->col - ref_mv->col) > (MAX_FULL_PEL_VAL << 3)) ||
+ (abs(bestmv->row - ref_mv->row) > (MAX_FULL_PEL_VAL << 3)))
+ return INT_MAX;
+
+ return besterr;
+}
+
+#undef DIST
+#undef MVC
+#undef CHECK_BETTER
+
+int vp9_get_masked_mvpred_var(const MACROBLOCK *x,
+ uint8_t *mask, int mask_stride,
+ const MV *best_mv, const MV *center_mv,
+ const vp9_variance_fn_ptr_t *vfp,
+ int use_mvcost, int is_second) {
+ const MACROBLOCKD *const xd = &x->e_mbd;
+ const struct buf_2d *const what = &x->plane[0].src;
+ const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
+ const MV mv = {best_mv->row * 8, best_mv->col * 8};
+ unsigned int unused;
+
+ return vfp->mvf(what->buf, what->stride,
+ get_buf_from_mv(in_what, best_mv), in_what->stride,
+ mask, mask_stride, &unused) +
+ (use_mvcost ? mv_err_cost(&mv, center_mv, x->nmvjointcost,
+ x->mvcost, x->errorperbit) : 0);
+}
+
+int vp9_masked_refining_search_sad_c(const MACROBLOCK *x,
+ uint8_t *mask, int mask_stride,
+ MV *ref_mv, int error_per_bit,
+ int search_range,
+ const vp9_variance_fn_ptr_t *fn_ptr,
+ const MV *center_mv, int is_second) {
+ const MV neighbors[4] = {{ -1, 0}, {0, -1}, {0, 1}, {1, 0}};
+ const MACROBLOCKD *const xd = &x->e_mbd;
+ const struct buf_2d *const what = &x->plane[0].src;
+ const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
+ const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
+ unsigned int best_sad = fn_ptr->msdf(what->buf, what->stride,
+ get_buf_from_mv(in_what, ref_mv),
+ in_what->stride, mask, mask_stride) +
+ mvsad_err_cost(x, ref_mv, &fcenter_mv, error_per_bit);
+ int i, j;
+
+ for (i = 0; i < search_range; i++) {
+ int best_site = -1;
+
+ for (j = 0; j < 4; j++) {
+ const MV mv = {ref_mv->row + neighbors[j].row,
+ ref_mv->col + neighbors[j].col};
+ if (is_mv_in(x, &mv)) {
+ unsigned int sad = fn_ptr->msdf(what->buf, what->stride,
+ get_buf_from_mv(in_what, &mv), in_what->stride, mask, mask_stride);
+ if (sad < best_sad) {
+ sad += mvsad_err_cost(x, &mv, &fcenter_mv, error_per_bit);
+ if (sad < best_sad) {
+ best_sad = sad;
+ best_site = j;
+ }
+ }
+ }
+ }
+
+ if (best_site == -1) {
+ break;
+ } else {
+ ref_mv->row += neighbors[best_site].row;
+ ref_mv->col += neighbors[best_site].col;
+ }
+ }
+ return best_sad;
+}
+
+int vp9_masked_diamond_search_sad_c(const MACROBLOCK *x,
+ const search_site_config *cfg,
+ uint8_t *mask, int mask_stride,
+ MV *ref_mv, MV *best_mv,
+ int search_param, int sad_per_bit, int *num00,
+ const vp9_variance_fn_ptr_t *fn_ptr,
+ const MV *center_mv, int is_second) {
+ const MACROBLOCKD *const xd = &x->e_mbd;
+ const struct buf_2d *const what = &x->plane[0].src;
+ const struct buf_2d *const in_what = &xd->plane[0].pre[is_second];
+ // search_param determines the length of the initial step and hence the number
+ // of iterations
+ // 0 = initial step (MAX_FIRST_STEP) pel : 1 = (MAX_FIRST_STEP/2) pel, 2 =
+ // (MAX_FIRST_STEP/4) pel... etc.
+ const search_site *const ss = &cfg->ss[search_param * cfg->searches_per_step];
+ const int tot_steps = (cfg->ss_count / cfg->searches_per_step) - search_param;
+ const MV fcenter_mv = {center_mv->row >> 3, center_mv->col >> 3};
+ const uint8_t *best_address, *in_what_ref;
+ int best_sad = INT_MAX;
+ int best_site = 0;
+ int last_site = 0;
+ int i, j, step;
+
+ clamp_mv(ref_mv, x->mv_col_min, x->mv_col_max, x->mv_row_min, x->mv_row_max);
+ in_what_ref = get_buf_from_mv(in_what, ref_mv);
+ best_address = in_what_ref;
+ *num00 = 0;
+ *best_mv = *ref_mv;
+
+ // Check the starting position
+ best_sad = fn_ptr->msdf(what->buf, what->stride,
+ best_address, in_what->stride,
+ mask, mask_stride) +
+ mvsad_err_cost(x, best_mv, &fcenter_mv, sad_per_bit);
+
+ i = 1;
+
+ for (step = 0; step < tot_steps; step++) {
+ for (j = 0; j < cfg->searches_per_step; j++) {
+ const MV mv = {best_mv->row + ss[i].mv.row,
+ best_mv->col + ss[i].mv.col};
+ if (is_mv_in(x, &mv)) {
+ int sad = fn_ptr->msdf(what->buf, what->stride,
+ best_address + ss[i].offset, in_what->stride,
+ mask, mask_stride);
+ if (sad < best_sad) {
+ sad += mvsad_err_cost(x, &mv, &fcenter_mv, sad_per_bit);
+ if (sad < best_sad) {
+ best_sad = sad;
+ best_site = i;
+ }
+ }
+ }
+
+ i++;
+ }
+
+ if (best_site != last_site) {
+ best_mv->row += ss[best_site].mv.row;
+ best_mv->col += ss[best_site].mv.col;
+ best_address += ss[best_site].offset;
+ last_site = best_site;
+#if defined(NEW_DIAMOND_SEARCH)
+ while (1) {
+ const MV this_mv = {best_mv->row + ss[best_site].mv.row,
+ best_mv->col + ss[best_site].mv.col};
+ if (is_mv_in(x, &this_mv)) {
+ int sad = fn_ptr->msdf(what->buf, what->stride,
+ best_address + ss[best_site].offset,
+ in_what->stride, mask, mask_stride);
+ if (sad < best_sad) {
+ sad += mvsad_err_cost(x, &this_mv, &fcenter_mv, sad_per_bit);
+ if (sad < best_sad) {
+ best_sad = sad;
+ best_mv->row += ss[best_site].mv.row;
+ best_mv->col += ss[best_site].mv.col;
+ best_address += ss[best_site].offset;
+ continue;
+ }
+ }
+ }
+ break;
+ }
+#endif
+ } else if (best_address == in_what_ref) {
+ (*num00)++;
+ }
+ }
+ return best_sad;
+}
+
+int vp9_masked_full_pixel_diamond(const VP9_COMP *cpi, MACROBLOCK *x,
+ uint8_t *mask, int mask_stride,
+ MV *mvp_full, int step_param,
+ int sadpb, int further_steps, int do_refine,
+ const vp9_variance_fn_ptr_t *fn_ptr,
+ const MV *ref_mv, MV *dst_mv,
+ int is_second) {
+ MV temp_mv;
+ int thissme, n, num00 = 0;
+ int bestsme = vp9_masked_diamond_search_sad_c(x, &cpi->ss_cfg,
+ mask, mask_stride,
+ mvp_full, &temp_mv,
+ step_param, sadpb, &n,
+ fn_ptr, ref_mv, is_second);
+ if (bestsme < INT_MAX)
+ bestsme = vp9_get_masked_mvpred_var(x, mask, mask_stride, &temp_mv, ref_mv,
+ fn_ptr, 1, is_second);
+ *dst_mv = temp_mv;
+
+ // If there won't be more n-step search, check to see if refining search is
+ // needed.
+ if (n > further_steps)
+ do_refine = 0;
+
+ while (n < further_steps) {
+ ++n;
+
+ if (num00) {
+ num00--;
+ } else {
+ thissme = vp9_masked_diamond_search_sad_c(x, &cpi->ss_cfg,
+ mask, mask_stride,
+ mvp_full, &temp_mv,
+ step_param + n, sadpb, &num00,
+ fn_ptr, ref_mv, is_second);
+ if (thissme < INT_MAX)
+ thissme = vp9_get_masked_mvpred_var(x, mask, mask_stride,
+ &temp_mv, ref_mv, fn_ptr, 1,
+ is_second);
+
+ // check to see if refining search is needed.
+ if (num00 > further_steps - n)
+ do_refine = 0;
+
+ if (thissme < bestsme) {
+ bestsme = thissme;
+ *dst_mv = temp_mv;
+ }
+ }
+ }
+
+ // final 1-away diamond refining search
+ if (do_refine) {
+ const int search_range = 8;
+ MV best_mv = *dst_mv;
+ thissme = vp9_masked_refining_search_sad_c(x, mask, mask_stride,
+ &best_mv, sadpb, search_range,
+ fn_ptr, ref_mv, is_second);
+ if (thissme < INT_MAX)
+ thissme = vp9_get_masked_mvpred_var(x, mask, mask_stride,
+ &best_mv, ref_mv, fn_ptr, 1,
+ is_second);
+ if (thissme < bestsme) {
+ bestsme = thissme;
+ *dst_mv = best_mv;
+ }
+ }
+ return bestsme;
+}
+#endif
int step_param, int error_per_bit,
const MV *ref_mv, MV *tmp_mv,
int var_max, int rd);
+
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+ CONFIG_MASKED_INTERINTER)
+int vp9_find_best_masked_sub_pixel_tree(const MACROBLOCK *x,
+ uint8_t *mask, int mask_stride,
+ MV *bestmv, const MV *ref_mv,
+ int allow_hp,
+ int error_per_bit,
+ const vp9_variance_fn_ptr_t *vfp,
+ int forced_stop,
+ int iters_per_step,
+ int *mvjcost, int *mvcost[2],
+ int *distortion,
+ unsigned int *sse1, int is_second);
+int vp9_masked_full_pixel_diamond(const struct VP9_COMP *cpi, MACROBLOCK *x,
+ uint8_t *mask, int mask_stride,
+ MV *mvp_full, int step_param,
+ int sadpb, int further_steps, int do_refine,
+ const vp9_variance_fn_ptr_t *fn_ptr,
+ const MV *ref_mv, MV *dst_mv,
+ int is_second);
+#endif
+
#ifdef __cplusplus
} // extern "C"
#endif
for (i = 0; i < width; i += step) {
vp9_predict_intra_block(xd, block_idx, b_width_log2(bsize),
mbmi->tx_size, this_mode,
+#if CONFIG_FILTERINTRA
+ 0,
+#endif
&p->src.buf[4 * (j * dst_stride + i)],
src_stride,
&pd->dst.buf[4 * (j * dst_stride + i)],
++block_idx;
}
}
-
rate = rate2;
dist = dist2;
{D63_PRED, {INTRA_FRAME, NONE}},
{D117_PRED, {INTRA_FRAME, NONE}},
{D45_PRED, {INTRA_FRAME, NONE}},
+
+#if CONFIG_INTERINTRA
+ {ZEROMV, {LAST_FRAME, INTRA_FRAME}},
+ {NEARESTMV, {LAST_FRAME, INTRA_FRAME}},
+ {NEARMV, {LAST_FRAME, INTRA_FRAME}},
+ {NEWMV, {LAST_FRAME, INTRA_FRAME}},
+
+ {ZEROMV, {GOLDEN_FRAME, INTRA_FRAME}},
+ {NEARESTMV, {GOLDEN_FRAME, INTRA_FRAME}},
+ {NEARMV, {GOLDEN_FRAME, INTRA_FRAME}},
+ {NEWMV, {GOLDEN_FRAME, INTRA_FRAME}},
+
+ {ZEROMV, {ALTREF_FRAME, INTRA_FRAME}},
+ {NEARESTMV, {ALTREF_FRAME, INTRA_FRAME}},
+ {NEARMV, {ALTREF_FRAME, INTRA_FRAME}},
+ {NEWMV, {ALTREF_FRAME, INTRA_FRAME}},
+#endif
};
static const REF_DEFINITION vp9_ref_order[MAX_REFS] = {
static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
PREDICTION_MODE *best_mode,
+#if CONFIG_FILTERINTRA
+ int *best_fbit,
+#endif
const int *bmode_costs,
ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l,
int *bestrate, int *bestratey,
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
int idx, idy;
uint8_t best_dst[8 * 8];
+#if CONFIG_FILTERINTRA
+ int mode_ext, fbit;
+#endif
assert(ib < 4);
vpx_memcpy(tl, l, sizeof(tl));
xd->mi[0]->mbmi.tx_size = TX_4X4;
+#if !CONFIG_FILTERINTRA
for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
int64_t this_rd;
int ratey = 0;
if (conditional_skipintra(mode, *best_mode))
continue;
}
+#else
+ for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * TM_PRED + 1; ++mode_ext) {
+ int64_t this_rd;
+ int ratey = 0;
+ int64_t distortion = 0;
+ int rate;
+
+ fbit = mode_ext & 1;
+ mode = mode_ext >> 1;
+ if (fbit && !is_filter_allowed(mode))
+ continue;
+
+ rate = bmode_costs[mode];
+ if (is_filter_allowed(mode))
+ rate += vp9_cost_bit(cpi->common.fc.filterintra_prob[0][mode], fbit);
+#endif
vpx_memcpy(tempa, ta, sizeof(ta));
vpx_memcpy(templ, tl, sizeof(tl));
p->src_diff);
int16_t *const coeff = BLOCK_OFFSET(x->plane[0].coeff, block);
xd->mi[0]->bmi[block].as_mode = mode;
+#if CONFIG_FILTERINTRA
+ xd->mi[0]->b_filter_info[block] = fbit;
+#endif
vp9_predict_intra_block(xd, block, 1,
TX_4X4, mode,
+#if CONFIG_FILTERINTRA
+ fbit,
+#endif
x->skip_encode ? src : dst,
x->skip_encode ? src_stride : dst_stride,
dst, dst_stride, idx, idy, 0);
*bestdistortion = distortion;
best_rd = this_rd;
*best_mode = mode;
+#if CONFIG_FILTERINTRA
+ *best_fbit = fbit;
+#endif
vpx_memcpy(a, tempa, sizeof(tempa));
vpx_memcpy(l, templ, sizeof(templ));
for (idy = 0; idy < num_4x4_blocks_high * 4; ++idy)
for (idy = 0; idy < 2; idy += num_4x4_blocks_high) {
for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
PREDICTION_MODE best_mode = DC_PRED;
+#if CONFIG_FILTERINTRA
+ int best_fbit = 0;
+#endif
int r = INT_MAX, ry = INT_MAX;
int64_t d = INT64_MAX, this_rd = INT64_MAX;
i = idy * 2 + idx;
bmode_costs = cpi->y_mode_costs[A][L];
}
- this_rd = rd_pick_intra4x4block(cpi, mb, i, &best_mode, bmode_costs,
+ this_rd = rd_pick_intra4x4block(cpi, mb, i, &best_mode,
+#if CONFIG_FILTERINTRA
+ &best_fbit,
+#endif
+ bmode_costs,
t_above + idx, t_left + idy, &r, &ry, &d,
bsize, best_rd - total_rd);
if (this_rd >= best_rd - total_rd)
mic->bmi[i + j * 2].as_mode = best_mode;
for (j = 1; j < num_4x4_blocks_wide; ++j)
mic->bmi[i + j].as_mode = best_mode;
+#if CONFIG_FILTERINTRA
+ mic->b_filter_info[i] = best_fbit;
+ for (j = 1; j < num_4x4_blocks_high; ++j)
+ mic->b_filter_info[i + j * 2] = best_fbit;
+ for (j = 1; j < num_4x4_blocks_wide; ++j)
+ mic->b_filter_info[i + j] = best_fbit;
+#endif
if (total_rd >= best_rd)
return INT64_MAX;
*rate_y = tot_rate_y;
*distortion = total_distortion;
mic->mbmi.mode = mic->bmi[3].as_mode;
+#if CONFIG_FILTERINTRA
+ mic->mbmi.filterbit = mic->b_filter_info[3];
+#endif
return RDCOST(mb->rdmult, mb->rddiv, cost, total_distortion);
}
TX_SIZE best_tx = TX_4X4;
int i;
int *bmode_costs = cpi->mbmode_cost;
+#if CONFIG_FILTERINTRA
+ int mode_ext, fbit, fbit_selected = 0;
+#endif
if (cpi->sf.tx_size_search_method == USE_FULL_RD)
for (i = 0; i < TX_MODES; i++)
tx_cache[i] = INT64_MAX;
/* Y Search for intra prediction mode */
+#if !CONFIG_FILTERINTRA
for (mode = DC_PRED; mode <= TM_PRED; mode++) {
int64_t local_tx_cache[TX_MODES];
MODE_INFO *above_mi = xd->mi[-xd->mi_stride];
MODE_INFO *left_mi = xd->left_available ? xd->mi[-1] : NULL;
+#else
+ for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * TM_PRED + 1; mode_ext++) {
+ int64_t local_tx_cache[TX_MODES];
+ MODE_INFO *above_mi = xd->mi[-xd->mi_stride];
+ MODE_INFO *left_mi = xd->left_available ? xd->mi[-1] : NULL;
+ fbit = mode_ext & 1;
+ mode = mode_ext >> 1;
+ if (fbit && !is_filter_allowed(mode))
+ continue;
+#endif
if (cpi->common.frame_type == KEY_FRAME) {
const PREDICTION_MODE A = vp9_above_block_mode(mic, above_mi, 0);
const PREDICTION_MODE L = vp9_left_block_mode(mic, left_mi, 0);
bmode_costs = cpi->y_mode_costs[A][L];
}
mic->mbmi.mode = mode;
+#if CONFIG_FILTERINTRA
+ mic->mbmi.filterbit = fbit;
+#endif
intra_super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion,
&s, NULL, bsize, local_tx_cache, best_rd);
continue;
this_rate = this_rate_tokenonly + bmode_costs[mode];
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mode) && is_filter_enabled(mic->mbmi.tx_size))
+ this_rate += vp9_cost_bit(cpi->common.fc.filterintra_prob
+ [mic->mbmi.tx_size][mode], fbit);
+#endif
this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
if (this_rd < best_rd) {
mode_selected = mode;
+#if CONFIG_FILTERINTRA
+ fbit_selected = fbit;
+#endif
best_rd = this_rd;
best_tx = mic->mbmi.tx_size;
*rate = this_rate;
}
mic->mbmi.mode = mode_selected;
+#if CONFIG_FILTERINTRA
+ if (is_filter_enabled(best_tx))
+ mic->mbmi.filterbit = fbit_selected;
+ else
+ mic->mbmi.filterbit = 0;
+#endif
mic->mbmi.tx_size = best_tx;
return best_rd;
int this_rate_tokenonly, this_rate, s;
int64_t this_distortion, this_sse;
+#if CONFIG_FILTERINTRA
+ int mode_ext, fbit = 0, fbit_selected = 0;
+ for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * TM_PRED + 1; mode_ext++) {
+ mode = mode_ext >> 1;
+ fbit = mode_ext & 1;
+
+ if (fbit && !is_filter_allowed(mode))
+ continue;
+ if (fbit &&
+ !is_filter_enabled(get_uv_tx_size(&(x->e_mbd.mi[0]->mbmi))))
+ continue;
+
+ x->e_mbd.mi[0]->mbmi.uv_filterbit = fbit;
+#else
for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
if (!(cpi->sf.intra_uv_mode_mask[max_tx_size] & (1 << mode)))
continue;
+#endif
xd->mi[0]->mbmi.uv_mode = mode;
continue;
this_rate = this_rate_tokenonly +
cpi->intra_uv_mode_cost[cpi->common.frame_type][mode];
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mode) &&
+ is_filter_enabled(get_uv_tx_size(&(x->e_mbd.mi[0]->mbmi))))
+ this_rate += vp9_cost_bit(cpi->common.fc.filterintra_prob
+ [get_uv_tx_size(&(x->e_mbd.mi[0]->mbmi))][mode], fbit);
+#endif
this_rd = RDCOST(x->rdmult, x->rddiv, this_rate, this_distortion);
if (this_rd < best_rd) {
mode_selected = mode;
+#if CONFIG_FILTERINTRA
+ fbit_selected = fbit;
+#endif
best_rd = this_rd;
*rate = this_rate;
*rate_tokenonly = this_rate_tokenonly;
}
xd->mi[0]->mbmi.uv_mode = mode_selected;
+#if CONFIG_FILTERINTRA
+ xd->mi[0]->mbmi.uv_filterbit = fbit_selected;
+#endif
return best_rd;
}
BLOCK_SIZE bsize, TX_SIZE max_tx_size,
int *rate_uv, int *rate_uv_tokenonly,
int64_t *dist_uv, int *skip_uv,
+#if CONFIG_FILTERINTRA
+ int *fbit_uv,
+#endif
PREDICTION_MODE *mode_uv) {
MACROBLOCK *const x = &cpi->mb;
bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize, max_tx_size);
}
*mode_uv = x->e_mbd.mi[0]->mbmi.uv_mode;
+#if CONFIG_FILTERINTRA
+ *fbit_uv = x->e_mbd.mi[0]->mbmi.uv_filterbit;
+#endif
}
static int cost_mv_ref(const VP9_COMP *cpi, PREDICTION_MODE mode,
(this_mode == NEARMV || this_mode == NEARESTMV || this_mode == ZEROMV) &&
frame_mv[this_mode][ref_frames[0]].as_int == 0 &&
(ref_frames[1] == NONE ||
+#if CONFIG_INTERINTRA
+ ref_frames[1] == INTRA_FRAME ||
+#endif
frame_mv[this_mode][ref_frames[1]].as_int == 0)) {
int rfc = mode_context[ref_frames[0]];
int c1 = cost_mv_ref(cpi, NEARMV, rfc);
if (c2 > c3) return 0;
} else {
assert(this_mode == ZEROMV);
- if (ref_frames[1] == NONE) {
+ if (ref_frames[1] == NONE
+#if CONFIG_INTERINTRA
+ || ref_frames[1] == INTRA_FRAME
+#endif
+ ) {
if ((c3 >= c2 && frame_mv[NEARESTMV][ref_frames[0]].as_int == 0) ||
(c3 >= c1 && frame_mv[NEARMV][ref_frames[0]].as_int == 0))
return 0;
}
}
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA)|| \
+ CONFIG_MASKED_INTERINTER)
+static void do_masked_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
+ uint8_t *mask, int mask_stride,
+ BLOCK_SIZE bsize,
+ int mi_row, int mi_col,
+ int_mv *tmp_mv, int *rate_mv,
+ int is_second) {
+ MACROBLOCKD *xd = &x->e_mbd;
+ const VP9_COMMON *cm = &cpi->common;
+ MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+ struct buf_2d backup_yv12[MAX_MB_PLANE] = {{0, 0}};
+ int bestsme = INT_MAX;
+ int step_param;
+ int sadpb = x->sadperbit16;
+ MV mvp_full;
+ int ref = mbmi->ref_frame[is_second];
+ MV ref_mv = mbmi->ref_mvs[ref][0].as_mv;
+
+ int tmp_col_min = x->mv_col_min;
+ int tmp_col_max = x->mv_col_max;
+ int tmp_row_min = x->mv_row_min;
+ int tmp_row_max = x->mv_row_max;
+
+ const YV12_BUFFER_CONFIG *scaled_ref_frame = vp9_get_scaled_ref_frame(cpi,
+ ref);
+
+ MV pred_mv[3];
+ pred_mv[0] = mbmi->ref_mvs[ref][0].as_mv;
+ pred_mv[1] = mbmi->ref_mvs[ref][1].as_mv;
+ pred_mv[2] = x->pred_mv[ref];
+
+ if (scaled_ref_frame) {
+ int i;
+ // Swap out the reference frame for a version that's been scaled to
+ // match the resolution of the current frame, allowing the existing
+ // motion search code to be used without additional modifications.
+ for (i = 0; i < MAX_MB_PLANE; i++)
+ backup_yv12[i] = xd->plane[i].pre[is_second];
+
+ vp9_setup_pre_planes(xd, is_second, scaled_ref_frame, mi_row, mi_col, NULL);
+ }
+
+ vp9_set_mv_search_range(x, &ref_mv);
+
+ // Work out the size of the first step in the mv step search.
+ // 0 here is maximum length first step. 1 is MAX >> 1 etc.
+ if (cpi->sf.mv.auto_mv_step_size && cm->show_frame) {
+ // Take wtd average of the step_params based on the last frame's
+ // max mv magnitude and that based on the best ref mvs of the current
+ // block for the given reference.
+ step_param = (vp9_init_search_range(&cpi->sf, x->max_mv_context[ref]) +
+ cpi->mv_step_param) / 2;
+ } else {
+ step_param = cpi->mv_step_param;
+ }
+
+ if (cpi->sf.adaptive_motion_search && bsize < BLOCK_64X64 &&
+ cm->show_frame) {
+ int boffset = 2 * (b_width_log2(BLOCK_64X64) - MIN(b_height_log2(bsize),
+ b_width_log2(bsize)));
+ step_param = MAX(step_param, boffset);
+ }
+
+ if (cpi->sf.adaptive_motion_search) {
+ int bwl = b_width_log2_lookup[bsize];
+ int bhl = b_height_log2_lookup[bsize];
+ int i;
+ int tlevel = x->pred_mv_sad[ref] >> (bwl + bhl + 4);
+
+ if (tlevel < 5)
+ step_param += 2;
+
+ for (i = LAST_FRAME; i <= ALTREF_FRAME && cm->show_frame; ++i) {
+ if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
+ x->pred_mv[ref].row = 0;
+ x->pred_mv[ref].col = 0;
+ tmp_mv->as_int = INVALID_MV;
+
+ if (scaled_ref_frame) {
+ int i;
+ for (i = 0; i < MAX_MB_PLANE; i++)
+ xd->plane[i].pre[is_second] = backup_yv12[i];
+ }
+ return;
+ }
+ }
+ }
+
+ mvp_full = pred_mv[x->mv_best_ref_index[ref]];
+
+ mvp_full.col >>= 3;
+ mvp_full.row >>= 3;
+
+ bestsme = vp9_masked_full_pixel_diamond(cpi, x, mask, mask_stride,
+ &mvp_full, step_param, sadpb,
+ cpi->sf.mv.max_step_search_steps - 1
+ - step_param, 1,
+ &cpi->fn_ptr[bsize],
+ &ref_mv, &tmp_mv->as_mv, is_second);
+
+ x->mv_col_min = tmp_col_min;
+ x->mv_col_max = tmp_col_max;
+ x->mv_row_min = tmp_row_min;
+ x->mv_row_max = tmp_row_max;
+
+ if (bestsme < INT_MAX) {
+ int dis; /* TODO: use dis in distortion calculation later. */
+ vp9_find_best_masked_sub_pixel_tree(x, mask, mask_stride,
+ &tmp_mv->as_mv, &ref_mv,
+ cm->allow_high_precision_mv,
+ x->errorperbit,
+ &cpi->fn_ptr[bsize],
+ cpi->sf.mv.subpel_force_stop,
+ cpi->sf.mv.subpel_iters_per_step,
+ x->nmvjointcost, x->mvcost,
+ &dis, &x->pred_sse[ref], is_second);
+ }
+ *rate_mv = vp9_mv_bit_cost(&tmp_mv->as_mv, &ref_mv,
+ x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
+
+ if (cpi->sf.adaptive_motion_search && cm->show_frame)
+ x->pred_mv[ref] = tmp_mv->as_mv;
+
+ if (scaled_ref_frame) {
+ int i;
+ for (i = 0; i < MAX_MB_PLANE; i++)
+ xd->plane[i].pre[is_second] = backup_yv12[i];
+ }
+}
+#endif
+
+#if CONFIG_MASKED_INTERINTER
+static void do_masked_motion_search_indexed(VP9_COMP *cpi, MACROBLOCK *x,
+ int mask_index,
+ BLOCK_SIZE bsize,
+ int *refs,
+ int mi_row, int mi_col,
+ int_mv *tmp_mv, int *rate_mv) {
+ MACROBLOCKD *xd = &x->e_mbd;
+ MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
+ BLOCK_SIZE sb_type = mbmi->sb_type;
+ int w = (4 << b_width_log2(sb_type));
+ int h = (4 << b_height_log2(sb_type));
+ int i, j;
+ uint8_t mask[4096];
+ int mask_stride = 64;
+
+ vp9_generate_masked_weight(mask_index, sb_type, h, w,
+ mask, mask_stride);
+ /*
+ vp9_generate_hard_mask(mask_index, sb_type, h, w,
+ mask, mask_stride);
+ */
+
+ do_masked_motion_search(cpi, x, mask, mask_stride, bsize,
+ mi_row, mi_col, &tmp_mv[0], &rate_mv[0], 0);
+
+ for (i = 0; i < h; ++i)
+ for (j = 0; j < w; ++j)
+ mask[i * mask_stride + j] = 64 - mask[i * mask_stride + j];
+
+ do_masked_motion_search(cpi, x, mask, mask_stride, bsize,
+ mi_row, mi_col, &tmp_mv[1], &rate_mv[1], 1);
+}
+#endif
+
static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bsize,
int64_t txfm_cache[],
int *rate2, int64_t *distortion,
int *skippable,
+#if CONFIG_MASKED_INTERINTER
+ int *compmode_interinter_cost,
+#endif
+#if CONFIG_INTERINTRA
+ int *compmode_interintra_cost,
+#endif
int *rate_y, int64_t *distortion_y,
int *rate_uv, int64_t *distortion_uv,
int *mode_excluded, int *disable_skip,
int_mv (*mode_mv)[MAX_REF_FRAMES],
int mi_row, int mi_col,
int_mv single_newmv[MAX_REF_FRAMES],
+#if CONFIG_INTERINTRA
+ int single_newmv_rate[MAX_REF_FRAMES],
+#endif
int64_t *psse,
const int64_t ref_best_rd) {
VP9_COMMON *cm = &cpi->common;
uint8_t *orig_dst[MAX_MB_PLANE];
int orig_dst_stride[MAX_MB_PLANE];
int rs = 0;
+#if CONFIG_MASKED_INTERINTER || CONFIG_INTERINTRA
+ int rate_mv_tmp = 0;
+#endif
+#if CONFIG_INTERINTRA
+ const int is_comp_interintra_pred = (mbmi->ref_frame[1] == INTRA_FRAME);
+#if CONFIG_MASKED_INTERINTRA
+ mbmi->use_masked_interintra = 0;
+ mbmi->interintra_mask_index = -1;
+ mbmi->interintra_uv_mask_index = -1;
+#endif
+#endif
+#if CONFIG_MASKED_INTERINTER
+ mbmi->use_masked_interinter = 0;
+ mbmi->mask_index = MASK_NONE;
+ *compmode_interinter_cost = 0;
+#endif
if (is_comp_pred) {
if (frame_mv[refs[0]].as_int == INVALID_MV ||
&mbmi->ref_mvs[refs[1]][0].as_mv,
x->nmvjointcost, x->mvcost, MV_COST_WEIGHT);
}
+#if !(CONFIG_MASKED_INTERINTER || CONFIG_INTERINTRA)
*rate2 += rate_mv;
+#endif
} else {
int_mv tmp_mv;
+#if CONFIG_INTERINTRA
+ if (!is_comp_interintra_pred) {
+#endif
single_motion_search(cpi, x, bsize, mi_row, mi_col,
&tmp_mv, &rate_mv);
if (tmp_mv.as_int == INVALID_MV)
return INT64_MAX;
+#if !(CONFIG_MASKED_INTERINTER || CONFIG_INTERINTRA)
*rate2 += rate_mv;
+#endif
frame_mv[refs[0]].as_int =
xd->mi[0]->bmi[0].as_mv[0].as_int = tmp_mv.as_int;
single_newmv[refs[0]].as_int = tmp_mv.as_int;
+#if CONFIG_INTERINTRA
+ single_newmv_rate[refs[0]] = rate_mv;
+ } else {
+ frame_mv[refs[0]].as_int = single_newmv[refs[0]].as_int;
+ rate_mv = single_newmv_rate[refs[0]];
+ }
+#endif
}
+#if CONFIG_MASKED_INTERINTER || CONFIG_INTERINTRA
+ rate_mv_tmp = rate_mv;
+#endif
}
for (i = 0; i < num_refs; ++i) {
int64_t dist_sum = 0;
if ((cm->interp_filter == SWITCHABLE &&
(!i || best_needs_copy)) ||
+#if CONFIG_INTERINTRA
+ (is_inter_mode(this_mode) && is_comp_interintra_pred &&
+ is_interintra_allowed(mbmi->sb_type)) ||
+#endif
(cm->interp_filter != SWITCHABLE &&
(cm->interp_filter == mbmi->interp_filter ||
(i == 0 && intpel_mv)))) {
restore_dst_buf(xd, orig_dst, orig_dst_stride);
}
}
+
// Set the appropriate filter
mbmi->interp_filter = cm->interp_filter != SWITCHABLE ?
cm->interp_filter : *best_filter;
rs = cm->interp_filter == SWITCHABLE ? vp9_get_switchable_rate(cpi) : 0;
+#if CONFIG_MASKED_INTERINTER
+ if (is_comp_pred && get_mask_bits(bsize)) {
+ int mask_index, best_mask_index = MASK_NONE, rs;
+ int rate_sum;
+ int64_t dist_sum;
+ int64_t best_rd_nomask = INT64_MAX;
+ int64_t best_rd_mask = INT64_MAX;
+ int mask_types;
+ mbmi->use_masked_interinter = 0;
+ rs = vp9_cost_bit(cm->fc.masked_interinter_prob[bsize], 0);
+ vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+ rd = RDCOST(x->rdmult, x->rddiv, rs + rate_mv_tmp + rate_sum, dist_sum);
+ best_rd_nomask = rd;
+ mbmi->use_masked_interinter = 1;
+ rs = get_mask_bits(bsize) * 256 +
+ vp9_cost_bit(cm->fc.masked_interinter_prob[bsize], 1);
+ mask_types = (1 << get_mask_bits(bsize));
+ if (this_mode == NEWMV) {
+#define USE_MASKED_NEWMV_FAST_SEARCH
+#ifdef USE_MASKED_NEWMV_FAST_SEARCH
+ int_mv tmp_mv[2];
+ int rate_mvs[2], tmp_rate_mv;
+ for (mask_index = 0; mask_index < mask_types; ++mask_index) {
+ mbmi->mask_index = mask_index;
+ vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+ rd = RDCOST(x->rdmult, x->rddiv, rs + rate_mv_tmp + rate_sum, dist_sum);
+ if (rd < best_rd_mask) {
+ best_mask_index = mask_index;
+ best_rd_mask = rd;
+ }
+ }
+ mbmi->mask_index = best_mask_index;
+ do_masked_motion_search_indexed(cpi, x, mbmi->mask_index, bsize,
+ refs, mi_row, mi_col,
+ tmp_mv, rate_mvs);
+ tmp_rate_mv = rate_mvs[0] + rate_mvs[1];
+ mbmi->mv[0].as_int = tmp_mv[0].as_int;
+ mbmi->mv[1].as_int = tmp_mv[1].as_int;
+ vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+ rd = RDCOST(x->rdmult, x->rddiv, rs + tmp_rate_mv + rate_sum, dist_sum);
+ if (rd < best_rd_mask) {
+ best_rd_mask = rd;
+ } else {
+ mbmi->mv[0].as_int = cur_mv[0].as_int;
+ mbmi->mv[1].as_int = cur_mv[1].as_int;
+ tmp_rate_mv = rate_mv_tmp;
+ }
+ if (best_rd_mask < best_rd_nomask) {
+ mbmi->use_masked_interinter = 1;
+ mbmi->mask_index = best_mask_index;
+ if (cm->use_masked_interinter) {
+ xd->mi[0]->bmi[0].as_mv[0].as_int = mbmi->mv[0].as_int;
+ xd->mi[0]->bmi[0].as_mv[1].as_int = mbmi->mv[1].as_int;
+ rate_mv_tmp = tmp_rate_mv;
+ }
+ } else {
+ mbmi->use_masked_interinter = 0;
+ mbmi->mask_index = MASK_NONE;
+ mbmi->mv[0].as_int = cur_mv[0].as_int;
+ mbmi->mv[1].as_int = cur_mv[1].as_int;
+ }
+#else
+ int best_tmp_rate_mv = INT_MAX;
+ int_mv best_tmp_mv[2];
+ best_tmp_mv[0].as_int = 0;
+ best_tmp_mv[1].as_int = 0;
+ for (mask_index = 0; mask_index < mask_types; ++mask_index) {
+ int_mv tmp_mv[2];
+ int rate_mvs[2], tmp_rate_mv;
+ mbmi->mask_index = mask_index;
+ do_masked_motion_search_indexed(cpi, x, mask_index, bsize,
+ refs, mi_row, mi_col,
+ tmp_mv, rate_mvs);
+ tmp_rate_mv = rate_mvs[0] + rate_mvs[1];
+ mbmi->mv[0].as_int = tmp_mv[0].as_int;
+ mbmi->mv[1].as_int = tmp_mv[1].as_int;
+ vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+ rd = RDCOST(x->rdmult, x->rddiv, rs + tmp_rate_mv + rate_sum, dist_sum);
+ mbmi->mv[0].as_int = cur_mv[0].as_int;
+ mbmi->mv[1].as_int = cur_mv[1].as_int;
+ if (rd < best_rd_mask) {
+ best_mask_index = mask_index;
+ best_rd_mask = rd;
+ best_tmp_mv[0].as_int = tmp_mv[0].as_int;
+ best_tmp_mv[1].as_int = tmp_mv[1].as_int;
+ best_tmp_rate_mv = tmp_rate_mv;
+ }
+ }
+ if (best_rd_mask < best_rd_nomask) {
+ mbmi->use_masked_compound = 1;
+ mbmi->mask_index = best_mask_index;
+ if (cm->use_masked_compound) {
+ mbmi->mv[0].as_int = best_tmp_mv[0].as_int;
+ mbmi->mv[1].as_int = best_tmp_mv[1].as_int;
+ xd->mode_info_context->bmi[0].as_mv[0].as_int = best_tmp_mv[0].as_int;
+ xd->mode_info_context->bmi[0].as_mv[1].as_int = best_tmp_mv[1].as_int;
+ rate_mv_tmp = best_tmp_rate_mv;
+ }
+ } else {
+ mbmi->use_masked_compound = 0;
+ mbmi->mask_index = MASK_NONE;
+ }
+#endif
+ } else {
+ for (mask_index = 0; mask_index < mask_types; ++mask_index) {
+ mbmi->mask_index = mask_index;
+ vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+ rd = RDCOST(x->rdmult, x->rddiv, rs + rate_mv_tmp + rate_sum, dist_sum);
+ if (rd < best_rd_mask) {
+ best_mask_index = mask_index;
+ best_rd_mask = rd;
+ }
+ }
+ if (best_rd_mask < best_rd_nomask) {
+ mbmi->use_masked_interinter = 1;
+ mbmi->mask_index = best_mask_index;
+ } else {
+ mbmi->use_masked_interinter = 0;
+ mbmi->mask_index = MASK_NONE;
+ }
+ }
+
+ ++cpi->masked_interinter_select_counts[mbmi->use_masked_interinter];
+
+ if (!cm->use_masked_interinter) {
+ mbmi->use_masked_interinter = 0;
+ }
+ if (ref_best_rd < INT64_MAX &&
+ MIN(best_rd_mask, best_rd_nomask) / 2 > ref_best_rd)
+ return INT64_MAX;
+
+ pred_exists = 0;
+ if (mbmi->use_masked_interinter)
+ *compmode_interinter_cost = get_mask_bits(bsize) * 256 +
+ vp9_cost_bit(cm->fc.masked_interinter_prob[bsize], 1);
+ else
+ *compmode_interinter_cost = vp9_cost_bit
+ (cm->fc.masked_interinter_prob[bsize], 0);
+ }
+#endif // CONFIG_MASKED_INTERINTER
+
+#if CONFIG_INTERINTRA
+ if ((!is_comp_pred) && is_comp_interintra_pred &&
+ is_interintra_allowed(mbmi->sb_type)) {
+ PREDICTION_MODE interintra_mode, best_interintra_mode = DC_PRED;
+ int64_t best_interintra_rd = INT64_MAX;
+ int rmode, rate_sum;
+ int64_t dist_sum;
+ int j;
+#if CONFIG_MASKED_INTERINTRA
+ int maskbits, mask_types, mask_index, best_mask_index = -1;
+ int64_t best_interintra_rd_nomask, best_interintra_rd_mask = INT64_MAX;
+ int rmask;
+#define MASKED_INTERINTRA_REFINE_SEARCH
+#ifdef MASKED_INTERINTRA_REFINE_SEARCH
+ int bw = 4 << b_width_log2(mbmi->sb_type),
+ bh = 4 << b_height_log2(mbmi->sb_type);
+ uint8_t mask[4096];
+ int_mv tmp_mv;
+ int tmp_rate_mv = 0;
+#endif
+#endif
+ mbmi->ref_frame[1] = NONE;
+ for (j = 0; j < MAX_MB_PLANE; j++) {
+ xd->plane[j].dst.buf = tmp_buf + j * 64 * 64;
+ xd->plane[j].dst.stride = 64;
+ }
+ vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ restore_dst_buf(xd, orig_dst, orig_dst_stride);
+ mbmi->ref_frame[1] = INTRA_FRAME;
+
+ for (interintra_mode = DC_PRED; interintra_mode <= TM_PRED;
+ ++interintra_mode) {
+ mbmi->interintra_mode = interintra_mode;
+ mbmi->interintra_uv_mode = interintra_mode;
+ rmode = cpi->mbmode_cost[mbmi->interintra_mode];
+ vp9_build_interintra_predictors(xd, tmp_buf, tmp_buf + 64 * 64,
+ tmp_buf + 2* 64 * 64, 64, 64, 64, bsize);
+ model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+ rd = RDCOST(x->rdmult, x->rddiv, rmode + rate_sum, dist_sum);
+ if (rd < best_interintra_rd) {
+ best_interintra_rd = rd;
+ best_interintra_mode = interintra_mode;
+ }
+ }
+ mbmi->interintra_mode = best_interintra_mode;
+ mbmi->interintra_uv_mode = best_interintra_mode;
+#if CONFIG_MASKED_INTERINTRA
+ maskbits = get_mask_bits_interintra(bsize);
+ rmode = cpi->mbmode_cost[mbmi->interintra_mode];
+ if (maskbits) {
+ mbmi->use_masked_interintra = 0;
+ vp9_build_interintra_predictors(xd, tmp_buf, tmp_buf + 64 * 64,
+ tmp_buf + 2* 64 * 64, 64, 64, 64, bsize);
+ model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+ rmask = vp9_cost_bit(cm->fc.masked_interintra_prob[bsize], 0);
+ rd = RDCOST(x->rdmult, x->rddiv,
+ rmode + rate_mv_tmp + rmask + rate_sum, dist_sum);
+ best_interintra_rd_nomask = rd;
+
+ mbmi->use_masked_interintra = 1;
+ rmask = maskbits * 256 +
+ vp9_cost_bit(cm->fc.masked_interintra_prob[bsize], 1);
+ mask_types = (1 << maskbits);
+ for (mask_index = 0; mask_index < mask_types; ++mask_index) {
+ mbmi->interintra_mask_index = mask_index;
+ mbmi->interintra_uv_mask_index = mask_index;
+ vp9_build_interintra_predictors(xd, tmp_buf, tmp_buf + 64 * 64,
+ tmp_buf + 2* 64 * 64, 64, 64, 64, bsize);
+ model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+ rd = RDCOST(x->rdmult, x->rddiv,
+ rmode + rate_mv_tmp + rmask + rate_sum, dist_sum);
+ if (rd < best_interintra_rd_mask) {
+ best_interintra_rd_mask = rd;
+ best_mask_index = mask_index;
+ }
+ }
+#ifdef MASKED_INTERINTRA_REFINE_SEARCH
+ // Refine motion vector
+ if (this_mode == NEWMV) {
+ int j;
+ mbmi->interintra_mask_index = best_mask_index;
+ mbmi->interintra_uv_mask_index = best_mask_index;
+ vp9_generate_masked_weight_interintra(best_mask_index, bsize,
+ bh, bw, mask, bw);
+ for (i = 0; i < bh; ++i)
+ for (j = 0; j < bw; ++j)
+ mask[i * bw + j] = 64 - mask[i * bw + j];
+ do_masked_motion_search(cpi, x, mask, bw, bsize,
+ mi_row, mi_col, &tmp_mv, &tmp_rate_mv, 0);
+ mbmi->mv[0].as_int = tmp_mv.as_int;
+ vp9_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ model_rd_for_sb(cpi, bsize, x, xd, &rate_sum, &dist_sum);
+ rd = RDCOST(x->rdmult, x->rddiv,
+ rmode + tmp_rate_mv + rmask + rate_sum, dist_sum);
+ if (rd < best_interintra_rd_mask) {
+ best_interintra_rd_mask = rd;
+ } else {
+ tmp_mv.as_int = cur_mv[0].as_int;
+ tmp_rate_mv = rate_mv_tmp;
+ }
+ } else {
+ tmp_mv.as_int = cur_mv[0].as_int;
+ tmp_rate_mv = rate_mv_tmp;
+ }
+ mbmi->mv[0].as_int = tmp_mv.as_int;
+#endif
+ if (best_interintra_rd_mask < best_interintra_rd_nomask) {
+ mbmi->use_masked_interintra = 1;
+ if (cm->use_interintra && cm->use_masked_interintra) {
+ mbmi->interintra_mask_index = best_mask_index;
+ mbmi->interintra_uv_mask_index = best_mask_index;
+#ifdef MASKED_INTERINTRA_REFINE_SEARCH
+ mbmi->mv[0].as_int = tmp_mv.as_int;
+ rate_mv_tmp = tmp_rate_mv;
+#endif
+ } else {
+ mbmi->interintra_mode = best_interintra_mode;
+ mbmi->interintra_uv_mode = best_interintra_mode;
+ mbmi->mv[0].as_int = cur_mv[0].as_int;
+ }
+ best_interintra_rd = best_interintra_rd_mask;
+ } else {
+ mbmi->use_masked_interintra = 0;
+#ifdef MASKED_INTERINTRA_REFINE_SEARCH
+ mbmi->interintra_mode = best_interintra_mode;
+ mbmi->interintra_uv_mode = best_interintra_mode;
+ mbmi->mv[0].as_int = cur_mv[0].as_int;
+#endif
+ best_interintra_rd = best_interintra_rd_nomask;
+ }
+
+ ++cpi->masked_interintra_select_count[mbmi->use_masked_interintra];
+ if (!cm->use_masked_interintra)
+ mbmi->use_masked_interintra = 0;
+ }
+#endif
+ if (ref_best_rd < INT64_MAX &&
+ best_interintra_rd / 2 > ref_best_rd)
+ return INT64_MAX;
+
+ pred_exists = 0;
+ }
+
+ if (!is_comp_pred && is_interintra_allowed(mbmi->sb_type)) {
+ *compmode_interintra_cost = vp9_cost_bit(cm->fc.interintra_prob[bsize],
+ is_comp_interintra_pred);
+ if (is_comp_interintra_pred) {
+ *compmode_interintra_cost += cpi->mbmode_cost[mbmi->interintra_mode];
+#if CONFIG_MASKED_INTERINTRA
+ if (get_mask_bits_interintra(bsize) && cm->use_masked_interintra) {
+ *compmode_interintra_cost += vp9_cost_bit(
+ cm->fc.masked_interintra_prob[bsize],
+ mbmi->use_masked_interintra);
+ if (mbmi->use_masked_interintra) {
+ *compmode_interintra_cost += get_mask_bits_interintra(bsize) * 256;
+ }
+ }
+#endif
+ }
+ }
+#endif
+
+#if CONFIG_INTERINTRA || CONFIG_MASKED_INTERINTER
+ *rate2 += rate_mv_tmp;
+#endif
+
if (pred_exists) {
if (best_needs_copy) {
// again temporarily set the buffers to local memory to prevent a memcpy
int64_t sseuv = INT64_MAX;
int64_t rdcosty = INT64_MAX;
+#if CONFIG_EXT_TX
+ int64_t rdcost_tx;
+ int rate_y_tx;
+ int64_t distortion_y_tx;
+ int dummy;
+ int64_t best_rdcost_tx = INT64_MAX;
+ int best_ext_tx = NORM;
+ double th = 0.97;
+
+ for (i = 0; i < EXT_TX_TYPES; i++) {
+ mbmi->ext_txfrm = i;
+ inter_super_block_yrd(cpi, x, &rate_y_tx, &distortion_y_tx, &dummy, psse,
+ bsize, txfm_cache, INT64_MAX);
+ assert(rate_y_tx != INT_MAX);
+ if (mbmi->tx_size < TX_32X32)
+ rate_y_tx += vp9_cost_bit(cm->fc.ext_tx_prob, i);
+ assert(rate_y_tx >= 0);
+ rdcost_tx = RDCOST(x->rdmult, x->rddiv, rate_y_tx, distortion_y_tx);
+ rdcost_tx = MIN(rdcost_tx, RDCOST(x->rdmult, x->rddiv, 0, *psse));
+ assert(rdcost_tx >= 0);
+ if (rdcost_tx < best_rdcost_tx * th) {
+ best_ext_tx = i;
+ best_rdcost_tx = rdcost_tx;
+ }
+ }
+ if (mbmi->tx_size == TX_32X32)
+ mbmi->ext_txfrm = NORM;
+ else
+ mbmi->ext_txfrm = best_ext_tx;
+#endif
+
// Y cost and distortion
inter_super_block_yrd(cpi, x, rate_y, distortion_y, &skippable_y, psse,
bsize, txfm_cache, ref_best_rd);
}
*rate2 += *rate_y;
+#if CONFIG_EXT_TX
+ if (mbmi->tx_size < TX_32X32)
+ *rate2 += vp9_cost_bit(cm->fc.ext_tx_prob, mbmi->ext_txfrm);
+#endif
*distortion += *distortion_y;
rdcosty = RDCOST(x->rdmult, x->rddiv, *rate2, *distortion);
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
struct buf_2d yv12_mb[4][MAX_MB_PLANE];
int_mv single_newmv[MAX_REF_FRAMES] = { { 0 } };
+#if CONFIG_INTERINTRA
+ int single_newmv_rate[MAX_REF_FRAMES] = { 0 };
+#endif
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
int64_t best_rd = best_rd_so_far;
int64_t dist_uv[TX_SIZES];
int skip_uv[TX_SIZES];
PREDICTION_MODE mode_uv[TX_SIZES];
+#if CONFIG_FILTERINTRA
+ int fbit_uv[TX_SIZES];
+#endif
int64_t mode_distortions[MB_MODE_COUNT] = {-1};
int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
const int bws = num_8x8_blocks_wide_lookup[bsize] / 2;
const int intra_y_mode_mask =
cpi->sf.intra_y_mode_mask[max_txsize_lookup[bsize]];
int inter_mode_mask = cpi->sf.inter_mode_mask[bsize];
+#if CONFIG_INTERINTRA
+ int64_t best_overall_rd = INT64_MAX;
+ int is_best_interintra = 0;
+ int start_skip = 0;
+ int mode_skip_mask_interintra = 0;
+#endif
vp9_zero(best_mbmode);
x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
int64_t this_rd = INT64_MAX;
int disable_skip = 0;
int compmode_cost = 0;
+#if CONFIG_MASKED_INTERINTER
+ int compmode_masked_cost = 0;
+#endif
+#if CONFIG_INTERINTRA
+ int compmode_interintra_cost = 0;
+#endif
int rate2 = 0, rate_y = 0, rate_uv = 0;
int64_t distortion2 = 0, distortion_y = 0, distortion_uv = 0;
int skippable = 0;
int64_t total_sse = INT64_MAX;
int early_term = 0;
+#if CONFIG_INTERINTRA
+ if (mode_index < 30) {
+#endif
// Look at the reference frame of the best mode so far and set the
// skip mask to look at a subset of the remaining modes.
if (mode_index == mode_skip_start && best_mode_index >= 0) {
}
if (mode_skip_mask & (1 << mode_index))
continue;
+#if CONFIG_INTERINTRA
+ }
+#define INTERINTRA_SPEEDUP
+#ifdef INTERINTRA_SPEEDUP
+ if (!start_skip && mode_index >= 30) {
+ start_skip = 1;
+ if (best_mode_index >= 0) {
+ if (vp9_mode_order[best_mode_index].ref_frame[1] == NONE) {
+ switch (vp9_mode_order[best_mode_index].ref_frame[0]) {
+ case INTRA_FRAME:
+ break;
+ case LAST_FRAME:
+ if (vp9_mode_order[best_mode_index].mode == NEWMV)
+ mode_skip_mask_interintra |= 0xFF0;
+ else
+ mode_skip_mask_interintra |= 0xFF8;
+ break;
+ case GOLDEN_FRAME:
+ if (vp9_mode_order[best_mode_index].mode == NEWMV)
+ mode_skip_mask_interintra |= 0xF0F;
+ else
+ mode_skip_mask_interintra |= 0xF8F;
+ break;
+ case ALTREF_FRAME:
+ if (vp9_mode_order[best_mode_index].mode == NEWMV)
+ mode_skip_mask_interintra |= 0x0FF;
+ else
+ mode_skip_mask_interintra |= 0x8FF;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (vp9_mode_order[best_mode_index].ref_frame[0]) {
+ case LAST_FRAME:
+ mode_skip_mask_interintra |= 0x0F0;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ if (mode_skip_mask_interintra & (1 << (mode_index - 30)))
+ continue;
+#endif
+#endif
+
// Test best rd so far against threshold for trying this mode.
if (rd_less_than_thresh(best_rd, rd_threshes[mode_index],
} else {
if (ref_frame != INTRA_FRAME)
mode_excluded = cm->reference_mode == COMPOUND_REFERENCE;
+#if CONFIG_INTERINTRA
+ if (ref_frame > INTRA_FRAME && second_ref_frame == INTRA_FRAME)
+ mode_excluded = mode_excluded? mode_excluded : !cm->use_interintra;
+#endif
}
if (ref_frame == INTRA_FRAME) {
inter_mode_mask, this_mode, ref_frames))
continue;
}
+#if CONFIG_INTERINTRA
+ if (ref_frame > INTRA_FRAME && second_ref_frame == INTRA_FRAME &&
+ !is_interintra_allowed(bsize))
+ continue;
+#endif
mbmi->mode = this_mode;
mbmi->uv_mode = DC_PRED;
for (i = 0; i < TX_MODES; ++i)
tx_cache[i] = INT64_MAX;
+#if CONFIG_MASKED_INTERINTER
+ mbmi->use_masked_interinter = 0;
+ mbmi->mask_index = MASK_NONE;
+#endif
+#if CONFIG_INTERINTRA
+ mbmi->interintra_mode = (PREDICTION_MODE)(DC_PRED - 1);
+ mbmi->interintra_uv_mode = (PREDICTION_MODE)(DC_PRED - 1);
+#endif
if (ref_frame == INTRA_FRAME) {
TX_SIZE uv_tx;
+#if CONFIG_FILTERINTRA
+ mbmi->filterbit = 0;
+#endif
intra_super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable, NULL,
bsize, tx_cache, best_rd);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(this_mode) && is_filter_enabled(mbmi->tx_size)) {
+ int rate_y_tmp, rate0, rate1, skippable_tmp;
+ int64_t distortion_y_tmp, tx_cache_tmp[TX_MODES];
+ int tx_size_tmp = mbmi->tx_size;
+ mbmi->filterbit = 0;
+
+ intra_super_block_yrd(cpi, x, &rate_y_tmp, &distortion_y_tmp,
+ &skippable_tmp, NULL, bsize, tx_cache_tmp,
+ best_rd);
+
+ if (rate_y == INT_MAX && rate_y_tmp == INT_MAX)
+ continue;
+
+ rate0 = vp9_cost_bit(
+ cm->fc.filterintra_prob[tx_size_tmp][mbmi->mode], 0);
+ rate1 = vp9_cost_bit(
+ cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode], 1);
+
+ if (rate_y_tmp == INT_MAX ||
+ RDCOST(x->rdmult, x->rddiv, rate_y + rate0, distortion_y) <=
+ RDCOST(x->rdmult, x->rddiv, rate_y_tmp + rate1, distortion_y_tmp)) {
+ mbmi->filterbit = 0;
+ mbmi->tx_size = tx_size_tmp;
+ } else {
+ rate_y = rate_y_tmp;
+ distortion_y = distortion_y_tmp;
+ skippable = skippable_tmp;
+ vpx_memcpy(tx_cache, tx_cache_tmp, TX_MODES * sizeof(int64_t));
+ }
+ }
+#endif
+
if (rate_y == INT_MAX)
continue;
if (rate_uv_intra[uv_tx] == INT_MAX) {
choose_intra_uv_mode(cpi, 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]);
+ &dist_uv[uv_tx], &skip_uv[uv_tx],
+#if CONFIG_FILTERINTRA
+ &fbit_uv[uv_tx],
+#endif
+ &mode_uv[uv_tx]);
}
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_FILTERINTRA
+ mbmi->uv_filterbit = fbit_uv[uv_tx];
+#endif
rate2 = rate_y + cpi->mbmode_cost[mbmi->mode] + rate_uv_intra[uv_tx];
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mbmi->mode) && is_filter_enabled(mbmi->tx_size))
+ rate2 += vp9_cost_bit(
+ cm->fc.filterintra_prob[mbmi->tx_size][mbmi->mode], mbmi->filterbit);
+#endif
if (this_mode != DC_PRED && this_mode != TM_PRED)
rate2 += intra_cost_penalty;
distortion2 = distortion_y + distortion_uv;
} else {
+#if CONFIG_INTERINTRA
+ if (second_ref_frame == INTRA_FRAME) {
+ mbmi->interintra_mode = best_intra_mode;
+ mbmi->interintra_uv_mode = best_intra_mode;
+ }
+#endif
+#if CONFIG_EXT_TX
+ mbmi->ext_txfrm = NORM;
+#endif
this_rd = handle_inter_mode(cpi, x, bsize,
tx_cache,
&rate2, &distortion2, &skippable,
+#if CONFIG_MASKED_INTERINTER
+ &compmode_masked_cost,
+#endif
+#if CONFIG_INTERINTRA
+ &compmode_interintra_cost,
+#endif
&rate_y, &distortion_y,
&rate_uv, &distortion_uv,
&mode_excluded, &disable_skip,
&tmp_best_filter, frame_mv,
mi_row, mi_col,
- single_newmv, &total_sse, best_rd);
+ single_newmv,
+#if CONFIG_INTERINTRA
+ single_newmv_rate,
+#endif
+ &total_sse, best_rd);
if (this_rd == INT64_MAX)
continue;
rate2 += compmode_cost;
}
+#if CONFIG_MASKED_INTERINTER
+ if ((cm->reference_mode == REFERENCE_MODE_SELECT ||
+ cm->reference_mode == COMPOUND_REFERENCE) &&
+ cm->use_masked_interinter && comp_pred)
+ rate2 += compmode_masked_cost;
+#endif
+#if CONFIG_INTERINTRA
+ if (cm->use_interintra)
+ rate2 += compmode_interintra_cost;
+#endif
+
// Estimate the reference frame signaling cost and add it
// to the rolling cost variable.
if (comp_pred) {
mode_distortions[this_mode] = distortion2;
}
+#if CONFIG_INTERINTRA
+ if (this_rd < best_overall_rd) {
+ best_overall_rd = this_rd;
+ is_best_interintra = (second_ref_frame == INTRA_FRAME);
+ }
+#endif
+
// Did this mode help.. i.e. is it the new best mode
if (this_rd < best_rd || x->skip) {
int max_plane = MAX_MB_PLANE;
break;
}
+#if CONFIG_INTERINTRA
+ if (best_mode_index >= 0)
+ ++cpi->interintra_select_count[is_best_interintra];
+#endif
+
if (best_mode_index < 0 || best_rd >= best_rd_so_far)
return INT64_MAX;
int64_t dist_uv;
int skip_uv;
PREDICTION_MODE mode_uv = DC_PRED;
+#if CONFIG_FILTERINTRA
+ int fbit_uv = 0;
+#endif
int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
int_mv seg_mvs[4][MAX_REF_FRAMES];
b_mode_info best_bmodes[4];
int best_skip2 = 0;
int mode_skip_mask = 0;
+#if CONFIG_MASKED_INTERINTER
+ mbmi->use_masked_interinter = 0;
+ mbmi->mask_index = MASK_NONE;
+#endif
+#if CONFIG_INTERINTRA && CONFIG_MASKED_INTERINTRA
+ mbmi->use_masked_interintra = 0;
+ mbmi->interintra_mask_index = MASK_NONE_INTERINTRA;
+ mbmi->interintra_uv_mask_index = MASK_NONE_INTERINTRA;
+#endif
+#if CONFIG_EXT_TX
+ mbmi->ext_txfrm = NORM;
+#endif
x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
vpx_memset(x->zcoeff_blk[TX_4X4], 0, 4);
&rate_uv_intra,
&rate_uv_tokenonly,
&dist_uv, &skip_uv,
+#if CONFIG_FILTERINTRA
+ &fbit_uv,
+#endif
&mode_uv);
}
rate2 += rate_uv_intra;
distortion2 += dist_uv;
distortion_uv = dist_uv;
mbmi->uv_mode = mode_uv;
+#if CONFIG_FILTERINTRA
+ mbmi->uv_filterbit = fbit_uv;
+#endif
} else {
int rate;
int64_t distortion;
rd->thresh_mult[THR_D207_PRED] += 2500;
rd->thresh_mult[THR_D63_PRED] += 2500;
+#if CONFIG_INTERINTRA
+ rd->thresh_mult[THR_COMP_INTERINTRA_ZEROL ] += 1500;
+ rd->thresh_mult[THR_COMP_INTERINTRA_ZEROG ] += 1500;
+ rd->thresh_mult[THR_COMP_INTERINTRA_ZEROA ] += 1500;
+
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] += 1500;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] += 1500;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] += 1500;
+
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARL ] += 1500;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARG ] += 1500;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARA ] += 1500;
+
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEWL ] += 2000;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEWG ] += 2000;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEWA ] += 2000;
+#endif
+
/* disable frame modes if flags not set */
if (!(cpi->ref_frame_flags & VP9_LAST_FLAG)) {
rd->thresh_mult[THR_NEWMV ] = INT_MAX;
rd->thresh_mult[THR_NEARESTMV] = INT_MAX;
rd->thresh_mult[THR_ZEROMV ] = INT_MAX;
rd->thresh_mult[THR_NEARMV ] = INT_MAX;
+#if CONFIG_INTERINTRA
+ rd->thresh_mult[THR_COMP_INTERINTRA_ZEROL ] = INT_MAX;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTL] = INT_MAX;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARL ] = INT_MAX;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEWL ] = INT_MAX;
+#endif
}
if (!(cpi->ref_frame_flags & VP9_GOLD_FLAG)) {
rd->thresh_mult[THR_NEARESTG ] = INT_MAX;
rd->thresh_mult[THR_ZEROG ] = INT_MAX;
rd->thresh_mult[THR_NEARG ] = INT_MAX;
rd->thresh_mult[THR_NEWG ] = INT_MAX;
+#if CONFIG_INTERINTRA
+ rd->thresh_mult[THR_COMP_INTERINTRA_ZEROG ] = INT_MAX;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTG] = INT_MAX;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARG ] = INT_MAX;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEWG ] = INT_MAX;
+#endif
}
if (!(cpi->ref_frame_flags & VP9_ALT_FLAG)) {
rd->thresh_mult[THR_NEARESTA ] = INT_MAX;
rd->thresh_mult[THR_ZEROA ] = INT_MAX;
rd->thresh_mult[THR_NEARA ] = INT_MAX;
rd->thresh_mult[THR_NEWA ] = INT_MAX;
+#if CONFIG_INTERINTRA
+ rd->thresh_mult[THR_COMP_INTERINTRA_ZEROA ] = INT_MAX;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARESTA] = INT_MAX;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEARA ] = INT_MAX;
+ rd->thresh_mult[THR_COMP_INTERINTRA_NEWA ] = INT_MAX;
+#endif
}
if ((cpi->ref_frame_flags & (VP9_LAST_FLAG | VP9_ALT_FLAG)) !=
#define INVALID_MV 0x80008000
+#if !CONFIG_INTERINTRA
#define MAX_MODES 30
+#else
+#define MAX_MODES 42
+#endif
#define MAX_REFS 6
// This enumerator type needs to be kept aligned with the mode order in
THR_D63_PRED,
THR_D117_PRED,
THR_D45_PRED,
+
+#if CONFIG_INTERINTRA
+ THR_COMP_INTERINTRA_ZEROL,
+ THR_COMP_INTERINTRA_NEARESTL,
+ THR_COMP_INTERINTRA_NEARL,
+ THR_COMP_INTERINTRA_NEWL,
+
+ THR_COMP_INTERINTRA_ZEROG,
+ THR_COMP_INTERINTRA_NEARESTG,
+ THR_COMP_INTERINTRA_NEARG,
+ THR_COMP_INTERINTRA_NEWG,
+
+ THR_COMP_INTERINTRA_ZEROA,
+ THR_COMP_INTERINTRA_NEARESTA,
+ THR_COMP_INTERINTRA_NEARA,
+ THR_COMP_INTERINTRA_NEWA,
+#endif
} THR_MODES;
typedef enum {
sadMxNxK(4, 4, 3)
sadMxNxK(4, 4, 8)
sadMxNx4D(4, 4)
+
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+ CONFIG_MASKED_INTERINTER)
+static INLINE unsigned int masked_sad(const uint8_t *a, int a_stride,
+ const uint8_t *b, int b_stride,
+ const uint8_t *m, int m_stride,
+ int width, int height) {
+ int y, x;
+ unsigned int sad = 0;
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++)
+ sad += m[x] * abs(a[x] - b[x]);
+
+ a += a_stride;
+ b += b_stride;
+ m += m_stride;
+ }
+ sad = (sad + 31) >> 6;
+
+ return sad;
+}
+
+#define MASKSADMxN(m, n) \
+unsigned int vp9_masked_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
+ const uint8_t *ref, int ref_stride, \
+ const uint8_t *msk, int msk_stride) { \
+ return masked_sad(src, src_stride, ref, ref_stride, msk, msk_stride, m, n); \
+}
+
+MASKSADMxN(64, 64)
+MASKSADMxN(64, 32)
+MASKSADMxN(32, 64)
+MASKSADMxN(32, 32)
+MASKSADMxN(32, 16)
+MASKSADMxN(16, 32)
+MASKSADMxN(16, 16)
+MASKSADMxN(16, 8)
+MASKSADMxN(8, 16)
+MASKSADMxN(8, 8)
+MASKSADMxN(8, 4)
+MASKSADMxN(4, 8)
+MASKSADMxN(4, 4)
+#endif
ref += ref_stride;
}
}
+
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+ CONFIG_MASKED_INTERINTER)
+void masked_variance(const uint8_t *a, int a_stride,
+ const uint8_t *b, int b_stride,
+ const uint8_t *m, int m_stride,
+ int w, int h, unsigned int *sse, int *sum) {
+ int i, j;
+
+ *sum = 0;
+ *sse = 0;
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ const int diff = (a[j] - b[j]) * (m[j]);
+ *sum += diff;
+ *sse += diff * diff;
+ }
+
+ a += a_stride;
+ b += b_stride;
+ m += m_stride;
+ }
+ *sum = (*sum >= 0) ? ((*sum + 31) >> 6) : -((-*sum + 31) >> 6);
+ *sse = (*sse + 2047) >> 12;
+}
+
+#define MASK_VAR(W, H) \
+unsigned int vp9_masked_variance##W##x##H##_c(const uint8_t *a, int a_stride, \
+ const uint8_t *b, int b_stride, \
+ const uint8_t *m, int m_stride, \
+ unsigned int *sse) { \
+ int sum; \
+ masked_variance(a, a_stride, b, b_stride, m, m_stride, W, H, sse, &sum); \
+ return *sse - (((int64_t)sum * sum) / (W * H)); \
+}
+
+#define MASK_SUBPIX_VAR(W, H) \
+unsigned int vp9_masked_sub_pixel_variance##W##x##H##_c( \
+ const uint8_t *src, int src_stride, \
+ int xoffset, int yoffset, \
+ const uint8_t *dst, int dst_stride, \
+ const uint8_t *msk, int msk_stride, \
+ unsigned int *sse) { \
+ uint16_t fdata3[(H + 1) * W]; \
+ uint8_t temp2[H * W]; \
+\
+ var_filter_block2d_bil_first_pass(src, fdata3, src_stride, 1, H + 1, W, \
+ BILINEAR_FILTERS_2TAP(xoffset)); \
+ var_filter_block2d_bil_second_pass(fdata3, temp2, W, W, H, W, \
+ BILINEAR_FILTERS_2TAP(yoffset)); \
+\
+ return vp9_masked_variance##W##x##H##_c(temp2, W, dst, dst_stride, \
+ msk, msk_stride, sse); \
+}
+
+MASK_VAR(4, 4)
+MASK_SUBPIX_VAR(4, 4)
+
+MASK_VAR(4, 8)
+MASK_SUBPIX_VAR(4, 8)
+
+MASK_VAR(8, 4)
+MASK_SUBPIX_VAR(8, 4)
+
+MASK_VAR(8, 8)
+MASK_SUBPIX_VAR(8, 8)
+
+MASK_VAR(8, 16)
+MASK_SUBPIX_VAR(8, 16)
+
+MASK_VAR(16, 8)
+MASK_SUBPIX_VAR(16, 8)
+
+MASK_VAR(16, 16)
+MASK_SUBPIX_VAR(16, 16)
+
+MASK_VAR(16, 32)
+MASK_SUBPIX_VAR(16, 32)
+
+MASK_VAR(32, 16)
+MASK_SUBPIX_VAR(32, 16)
+
+MASK_VAR(32, 32)
+MASK_SUBPIX_VAR(32, 32)
+
+MASK_VAR(32, 64)
+MASK_SUBPIX_VAR(32, 64)
+
+MASK_VAR(64, 32)
+MASK_SUBPIX_VAR(64, 32)
+
+MASK_VAR(64, 64)
+MASK_SUBPIX_VAR(64, 64)
+#endif
unsigned int *sse,
const uint8_t *second_pred);
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+ CONFIG_MASKED_INTERINTER)
+typedef unsigned int(*vp9_masked_sad_fn_t)(const uint8_t *src_ptr,
+ int source_stride,
+ const uint8_t *ref_ptr,
+ int ref_stride,
+ const uint8_t *msk_ptr,
+ int msk_stride);
+typedef unsigned int (*vp9_masked_variance_fn_t)(const uint8_t *src_ptr,
+ int source_stride,
+ const uint8_t *ref_ptr,
+ int ref_stride,
+ const uint8_t *msk_ptr,
+ int msk_stride,
+ unsigned int *sse);
+typedef unsigned int (*vp9_masked_subpixvariance_fn_t)(const uint8_t *src_ptr,
+ int source_stride,
+ int xoffset,
+ int yoffset,
+ const uint8_t *ref_ptr,
+ int Refstride,
+ const uint8_t *msk_ptr,
+ int msk_stride,
+ unsigned int *sse);
+#endif
+
typedef struct vp9_variance_vtable {
vp9_sad_fn_t sdf;
vp9_sad_avg_fn_t sdaf;
vp9_sad_multi_fn_t sdx3f;
vp9_sad_multi_fn_t sdx8f;
vp9_sad_multi_d_fn_t sdx4df;
+#if ((CONFIG_MASKED_INTERINTRA && CONFIG_INTERINTRA) || \
+ CONFIG_MASKED_INTERINTER)
+ vp9_masked_sad_fn_t msdf;
+ vp9_masked_variance_fn_t mvf;
+ vp9_masked_subpixvariance_fn_t msvf;
+#endif
} vp9_variance_fn_ptr_t;
void vp9_comp_avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,