Commit 7ded038a authored by Geza Lore's avatar Geza Lore Committed by Debargha Mukherjee

Port interintra experiment from nextgen.

The interintra experiment, which combines an inter prediction and an
inter prediction have been ported from the nextgen branch. The
experiment is merged into ext_inter, so there is no separate configure
option to enable it.

Change-Id: I0cc20cefd29e9b77ab7bbbb709abc11512320325
parent 3287f551
......@@ -170,6 +170,11 @@ typedef struct {
INTRA_FILTER intra_filter;
#endif // CONFIG_EXT_INTRA
#if CONFIG_EXT_INTER
PREDICTION_MODE interintra_mode;
PREDICTION_MODE interintra_uv_mode;
#endif // CONFIG_EXT_INTER
#if CONFIG_OBMC
int8_t obmc;
#endif // CONFIG_OBMC
......@@ -624,6 +629,30 @@ void vp10_set_contexts(const MACROBLOCKD *xd, struct macroblockd_plane *pd,
BLOCK_SIZE plane_bsize, TX_SIZE tx_size, int has_eob,
int aoff, int loff);
#if CONFIG_EXT_INTER
static INLINE int is_interintra_allowed_bsize(const BLOCK_SIZE bsize) {
return (bsize >= BLOCK_8X8) && (bsize < BLOCK_64X64);
}
static INLINE int is_interintra_allowed_mode(const PREDICTION_MODE mode) {
return (mode >= NEARESTMV) && (mode <= NEWMV);
}
static INLINE int is_interintra_allowed_ref(const MV_REFERENCE_FRAME rf[2]) {
return (rf[0] > INTRA_FRAME) && (rf[1] <= INTRA_FRAME);
}
static INLINE int is_interintra_allowed(const MB_MODE_INFO *mbmi) {
return is_interintra_allowed_bsize(mbmi->sb_type)
&& is_interintra_allowed_mode(mbmi->mode)
&& is_interintra_allowed_ref(mbmi->ref_frame);
}
static INLINE int is_interintra_pred(const MB_MODE_INFO *mbmi) {
return (mbmi->ref_frame[1] == INTRA_FRAME) && is_interintra_allowed(mbmi);
}
#endif // CONFIG_EXT_INTER
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -226,6 +226,10 @@ static const vpx_prob default_inter_compound_mode_probs
{17, 81, 52, 192, 192, 128, 180, 180}, // 5 = one intra neighbour
{25, 29, 50, 192, 192, 128, 180, 180}, // 6 = two intra neighbours
};
static const vpx_prob default_interintra_prob[BLOCK_SIZES] = {
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
};
#endif // CONFIG_EXT_INTER
#if CONFIG_OBMC
......@@ -1326,6 +1330,7 @@ static void init_mode_probs(FRAME_CONTEXT *fc) {
#endif // CONFIG_OBMC
#if CONFIG_EXT_INTER
vp10_copy(fc->inter_compound_mode_probs, default_inter_compound_mode_probs);
vp10_copy(fc->interintra_prob, default_interintra_prob);
#endif // CONFIG_EXT_INTER
#if CONFIG_SUPERTX
vp10_copy(fc->supertx_prob, default_supertx_prob);
......@@ -1434,6 +1439,12 @@ void vp10_adapt_inter_frame_probs(VP10_COMMON *cm) {
pre_fc->inter_compound_mode_probs[i],
counts->inter_compound_mode[i],
fc->inter_compound_mode_probs[i]);
for (i = 0; i < BLOCK_SIZES; ++i) {
if (is_interintra_allowed_bsize(i))
fc->interintra_prob[i] = mode_mv_merge_probs(pre_fc->interintra_prob[i],
counts->interintra[i]);
}
#endif // CONFIG_EXT_INTER
for (i = 0; i < BLOCK_SIZE_GROUPS; i++)
......
......@@ -80,6 +80,7 @@ typedef struct frame_contexts {
#if CONFIG_EXT_INTER
vpx_prob inter_compound_mode_probs[INTER_MODE_CONTEXTS]
[INTER_COMPOUND_MODES - 1];
vpx_prob interintra_prob[BLOCK_SIZES];
#endif // CONFIG_EXT_INTER
#if CONFIG_OBMC
vpx_prob obmc_prob[BLOCK_SIZES];
......@@ -141,6 +142,7 @@ typedef struct FRAME_COUNTS {
unsigned int inter_mode[INTER_MODE_CONTEXTS][INTER_MODES];
#if CONFIG_EXT_INTER
unsigned int inter_compound_mode[INTER_MODE_CONTEXTS][INTER_COMPOUND_MODES];
unsigned int interintra[BLOCK_SIZES][2];
#endif // CONFIG_EXT_INTER
#if CONFIG_OBMC
unsigned int obmc[BLOCK_SIZES][2];
......
......@@ -22,6 +22,10 @@
#include "vp10/common/onyxc_int.h"
#endif // CONFIG_OBMC
// TODO(geza.lore) Update this when the extended coding unit size experiment
// have been ported.
#define CU_SIZE 64
#if CONFIG_VP9_HIGHBITDEPTH
void vp10_highbd_build_inter_predictor(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
......@@ -232,23 +236,65 @@ static void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize,
void vp10_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_EXT_INTER
if (is_interintra_pred(&xd->mi[0]->mbmi))
vp10_build_interintra_predictors_sby(xd,
xd->plane[0].dst.buf,
xd->plane[0].dst.stride,
bsize);
#endif // CONFIG_EXT_INTER
}
void vp10_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col,
BLOCK_SIZE bsize, int plane) {
BLOCK_SIZE bsize, int plane) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, plane, plane);
#if CONFIG_EXT_INTER
if (is_interintra_pred(&xd->mi[0]->mbmi)) {
if (plane == 0) {
vp10_build_interintra_predictors_sby(xd,
xd->plane[0].dst.buf,
xd->plane[0].dst.stride,
bsize);
} else {
vp10_build_interintra_predictors_sbc(xd,
xd->plane[plane].dst.buf,
xd->plane[plane].dst.stride,
plane, bsize);
}
}
#endif // CONFIG_EXT_INTER
}
void vp10_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_EXT_INTER
if (is_interintra_pred(&xd->mi[0]->mbmi))
vp10_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 // CONFIG_EXT_INTER
}
void vp10_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_EXT_INTER
if (is_interintra_pred(&xd->mi[0]->mbmi))
vp10_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 // CONFIG_EXT_INTER
}
void vp10_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE],
......@@ -509,6 +555,17 @@ void vp10_build_inter_predictors_sb_sub8x8(MACROBLOCKD *xd,
0, 0, bw, bh,
mi_x, mi_y);
}
#if CONFIG_EXT_INTER
if (is_interintra_pred(&xd->mi[0]->mbmi))
vp10_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 // CONFIG_EXT_INTER
}
#endif // CONFIG_SUPERTX
......@@ -755,3 +812,387 @@ void vp10_build_obmc_inter_prediction(VP10_COMMON *cm,
} // each mi in the left column
}
#endif // CONFIG_OBMC
#if CONFIG_EXT_INTER
static void combine_interintra(PREDICTION_MODE mode,
BLOCK_SIZE plane_bsize,
uint8_t *comppred,
int compstride,
uint8_t *interpred,
int interstride,
uint8_t *intrapred,
int intrastride) {
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,
};
const int bw = 4 << b_width_log2_lookup[plane_bsize];
const int bh = 4 << b_height_log2_lookup[plane_bsize];
int size = VPXMAX(bw, bh);
int size_scale = (size >= 64 ? 1 :
size == 32 ? 2 :
size == 16 ? 4 :
size == 8 ? 8 : 16);
int i, j;
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;
}
}
#if CONFIG_VP9_HIGHBITDEPTH
static void combine_interintra_highbd(PREDICTION_MODE mode,
BLOCK_SIZE plane_bsize,
uint8_t *comppred8,
int compstride,
uint8_t *interpred8,
int interstride,
uint8_t *intrapred8,
int intrastride, int bd) {
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,
};
const int bw = 4 << b_width_log2_lookup[plane_bsize];
const int bh = 4 << b_height_log2_lookup[plane_bsize];
int size = VPXMAX(bw, bh);
int size_scale = (size >= 64 ? 1 :
size == 32 ? 2 :
size == 16 ? 4 :
size == 8 ? 8 : 16);
int i, j;
uint16_t *comppred = CONVERT_TO_SHORTPTR(comppred8);
uint16_t *interpred = CONVERT_TO_SHORTPTR(interpred8);
uint16_t *intrapred = CONVERT_TO_SHORTPTR(intrapred8);
(void) bd;
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;
}
}
#endif // CONFIG_VP9_HIGHBITDEPTH
// 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 *ref, int ref_stride,
uint8_t *dst, int dst_stride,
PREDICTION_MODE mode,
BLOCK_SIZE bsize,
int plane) {
BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, &xd->plane[plane]);
const int bwl = b_width_log2_lookup[plane_bsize];
const int bhl = b_height_log2_lookup[plane_bsize];
TX_SIZE max_tx_size = max_txsize_lookup[plane_bsize];
if (bwl == bhl) {
vp10_predict_intra_block(xd, bwl, bhl, max_tx_size, mode,
ref, ref_stride, dst, dst_stride,
0, 0, plane);
} else if (bwl < bhl) {
uint8_t *src_2 = ref + (4 << bwl)*ref_stride;
uint8_t *dst_2 = dst + (4 << bwl)*dst_stride;
vp10_predict_intra_block(xd, bwl, bhl, max_tx_size, mode,
ref, ref_stride, dst, dst_stride,
0, 0, plane);
vp10_predict_intra_block(xd, bwl, bhl, max_tx_size, mode,
src_2, ref_stride, dst_2, dst_stride,
0, 1 << bwl, plane);
} else {
uint8_t *src_2 = ref + (4 << bhl);
uint8_t *dst_2 = dst + (4 << bhl);
vp10_predict_intra_block(xd, bwl, bhl, max_tx_size, mode,
ref, ref_stride, dst, dst_stride,
0, 0, plane);
vp10_predict_intra_block(xd, bwl, bhl, max_tx_size, mode,
src_2, ref_stride, dst_2, dst_stride,
1 << bhl, 0, plane);
}
}
void vp10_build_interintra_predictors_sby(MACROBLOCKD *xd,
uint8_t *ypred,
int ystride,
BLOCK_SIZE bsize) {
const int bw = 4 << b_width_log2_lookup[bsize];
#if CONFIG_VP9_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
DECLARE_ALIGNED(16, uint16_t,
intrapredictor[CU_SIZE * CU_SIZE]);
build_intra_predictors_for_interintra(
xd, xd->plane[0].dst.buf, xd->plane[0].dst.stride,
CONVERT_TO_BYTEPTR(intrapredictor), bw,
xd->mi[0]->mbmi.interintra_mode, bsize, 0);
combine_interintra_highbd(xd->mi[0]->mbmi.interintra_mode,
bsize,
xd->plane[0].dst.buf, xd->plane[0].dst.stride,
ypred, ystride,
CONVERT_TO_BYTEPTR(intrapredictor), bw, xd->bd);
return;
}
#endif // CONFIG_VP9_HIGHBITDEPTH
{
uint8_t intrapredictor[CU_SIZE * CU_SIZE];
build_intra_predictors_for_interintra(
xd, xd->plane[0].dst.buf, xd->plane[0].dst.stride,
intrapredictor, bw,
xd->mi[0]->mbmi.interintra_mode, bsize, 0);
combine_interintra(xd->mi[0]->mbmi.interintra_mode,
bsize,
xd->plane[0].dst.buf, xd->plane[0].dst.stride,
ypred, ystride, intrapredictor, bw);
}
}
void vp10_build_interintra_predictors_sbc(MACROBLOCKD *xd,
uint8_t *upred,
int ustride,
int plane,
BLOCK_SIZE bsize) {
const BLOCK_SIZE uvbsize = get_plane_block_size(bsize, &xd->plane[plane]);
const int bw = 4 << b_width_log2_lookup[uvbsize];
#if CONFIG_VP9_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
DECLARE_ALIGNED(16, uint16_t,
uintrapredictor[CU_SIZE * CU_SIZE]);
build_intra_predictors_for_interintra(
xd, xd->plane[plane].dst.buf, xd->plane[plane].dst.stride,
CONVERT_TO_BYTEPTR(uintrapredictor), bw,
xd->mi[0]->mbmi.interintra_uv_mode, bsize, plane);
combine_interintra_highbd(xd->mi[0]->mbmi.interintra_uv_mode,
uvbsize,
xd->plane[plane].dst.buf,
xd->plane[plane].dst.stride,
upred, ustride,
CONVERT_TO_BYTEPTR(uintrapredictor), bw, xd->bd);
return;
}
#endif // CONFIG_VP9_HIGHBITDEPTH
{
uint8_t uintrapredictor[CU_SIZE * CU_SIZE];
build_intra_predictors_for_interintra(
xd, xd->plane[plane].dst.buf, xd->plane[plane].dst.stride,
uintrapredictor, bw,
xd->mi[0]->mbmi.interintra_uv_mode, bsize, 1);
combine_interintra(xd->mi[0]->mbmi.interintra_uv_mode,
uvbsize,
xd->plane[plane].dst.buf,
xd->plane[plane].dst.stride,
upred, ustride, uintrapredictor, bw);
}
}
void vp10_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
uint8_t *upred,
uint8_t *vpred,
int ustride, int vstride,
BLOCK_SIZE bsize) {
vp10_build_interintra_predictors_sbc(xd, upred, ustride, 1, bsize);
vp10_build_interintra_predictors_sbc(xd, vpred, vstride, 2, bsize);
}
void vp10_build_interintra_predictors(MACROBLOCKD *xd,
uint8_t *ypred,
uint8_t *upred,
uint8_t *vpred,
int ystride, int ustride, int vstride,
BLOCK_SIZE bsize) {
vp10_build_interintra_predictors_sby(xd, ypred, ystride, bsize);
vp10_build_interintra_predictors_sbuv(xd, upred, vpred,
ustride, vstride, bsize);
}
#endif // CONFIG_EXT_INTER
......@@ -369,6 +369,31 @@ void vp10_build_obmc_inter_prediction(VP10_COMMON *cm,
int tmp_stride2[MAX_MB_PLANE]);
#endif // CONFIG_OBMC
#if CONFIG_EXT_INTER
void vp10_build_interintra_predictors(MACROBLOCKD *xd,
uint8_t *ypred,
uint8_t *upred,
uint8_t *vpred,
int ystride,
int ustride,
int vstride,
BLOCK_SIZE bsize);
void vp10_build_interintra_predictors_sby(MACROBLOCKD *xd,
uint8_t *ypred,
int ystride,
BLOCK_SIZE bsize);
void vp10_build_interintra_predictors_sbc(MACROBLOCKD *xd,
uint8_t *upred,
int ustride,
int plane,
BLOCK_SIZE bsize);
void vp10_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
uint8_t *upred,
uint8_t *vpred,
int ustride, int vstride,
BLOCK_SIZE bsize);
#endif // CONFIG_EXT_INTER
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -403,6 +403,10 @@ void vp10_accumulate_frame_counts(VP10_COMMON *cm, FRAME_COUNTS *counts,
for (j = 0; j < INTER_COMPOUND_MODES; j++)
cm->counts.inter_compound_mode[i][j] +=
counts->inter_compound_mode[i][j];
for (i = 0; i < BLOCK_SIZES; i++)
for (j = 0; j < 2; j++)
cm->counts.interintra[i][j] += counts->interintra[i][j];