non420
alpha
interintra
+ filterintra
"
CONFIG_LIST="
external_build
return mode >= NEARESTMV && mode <= NEWMV;
}
+#if CONFIG_FILTERINTRA
+static INLINE int is_filter_allowed(MB_PREDICTION_MODE mode) {
+ return mode != DC_PRED &&
+ mode != D45_PRED &&
+ mode != D27_PRED &&
+ mode != D63_PRED;
+}
+#endif
+
#define VP9_INTRA_MODES (TM_PRED + 1)
#define VP9_INTER_MODES (1 + NEWMV - NEARESTMV)
MB_PREDICTION_MODE mode, uv_mode;
#if CONFIG_INTERINTRA
MB_PREDICTION_MODE interintra_mode, interintra_uv_mode;
+#endif
+#if CONFIG_FILTERINTRA
+ int filterbit, uv_filterbit;
#endif
MV_REFERENCE_FRAME ref_frame[2];
TX_SIZE txfm_size;
typedef struct {
MB_MODE_INFO mbmi;
+#if CONFIG_FILTERINTRA
+ int b_filter_info[4];
+#endif
union b_mode_info bmi[4];
} MODE_INFO;
}
};
+#if CONFIG_FILTERINTRA
+const vp9_prob vp9_default_filterintra_prob[TX_SIZES][VP9_INTRA_MODES] = {
+ // DC V H D45 D135 D117 D153 D27 D63 TM
+ {160, 160, 160, 160, 160, 160, 160, 160, 160, 160}, // TX_4X4
+ {180, 180, 180, 180, 180, 180, 180, 180, 180, 180}, // TX_8X8
+ {200, 200, 200, 200, 200, 200, 200, 200, 200, 200}, // TX_16X16
+ {220, 220, 220, 220, 220, 220, 220, 220, 220, 220}, // TX_32X32
+};
+#endif
+
static const vp9_prob default_inter_mode_probs[INTER_MODE_CONTEXTS]
[VP9_INTER_MODES - 1] = {
{2, 173, 34}, // 0 = both zero mv
#if CONFIG_INTERINTRA
cm->fc.interintra_prob = VP9_DEF_INTERINTRA_PROB;
#endif
+#if CONFIG_FILTERINTRA
+ vp9_copy(cm->fc.filterintra_prob, vp9_default_filterintra_prob);
+#endif
}
const vp9_tree_index vp9_switchable_interp_tree[VP9_SWITCHABLE_FILTERS*2-2] = {
counts->interintra);
}
#endif
+#if CONFIG_FILTERINTRA
+ for (i = 0; i < TX_SIZES; ++i)
+ for (j = 0; j < VP9_INTRA_MODES; ++j)
+ fc->filterintra_prob[i][j] = update_ct2(pre_fc->filterintra_prob[i][j],
+ counts->filterintra[i][j]);
+#endif
}
static void set_default_lf_deltas(struct loopfilter *lf) {
#if CONFIG_INTERINTRA
vp9_prob interintra_prob;
#endif
+#if CONFIG_FILTERINTRA
+ vp9_prob filterintra_prob[TX_SIZES][VP9_INTRA_MODES];
+#endif
} FRAME_CONTEXT;
typedef struct {
#if CONFIG_INTERINTRA
unsigned int interintra[2];
#endif
+#if CONFIG_FILTERINTRA
+ unsigned int filterintra[TX_SIZES][VP9_INTRA_MODES][2];
+#endif
} FRAME_COUNTS;
}
}
+#if CONFIG_FILTERINTRA
+static void filter_intra_predictors(uint8_t *ypred_ptr, int y_stride, int bs,
+ uint8_t *yabove_row, uint8_t *yleft_col,
+ int mode) {
+ static const int prec_bits = 10;
+ static const int round_val = 511;
+ static const int taps[10][3] = {
+ {438 , 660, -352}, // DC
+ {1014, 565, -559}, // V
+ {312, 1017, -312}, // H
+ {0, 0, 0}, // D45
+ {478, 483, 153}, // D135
+ {699, 470, -122}, // D117
+ {356, 707, 35}, // D153
+ {0, 0, 0}, // D27
+ {0, 0, 0}, // D63
+ {877, 896, -812} // TM
+ };
+ int k, r, c;
+ int pred[17][17];
+ int mean, ipred;
+ const int c1 = taps[mode][0];
+ const int c2 = taps[mode][1];
+ const int c3 = taps[mode][2];
+
+ k = 0;
+ mean = 0;
+ while (k < bs) {
+ mean = mean + (int)yleft_col[r];
+ mean = mean + (int)yabove_row[c];
+ 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 < bs + 1; c++)
+ pred[0][c] = (int)yabove_row[c - 1] - mean;
+
+ for (r = 1; r < bs + 1; r++)
+ for (c = 1; c < bs + 1; c++) {
+ ipred = c1 * pred[r - 1][c] + c2 * pred[r][c - 1]
+ + c3 * 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(uint8_t *src, int src_stride,
+ uint8_t *pred_ptr, int stride,
+ MB_PREDICTION_MODE mode, TX_SIZE txsz,
+ int up_available, int left_available,
+ int right_available) {
+ int i;
+ DECLARE_ALIGNED_ARRAY(16, uint8_t, left_col, 64);
+ DECLARE_ALIGNED_ARRAY(16, uint8_t, yabove_data, 128 + 16);
+ uint8_t *above_row = yabove_data + 16;
+ const int bs = 4 << txsz;
+
+ if (left_available) {
+ for (i = 0; i < bs; i++)
+ left_col[i] = src[i * src_stride - 1];
+ } else {
+ vpx_memset(left_col, 129, bs);
+ }
+
+ if (up_available) {
+ uint8_t *above_ptr = src - src_stride;
+ if (bs == 4 && right_available && left_available) {
+ above_row = above_ptr;
+ } else {
+ vpx_memcpy(above_row, above_ptr, bs);
+ if (bs == 4 && right_available)
+ vpx_memcpy(above_row + bs, above_ptr + bs, bs);
+ else
+ vpx_memset(above_row + bs, above_row[bs - 1], bs);
+ above_row[-1] = left_available ? above_ptr[-1] : 129;
+ }
+ } else {
+ vpx_memset(above_row, 127, bs * 2);
+ above_row[-1] = 127;
+ }
+
+ filter_intra_predictors(pred_ptr, stride, bs, above_row, left_col, mode);
+}
+#endif
+
void vp9_predict_intra_block(MACROBLOCKD *xd,
int block_idx,
int bwl_in,
TX_SIZE tx_size,
int mode,
+#if CONFIG_FILTERINTRA
+ int filterbit,
+#endif
uint8_t *reference, int ref_stride,
uint8_t *predictor, int pre_stride) {
const int bwl = bwl_in - tx_size;
const int have_top = (block_idx >> bwl) || xd->up_available;
const int have_left = (block_idx & wmask) || xd->left_available;
const int have_right = ((block_idx & wmask) != wmask);
+#if CONFIG_FILTERINTRA
+ int filterflag = is_filter_allowed(mode) && (tx_size <= TX_8X8) && filterbit;
+#endif
assert(bwl >= 0);
+#if CONFIG_FILTERINTRA
+ if (!filterflag) {
+#endif
build_intra_predictors(reference, ref_stride,
predictor, pre_stride,
mode,
tx_size,
have_top, have_left,
have_right);
+#if CONFIG_FILTERINTRA
+ } else {
+ build_filter_intra_predictors(reference, ref_stride,
+ predictor, pre_stride,
+ mode,
+ tx_size,
+ have_top, have_left,
+ have_right);
+ }
+#endif
}
#if CONFIG_INTERINTRA
// Break down rectangular intra prediction for joint spatio-temporal prediction
// into two square intra predictions.
-void build_intra_predictors_for_interintra(uint8_t *src, int src_stride,
+static void build_intra_predictors_for_interintra(uint8_t *src, int src_stride,
uint8_t *pred_ptr, int stride,
MB_PREDICTION_MODE mode,
int bw, int bh,
int block_idx,
int bwl_in,
TX_SIZE tx_size,
- int mode, uint8_t *ref, int ref_stride,
+ int mode,
+#if CONFIG_FILTERINTRA
+ int filterbit,
+#endif
+ uint8_t *ref, int ref_stride,
uint8_t *predictor, int pre_stride);
#if CONFIG_INTERINTRA
void vp9_build_interintra_predictors(MACROBLOCKD *xd,
const MB_PREDICTION_MODE L = xd->left_available ?
left_block_mode(m, 0) : DC_PRED;
mbmi->mode = read_intra_mode(r, vp9_kf_y_mode_prob[A][L]);
+#if CONFIG_FILTERINTRA
+ if ((mbmi->txfm_size <= TX_8X8) && is_filter_allowed(mbmi->mode))
+ mbmi->filterbit = vp9_read(r,
+ cm->fc.filterintra_prob[mbmi->txfm_size][mbmi->mode]);
+ else
+ mbmi->filterbit = 0;
+#endif
} else {
// Only 4x4, 4x8, 8x4 blocks
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize]; // 1 or 2
m->bmi[ib + 2].as_mode = b_mode;
if (num_4x4_w == 2)
m->bmi[ib + 1].as_mode = b_mode;
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(b_mode))
+ m->b_filter_info[ib] = vp9_read(r,
+ cm->fc.filterintra_prob[0][b_mode]);
+ else
+ m->b_filter_info[ib] = 0;
+ if (num_4x4_h == 2)
+ m->b_filter_info[ib + 2] = m->b_filter_info[ib];
+ if (num_4x4_w == 2)
+ m->b_filter_info[ib + 1] = m->b_filter_info[ib];
+#endif
}
}
mbmi->mode = m->bmi[3].as_mode;
+#if CONFIG_FILTERINTRA
+ mbmi->filterbit = m->b_filter_info[3];
+#endif
}
mbmi->uv_mode = read_intra_mode(r, vp9_kf_uv_mode_prob[mbmi->mode]);
+#if CONFIG_FILTERINTRA
+ if ((get_uv_tx_size(mbmi) <= TX_8X8) && 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,
const int size_group = size_group_lookup[bsize];
mbmi->mode = read_intra_mode(r, cm->fc.y_mode_prob[size_group]);
cm->counts.y_mode[size_group][mbmi->mode]++;
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mbmi->mode) && (mbmi->txfm_size <= TX_8X8)) {
+ mbmi->filterbit = vp9_read(r,
+ cm->fc.filterintra_prob[mbmi->txfm_size][mbmi->mode]);
+ cm->counts.filterintra[mbmi->txfm_size][mbmi->mode][mbmi->filterbit]++;
+ } else {
+ mbmi->filterbit = 0;
+ }
+#endif
} else {
// Only 4x4, 4x8, 8x4 blocks
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize]; // 1 or 2
mi->bmi[ib + 2].as_mode = b_mode;
if (num_4x4_w == 2)
mi->bmi[ib + 1].as_mode = b_mode;
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(b_mode)) {
+ mi->b_filter_info[ib] = vp9_read(r,
+ cm->fc.filterintra_prob[0][b_mode]);
+ cm->counts.filterintra[0][b_mode][mi->b_filter_info[ib]]++;
+ } else {
+ mi->b_filter_info[ib] = 0;
+ }
+
+ if (num_4x4_h == 2)
+ mi->b_filter_info[ib + 2] = mi->b_filter_info[ib];
+ if (num_4x4_w == 2)
+ mi->b_filter_info[ib + 1] = mi->b_filter_info[ib];
+#endif
}
}
mbmi->mode = mi->bmi[3].as_mode;
+#if CONFIG_FILTERINTRA
+ mbmi->filterbit = mi->b_filter_info[3];
+#endif
}
mbmi->uv_mode = read_intra_mode(r, cm->fc.uv_mode_prob[mbmi->mode]);
cm->counts.uv_mode[mbmi->mode][mbmi->uv_mode]++;
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mbmi->uv_mode) && (get_uv_tx_size(mbmi) <= TX_8X8)) {
+ 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 int read_is_inter_block(VP9D_COMP *pbi, int segment_id, vp9_reader *r) {
const int tx_ib = raster_block >> tx_size;
const int mode = plane == 0 ? mi->mbmi.mode
: mi->mbmi.uv_mode;
+#if CONFIG_FILTERINTRA
+ int fbit = 0;
+#endif
if (plane == 0 && mi->mbmi.sb_type < BLOCK_8X8) {
assert(bsize == BLOCK_8X8);
b_mode = mi->bmi[raster_block].as_mode;
+#if CONFIG_FILTERINTRA
+ fbit = mi->b_filter_info[raster_block];
+#endif
} else {
b_mode = mode;
+#if CONFIG_FILTERINTRA
+ if (tx_size <= TX_8X8)
+ fbit = plane == 0? mi->mbmi.filterbit: mi->mbmi.uv_filterbit;
+#endif
}
if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0)
plane_b_size = b_width_log2(bsize) - pd->subsampling_x;
vp9_predict_intra_block(xd, tx_ib, plane_b_size, tx_size, b_mode,
+#if CONFIG_FILTERINTRA
+ fbit,
+#endif
dst, pd->dst.stride,
dst, pd->dst.stride);
if (bsize >= BLOCK_8X8) {
write_intra_mode(bc, mode, pc->fc.y_mode_prob[size_group_lookup[bsize]]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mode) && (mi->txfm_size <= TX_8X8)) {
+ vp9_write(bc, mi->filterbit,
+ pc->fc.filterintra_prob[mi->txfm_size][mode]);
+ }
+#endif
} else {
int idx, idy;
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
const MB_PREDICTION_MODE bm = m->bmi[idy * 2 + idx].as_mode;
write_intra_mode(bc, bm, pc->fc.y_mode_prob[0]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(bm)) {
+ vp9_write(bc, m->b_filter_info[idy * 2 + idx],
+ pc->fc.filterintra_prob[0][bm]);
+ }
+#endif
}
}
}
write_intra_mode(bc, mi->uv_mode, pc->fc.uv_mode_prob[mode]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mi->uv_mode) && (get_uv_tx_size(mi) <= TX_8X8)) {
+ vp9_write(bc, mi->uv_filterbit,
+ pc->fc.filterintra_prob[get_uv_tx_size(mi)][mi->uv_mode]);
+ }
+#endif
} else {
vp9_prob *mv_ref_p;
encode_ref_frame(cpi, bc);
const MB_PREDICTION_MODE L = xd->left_available ?
left_block_mode(m, 0) : DC_PRED;
write_intra_mode(bc, ym, vp9_kf_y_mode_prob[A][L]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(ym) && (m->mbmi.txfm_size <= TX_8X8))
+ vp9_write(bc, m->mbmi.filterbit,
+ c->fc.filterintra_prob[m->mbmi.txfm_size][ym]);
+#endif
} else {
int idx, idy;
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[m->mbmi.sb_type];
++intra_mode_stats[A][L][bm];
#endif
write_intra_mode(bc, bm, vp9_kf_y_mode_prob[A][L]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(bm))
+ vp9_write(bc, m->b_filter_info[i], c->fc.filterintra_prob[0][bm]);
+#endif
}
}
}
write_intra_mode(bc, m->mbmi.uv_mode, vp9_kf_uv_mode_prob[ym]);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(m->mbmi.uv_mode) &&
+ (get_uv_tx_size(&(m->mbmi)) <= TX_8X8))
+ vp9_write(bc, m->mbmi.uv_filterbit,
+ c->fc.filterintra_prob[get_uv_tx_size(&(m->mbmi))][m->mbmi.uv_mode]);
+#endif
}
static void write_modes_b(VP9_COMP *cpi, MODE_INFO *m, vp9_writer *bc,
xd->mode_info_context->mbmi.mode = DC_PRED;
xd->mode_info_context->mbmi.uv_mode = DC_PRED;
+#if CONFIG_FILTERINTRA
+ xd->mode_info_context->mbmi.filterbit = 0;
+ xd->mode_info_context->mbmi.uv_filterbit = 0;
+#endif
vp9_zero(cpi->y_mode_count)
vp9_zero(cpi->y_uv_mode_count)
vp9_zero(cpi->interintra_count);
vp9_zero(cpi->interintra_select_count);
#endif
+#if CONFIG_FILTERINTRA
+ vp9_zero(cm->counts.filterintra);
+#endif
// Note: this memset assumes above_context[0], [1] and [2]
// are allocated as part of the same buffer.
const MACROBLOCKD *xd = &x->e_mbd;
const MB_PREDICTION_MODE m = xd->mode_info_context->mbmi.mode;
const MB_PREDICTION_MODE uvm = xd->mode_info_context->mbmi.uv_mode;
+#if CONFIG_FILTERINTRA
+ const int uv_fbit = xd->mode_info_context->mbmi.uv_filterbit;
+ int fbit = xd->mode_info_context->mbmi.filterbit;
+#endif
++cpi->y_uv_mode_count[m][uvm];
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(uvm) &&
+ (get_uv_tx_size(&(xd->mode_info_context->mbmi)) <= TX_8X8))
+ ++cpi->common.counts.filterintra
+ [get_uv_tx_size(&(xd->mode_info_context->mbmi))]
+ [uvm][uv_fbit];
+#endif
if (xd->mode_info_context->mbmi.sb_type >= BLOCK_8X8) {
const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type;
const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize);
const int bsl = MIN(bwl, bhl);
++cpi->y_mode_count[MIN(bsl, 3)][m];
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(m) &&
+ (xd->mode_info_context->mbmi.txfm_size <= TX_8X8))
+ ++cpi->common.counts.filterintra[xd->mode_info_context->mbmi.txfm_size]
+ [m][fbit];
+#endif
} else {
int idx, idy;
int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[
for (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
int m = xd->mode_info_context->bmi[idy * 2 + idx].as_mode;
++cpi->y_mode_count[0][m];
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(m)) {
+ fbit = xd->mode_info_context->b_filter_info[idy * 2 + idx];
+ ++cpi->common.counts.filterintra[0][m][fbit];
+ }
+#endif
}
}
}
const int16_t *scan, *iscan;
TX_TYPE tx_type;
MB_PREDICTION_MODE mode;
+#if CONFIG_FILTERINTRA
+ int fbit = 0;
+#endif
const int bwl = b_width_log2(bsize) - pd->subsampling_x, bw = 1 << bwl;
const int twl = bwl - tx_size, twmask = (1 << twl) - 1;
int xoff, yoff;
scan = vp9_default_scan_32x32;
iscan = vp9_default_iscan_32x32;
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
+#if CONFIG_FILTERINTRA
+ fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
+#endif
block >>= 6;
xoff = 32 * (block & twmask);
yoff = 32 * (block >> twl);
src = p->src.buf + yoff * p->src.stride + xoff;
src_diff = p->src_diff + 4 * bw * yoff + xoff;
vp9_predict_intra_block(xd, block, bwl, TX_32X32, mode,
+#if CONFIG_FILTERINTRA
+ fbit,
+#endif
dst, pd->dst.stride, dst, pd->dst.stride);
vp9_subtract_block(32, 32, src_diff, bw * 4,
src, p->src.stride, dst, pd->dst.stride);
scan = get_scan_16x16(tx_type);
iscan = get_iscan_16x16(tx_type);
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
+#if CONFIG_FILTERINTRA
+ fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
+#endif
block >>= 4;
xoff = 16 * (block & twmask);
yoff = 16 * (block >> twl);
src = p->src.buf + yoff * p->src.stride + xoff;
src_diff = p->src_diff + 4 * bw * yoff + xoff;
vp9_predict_intra_block(xd, block, bwl, TX_16X16, mode,
+#if CONFIG_FILTERINTRA
+ fbit,
+#endif
dst, pd->dst.stride, dst, pd->dst.stride);
vp9_subtract_block(16, 16, src_diff, bw * 4,
src, p->src.stride, dst, pd->dst.stride);
scan = get_scan_8x8(tx_type);
iscan = get_iscan_8x8(tx_type);
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
+#if CONFIG_FILTERINTRA
+ fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
+#endif
block >>= 2;
xoff = 8 * (block & twmask);
yoff = 8 * (block >> twl);
src = p->src.buf + yoff * p->src.stride + xoff;
src_diff = p->src_diff + 4 * bw * yoff + xoff;
vp9_predict_intra_block(xd, block, bwl, TX_8X8, mode,
+#if CONFIG_FILTERINTRA
+ fbit,
+#endif
dst, pd->dst.stride, dst, pd->dst.stride);
vp9_subtract_block(8, 8, src_diff, bw * 4,
src, p->src.stride, dst, pd->dst.stride);
else
mode = plane == 0 ? mbmi->mode : mbmi->uv_mode;
+#if CONFIG_FILTERINTRA
+ if (mbmi->sb_type < BLOCK_8X8 && plane == 0)
+ fbit = xd->mode_info_context->b_filter_info[block];
+ else
+ fbit = plane == 0 ? mbmi->filterbit : mbmi->uv_filterbit;
+#endif
+
xoff = 4 * (block & twmask);
yoff = 4 * (block >> twl);
dst = pd->dst.buf + yoff * pd->dst.stride + xoff;
src = p->src.buf + yoff * p->src.stride + xoff;
src_diff = p->src_diff + 4 * bw * yoff + xoff;
vp9_predict_intra_block(xd, block, bwl, TX_4X4, mode,
+#if CONFIG_FILTERINTRA
+ fbit,
+#endif
dst, pd->dst.stride, dst, pd->dst.stride);
vp9_subtract_block(4, 4, src_diff, bw * 4,
src, p->src.stride, dst, pd->dst.stride);
unsigned int err;
xd->mode_info_context->mbmi.mode = mode;
+#if CONFIG_FILTERINTRA
+ xd->mode_info_context->mbmi.filterbit = 0;
+#endif
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);
err = vp9_sad16x16(x->plane[0].src.buf, x->plane[0].src.stride,
#if CONFIG_INTERINTRA
vp9_prob interintra_prob;
#endif
+#if CONFIG_FILTERINTRA
+ vp9_prob filterintra_prob[TX_SIZES][VP9_INTRA_MODES];
+#endif
} CODING_CONTEXT;
typedef struct {
#if CONFIG_INTERINTRA
cc->interintra_prob = cm->fc.interintra_prob;
#endif
+#if CONFIG_FILTERINTRA
+ vp9_copy(cc->filterintra_prob, cm->fc.filterintra_prob);
+#endif
}
void vp9_restore_coding_context(VP9_COMP *cpi) {
#if CONFIG_INTERINTRA
cm->fc.interintra_prob = cc->interintra_prob;
#endif
+#if CONFIG_FILTERINTRA
+ vp9_copy(cm->fc.filterintra_prob, cc->filterintra_prob);
+#endif
}
void vp9_setup_key_frame(VP9_COMP *cpi) {
static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
MB_PREDICTION_MODE *best_mode,
+#if CONFIG_FILTERINTRA
+ int *best_fbit,
+#endif
int *bmode_costs,
ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l,
int *bestrate, int *bestratey,
const int num_4x4_blocks_wide = num_4x4_blocks_wide_lookup[bsize];
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
int idx, idy, block;
+#if CONFIG_FILTERINTRA
+ int mode_ext, fbit;
+#endif
uint8_t best_dst[8 * 8];
assert(ib < 4);
vpx_memcpy(tl, l, sizeof(tl));
xd->mode_info_context->mbmi.txfm_size = TX_4X4;
+#if !CONFIG_FILTERINTRA
for (mode = DC_PRED; mode <= TM_PRED; ++mode) {
int64_t this_rd;
int ratey = 0;
}
rate = bmode_costs[mode];
+#else
+ for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * TM_PRED + 1; ++mode_ext) {
+ int64_t this_rd;
+ int ratey = 0;
+
+ 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
distortion = 0;
vpx_memcpy(tempa, ta, sizeof(ta));
block = ib + idy * 2 + idx;
xd->mode_info_context->bmi[block].as_mode = mode;
+#if CONFIG_FILTERINTRA
+ xd->mode_info_context->b_filter_info[block] = fbit;
+#endif
src_diff = raster_block_offset_int16(xd, BLOCK_8X8, 0, block,
p->src_diff);
coeff = BLOCK_OFFSET(x->plane[0].coeff, block, 16);
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);
*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 (idx = 0; idx < 2; idx += num_4x4_blocks_wide) {
const int mis = xd->mode_info_stride;
MB_PREDICTION_MODE UNINITIALIZED_IS_SAFE(best_mode);
+#if CONFIG_FILTERINTRA
+ int UNINITIALIZED_IS_SAFE(best_fbit);
+#endif
int UNINITIALIZED_IS_SAFE(r), UNINITIALIZED_IS_SAFE(ry);
int64_t UNINITIALIZED_IS_SAFE(d), this_rd;
i = idy * 2 + idx;
bmode_costs = mb->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);
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;
xd->mode_info_context->mbmi.mode = mic->bmi[3].as_mode;
+#if CONFIG_FILTERINTRA
+ xd->mode_info_context->mbmi.filterbit = mic->b_filter_info[3];
+#endif
return RDCOST(mb->rdmult, mb->rddiv, cost, total_distortion);
}
TX_SIZE UNINITIALIZED_IS_SAFE(best_tx);
int i;
int *bmode_costs = x->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 *const mic = xd->mode_info_context;
const int mis = xd->mode_info_stride;
+#else
+ for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * TM_PRED + 1; mode_ext++) {
+ int64_t local_tx_cache[TX_MODES];
+ MODE_INFO *const mic = xd->mode_info_context;
+ const int mis = xd->mode_info_stride;
+
+ fbit = mode_ext & 1;
+ mode = mode_ext >> 1;
+ if (fbit && !is_filter_allowed(mode))
+ continue;
+#endif
if (cpi->common.frame_type == KEY_FRAME) {
const MB_PREDICTION_MODE A = above_block_mode(mic, 0, mis);
bmode_costs = x->y_mode_costs[A][L];
}
x->e_mbd.mode_info_context->mbmi.mode = mode;
+#if CONFIG_FILTERINTRA
+ x->e_mbd.mode_info_context->mbmi.filterbit = fbit;
+#endif
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) &&
+ (xd->mode_info_context->mbmi.txfm_size <= TX_8X8))
+ this_rate += vp9_cost_bit(cpi->common.fc.filterintra_prob
+ [xd->mode_info_context->mbmi.txfm_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 = x->e_mbd.mode_info_context->mbmi.txfm_size;
*rate = this_rate;
}
x->e_mbd.mode_info_context->mbmi.mode = mode_selected;
+#if CONFIG_FILTERINTRA
+ x->e_mbd.mode_info_context->mbmi.filterbit = fbit_selected;
+#endif
x->e_mbd.mode_info_context->mbmi.txfm_size = best_tx;
return best_rd;
MB_PREDICTION_MODE last_mode = bsize <= BLOCK_8X8 ?
TM_PRED : cpi->sf.last_chroma_intra_mode;
+#if CONFIG_FILTERINTRA
+ int mode_ext, fbit = 0, fbit_selected = 0;
+ for (mode_ext = 2 * DC_PRED; mode_ext <= 2 * last_mode + 1; mode_ext++) {
+ mode = mode_ext >> 1;
+ fbit = mode_ext & 1;
+
+ if (fbit && !is_filter_allowed(mode))
+ continue;
+ if (fbit && is_filter_allowed(mode) &&
+ (get_uv_tx_size(&(x->e_mbd.mode_info_context->mbmi)) != TX_4X4))
+ continue;
+
+ x->e_mbd.mode_info_context->mbmi.uv_filterbit = fbit;
+#else
for (mode = DC_PRED; mode <= last_mode; mode++) {
+#endif
x->e_mbd.mode_info_context->mbmi.uv_mode = mode;
super_block_uvrd(&cpi->common, x, &this_rate_tokenonly,
&this_distortion, &s, NULL, bsize);
this_rate = this_rate_tokenonly +
x->intra_uv_mode_cost[cpi->common.frame_type][mode];
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mode) &&
+ (get_uv_tx_size(&(x->e_mbd.mode_info_context->mbmi)) <= TX_8X8))
+ this_rate += vp9_cost_bit(cpi->common.fc.filterintra_prob
+ [get_uv_tx_size(&(x->e_mbd.mode_info_context->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;
}
x->e_mbd.mode_info_context->mbmi.uv_mode = mode_selected;
+#if CONFIG_FILTERINTRA
+ x->e_mbd.mode_info_context->mbmi.uv_filterbit = fbit_selected;
+#endif
return best_rd;
}
int64_t dist_uv[TX_SIZES];
int skip_uv[TX_SIZES];
MB_PREDICTION_MODE mode_uv[TX_SIZES];
+#if CONFIG_FILTERINTRA
+ int fbit_uv[TX_SIZES];
+#endif
struct scale_factors scale_factor[4];
unsigned int ref_frame_mask = 0;
unsigned int mode_mask = 0;
&rate_uv_tokenonly[TX_4X4],
&dist_uv[TX_4X4], &skip_uv[TX_4X4],
&mode_uv[TX_4X4]);
+#if CONFIG_FILTERINTRA
+ fbit_uv[TX_4X4] = mbmi->uv_filterbit;
+#endif
}
rate2 += rate_uv_intra[TX_4X4];
rate_uv = rate_uv_tokenonly[TX_4X4];
distortion2 += dist_uv[TX_4X4];
distortion_uv = dist_uv[TX_4X4];
mbmi->uv_mode = mode_uv[TX_4X4];
+#if CONFIG_FILTERINTRA
+ mbmi->uv_filterbit = fbit_uv[TX_4X4];
+#endif
tx_cache[ONLY_4X4] = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
for (i = 0; i < TX_MODES; ++i)
tx_cache[i] = tx_cache[ONLY_4X4];
if (conditional_skipintra(mbmi->mode, best_intra_mode))
continue;
}
+#if CONFIG_FILTERINTRA
+ mbmi->filterbit = 0;
+#endif
super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable, NULL,
bsize, tx_cache, best_rd);
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mbmi->mode)) {
+ int temp_txfm_size, skippable_fil, rate_y_fil = 0;
+ int64_t distortion_y_fil = 0;
+ int64_t tx_cache_fil[TX_MODES];
+ int rate0, rate1;
+ temp_txfm_size = mbmi->txfm_size;
+ mbmi->filterbit = 1;
+ super_block_yrd(cpi, x, &rate_y_fil, &distortion_y_fil, &skippable_fil,
+ NULL, bsize, tx_cache_fil, best_rd);
+ rate0 = vp9_cost_bit(
+ cm->fc.filterintra_prob[temp_txfm_size][mbmi->mode], 0);
+ rate1 = vp9_cost_bit(
+ cm->fc.filterintra_prob[mbmi->txfm_size][mbmi->mode], 1);
+ if (RDCOST(x->rdmult, x->rddiv, rate_y + rate0, distortion_y) <=
+ RDCOST(x->rdmult, x->rddiv, rate_y_fil + rate1, distortion_y_fil)) {
+ mbmi->txfm_size = temp_txfm_size;
+ mbmi->filterbit = 0;
+ } else {
+ rate_y = rate_y_fil;
+ distortion_y = distortion_y_fil;
+ skippable = skippable_fil;
+ vpx_memcpy(tx_cache, tx_cache_fil, TX_MODES * sizeof(int64_t));
+ }
+ }
+#endif
+
if (rate_y == INT_MAX)
continue;
&rate_uv_tokenonly[uv_tx],
&dist_uv[uv_tx], &skip_uv[uv_tx],
&mode_uv[uv_tx]);
+#if CONFIG_FILTERINTRA
+ fbit_uv[uv_tx] = mbmi->uv_filterbit;
+#endif
}
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 + x->mbmode_cost[mbmi->mode] + rate_uv_intra[uv_tx];
+#if CONFIG_FILTERINTRA
+ if (is_filter_allowed(mbmi->mode) && mbmi->txfm_size <= TX_8X8)
+ rate2 += vp9_cost_bit(
+ cm->fc.filterintra_prob[mbmi->txfm_size][mbmi->mode], mbmi->filterbit);
+#endif
if (mbmi->mode != DC_PRED && mbmi->mode != TM_PRED)
rate2 += intra_cost_penalty;
distortion2 = distortion_y + distortion_uv;