Commit 85b66463 authored by Zoe Liu's avatar Zoe Liu

Add encoder/decoder pipeline to support single ref comp modes

Now the single ref comp mode should work with WEDGE and
COMPOUND_SEGMENT. For motion_var, the OBMC_CAUSAL mode uses the 2nd
predictor if the neighboring block is single ref comp mode predicted.

This patch removes the mode of SR_NEAREST_NEWMV and leaves four
single ref comp modes in total:

SR_NEAREST_NEARMV
SR_NEAR_NEWMV
SR_ZERO_NEWMV
SR_NEW_NEWMV

Change-Id: If6140455771f0f1a3b947766eccf82f23cc6b67a
parent c0f6bf25
......@@ -273,6 +273,11 @@ static const int mode_lf_lut[] = {
#endif // CONFIG_ALT_INTRA
1, 1, 0, 1, // INTER_MODES (ZEROMV == 0)
#if CONFIG_EXT_INTER
#if CONFIG_COMPOUND_SINGLEREF
// 1, 1, 1, 1, 1, // INTER_SINGLEREF_COMP_MODES
// NOTE(zoeliu): Remove SR_NEAREST_NEWMV
1, 1, 1, 1, // INTER_SINGLEREF_COMP_MODES
#endif // CONFIG_COMPOUND_SINGLEREF
1, 1, 1, 1, 1, 1, 0, 1 // INTER_COMPOUND_MODES (ZERO_ZEROMV == 0)
#endif // CONFIG_EXT_INTER
};
......
......@@ -119,14 +119,17 @@ typedef struct {
static INLINE int is_inter_singleref_mode(PREDICTION_MODE mode) {
return mode >= NEARESTMV && mode <= NEWMV;
}
static INLINE int is_inter_compound_mode(PREDICTION_MODE mode) {
return mode >= NEAREST_NEARESTMV && mode <= NEW_NEWMV;
}
#if CONFIG_COMPOUND_SINGLEREF
static INLINE int is_inter_singleref_comp_mode(PREDICTION_MODE mode) {
return mode >= SR_NEAREST_NEARMV && mode <= SR_NEW_NEWMV;
}
#endif // CONFIG_COMPOUND_SINGLEREF
static INLINE int is_inter_compound_mode(PREDICTION_MODE mode) {
return mode >= NEAREST_NEARESTMV && mode <= NEW_NEWMV;
static INLINE int is_inter_anyref_comp_mode(PREDICTION_MODE mode) {
return is_inter_compound_mode(mode) || is_inter_singleref_comp_mode(mode);
}
#endif // CONFIG_COMPOUND_SINGLEREF
static INLINE PREDICTION_MODE compound_ref0_mode(PREDICTION_MODE mode) {
static PREDICTION_MODE lut[] = {
......@@ -153,7 +156,7 @@ static INLINE PREDICTION_MODE compound_ref0_mode(PREDICTION_MODE mode) {
MB_MODE_COUNT, // NEWMV
#if CONFIG_COMPOUND_SINGLEREF
NEARESTMV, // SR_NEAREST_NEARMV
NEARESTMV, // SR_NEAREST_NEWMV
// NEARESTMV, // SR_NEAREST_NEWMV
NEARMV, // SR_NEAR_NEWMV
ZEROMV, // SR_ZERO_NEWMV
NEWMV, // SR_NEW_NEWMV
......@@ -168,7 +171,11 @@ static INLINE PREDICTION_MODE compound_ref0_mode(PREDICTION_MODE mode) {
NEWMV, // NEW_NEWMV
};
assert(NELEMENTS(lut) == MB_MODE_COUNT);
#if CONFIG_COMPOUND_SINGLEREF
assert(is_inter_anyref_comp_mode(mode));
#else // !CONFIG_COMPOUND_SINGLEREF
assert(is_inter_compound_mode(mode));
#endif // CONFIG_COMPOUND_SINGLEREF
return lut[mode];
}
......@@ -196,8 +203,8 @@ static INLINE PREDICTION_MODE compound_ref1_mode(PREDICTION_MODE mode) {
MB_MODE_COUNT, // ZEROMV
MB_MODE_COUNT, // NEWMV
#if CONFIG_COMPOUND_SINGLEREF
NEARMV, // SR_NEAREST_NEARMV
NEWMV, // SR_NEAREST_NEWMV
NEARMV, // SR_NEAREST_NEARMV
// NEWMV, // SR_NEAREST_NEWMV
NEWMV, // SR_NEAR_NEWMV
NEWMV, // SR_ZERO_NEWMV
NEWMV, // SR_NEW_NEWMV
......@@ -212,17 +219,28 @@ static INLINE PREDICTION_MODE compound_ref1_mode(PREDICTION_MODE mode) {
NEWMV, // NEW_NEWMV
};
assert(NELEMENTS(lut) == MB_MODE_COUNT);
#if CONFIG_COMPOUND_SINGLEREF
assert(is_inter_anyref_comp_mode(mode));
#else // !CONFIG_COMPOUND_SINGLEREF
assert(is_inter_compound_mode(mode));
#endif // CONFIG_COMPOUND_SINGLEREF
return lut[mode];
}
static INLINE int have_nearmv_in_inter_mode(PREDICTION_MODE mode) {
return (mode == NEARMV || mode == NEAR_NEARMV || mode == NEAR_NEWMV ||
#if CONFIG_COMPOUND_SINGLEREF
mode == SR_NEAREST_NEARMV || mode == SR_NEAR_NEWMV ||
#endif // CONFIG_COMPOUND_SINGLEREF
mode == NEW_NEARMV);
}
static INLINE int have_newmv_in_inter_mode(PREDICTION_MODE mode) {
return (mode == NEWMV || mode == NEW_NEWMV || mode == NEAREST_NEWMV ||
#if CONFIG_COMPOUND_SINGLEREF
/* mode == SR_NEAREST_NEWMV || */ mode == SR_NEAR_NEWMV ||
mode == SR_ZERO_NEWMV || mode == SR_NEW_NEWMV ||
#endif // CONFIG_COMPOUND_SINGLEREF
mode == NEW_NEARESTMV || mode == NEAR_NEWMV || mode == NEW_NEARMV);
}
......@@ -246,7 +264,8 @@ static INLINE int is_masked_compound_type(COMPOUND_TYPE type) {
(void)type;
return 0;
}
#else
#else // !CONFIG_EXT_INTER
static INLINE int have_nearmv_in_inter_mode(PREDICTION_MODE mode) {
return (mode == NEARMV);
......@@ -1256,7 +1275,11 @@ static INLINE int is_motion_variation_allowed_bsize(BLOCK_SIZE bsize) {
static INLINE int is_motion_variation_allowed_compound(
const MB_MODE_INFO *mbmi) {
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
if (!has_second_ref(mbmi) && !is_inter_singleref_comp_mode(mbmi->mode))
#else
if (!has_second_ref(mbmi))
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
return 1;
else
return 0;
......
......@@ -1027,6 +1027,7 @@ static const aom_prob default_inter_compound_mode_probs
#if CONFIG_COMPOUND_SINGLEREF
// TODO(zoeliu): Default values to be further adjusted based on the collected
// stats.
/*
static const aom_prob default_inter_singleref_comp_mode_probs
[INTER_MODE_CONTEXTS][INTER_SINGLEREF_COMP_MODES - 1] = {
{ 2, 173, 68, 180 }, // 0 = both zero mv
......@@ -1036,6 +1037,16 @@ static const aom_prob default_inter_singleref_comp_mode_probs
{ 8, 64, 64, 180 }, // 4 = two new mvs
{ 17, 81, 52, 180 }, // 5 = one intra neighbour
{ 25, 29, 50, 180 }, // 6 = two intra neighbours
};*/
static const aom_prob default_inter_singleref_comp_mode_probs
[INTER_MODE_CONTEXTS][INTER_SINGLEREF_COMP_MODES - 1] = {
{ 2, 173, 68 }, // 0 = both zero mv
{ 7, 145, 160 }, // 1 = 1 zero + 1 predicted
{ 7, 166, 126 }, // 2 = two predicted mvs
{ 7, 94, 132 }, // 3 = 1 pred/zero, 1 new
{ 8, 64, 64 }, // 4 = two new mvs
{ 17, 81, 52 }, // 5 = one intra neighbour
{ 25, 29, 50 }, // 6 = two intra neighbours
};
#endif // CONFIG_COMPOUND_SINGLEREF
......@@ -1280,6 +1291,8 @@ const aom_tree_index av1_inter_compound_mode_tree
};
#if CONFIG_COMPOUND_SINGLEREF
// TODO(zoeliu): To redesign the tree structure once the number of mode changes.
/*
const aom_tree_index av1_inter_singleref_comp_mode_tree
[TREE_SIZE(INTER_SINGLEREF_COMP_MODES)] = {
-INTER_SINGLEREF_COMP_OFFSET(SR_ZERO_NEWMV), 2,
......@@ -1287,6 +1300,14 @@ const aom_tree_index av1_inter_singleref_comp_mode_tree
6, -INTER_SINGLEREF_COMP_OFFSET(SR_NEW_NEWMV),
-INTER_SINGLEREF_COMP_OFFSET(SR_NEAREST_NEWMV),
-INTER_SINGLEREF_COMP_OFFSET(SR_NEAR_NEWMV)
};*/
const aom_tree_index av1_inter_singleref_comp_mode_tree
[TREE_SIZE(INTER_SINGLEREF_COMP_MODES)] = {
-INTER_SINGLEREF_COMP_OFFSET(SR_ZERO_NEWMV), 2,
-INTER_SINGLEREF_COMP_OFFSET(SR_NEAREST_NEARMV), 4,
-INTER_SINGLEREF_COMP_OFFSET(SR_NEAR_NEWMV),
-INTER_SINGLEREF_COMP_OFFSET(SR_NEW_NEWMV)
};
#endif // CONFIG_COMPOUND_SINGLEREF
......@@ -1368,7 +1389,7 @@ static const aom_prob default_single_ref_p[REF_CONTEXTS][SINGLE_REFS - 1] = {
// TODO(zoeliu): Default values to be further adjusted based on the collected
// stats.
static const aom_prob default_comp_inter_mode_p[COMP_INTER_MODE_CONTEXTS] = {
41, 119, 187, 225
40, 110, 160, 220
};
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
......
......@@ -346,7 +346,7 @@ typedef enum ATTRIBUTE_PACKED {
#if CONFIG_COMPOUND_SINGLEREF
// Single ref compound modes
SR_NEAREST_NEARMV,
SR_NEAREST_NEWMV,
// SR_NEAREST_NEWMV,
SR_NEAR_NEWMV,
SR_ZERO_NEWMV,
SR_NEW_NEWMV,
......
......@@ -66,7 +66,7 @@ static const int mode_2_counter[] = {
#if CONFIG_EXT_INTER
#if CONFIG_COMPOUND_SINGLEREF
0, // SR_NEAREST_NEARMV
1, // SR_NEAREST_NEWMV
// 1, // SR_NEAREST_NEWMV
1, // SR_NEAR_NEWMV
3, // SR_ZERO_NEWMV
1, // SR_NEW_NEWMV
......
......@@ -223,27 +223,34 @@ int av1_get_intra_inter_context(const MACROBLOCKD *xd) {
// The compound/single mode info data structure has one element border above and
// to the left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
// 0 - single/single
// 1 - single/--, --/single, --/--
// 2 - single/comp, comp/single
// 3 - comp/comp, comp/--, --/comp
int av1_get_inter_mode_context(const MACROBLOCKD *xd) {
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int has_above = xd->up_available;
const int has_left = xd->left_available;
if (has_above && has_left) { // both edges available (0/2/3)
const int above_inter_comp_mode = is_inter_compound_mode(above_mbmi->mode);
const int left_inter_comp_mode = is_inter_compound_mode(left_mbmi->mode);
return (above_inter_comp_mode && left_inter_comp_mode)
? 3
: (above_inter_comp_mode || left_inter_comp_mode) * 2;
} else if (has_above || has_left) { // one edge available (1/3)
if (has_above && has_left) { // both edges available
const int above_inter_comp_mode =
is_inter_anyref_comp_mode(above_mbmi->mode);
const int left_inter_comp_mode = is_inter_anyref_comp_mode(left_mbmi->mode);
if (above_inter_comp_mode && left_inter_comp_mode)
return 0;
else if (above_inter_comp_mode || left_inter_comp_mode)
return 1;
else if (!is_inter_block(above_mbmi) && !is_inter_block(left_mbmi))
return 2;
else
return 3;
} else if (has_above || has_left) { // one edge available
const MB_MODE_INFO *const edge_mbmi = has_above ? above_mbmi : left_mbmi;
return is_inter_compound_mode(edge_mbmi->mode) ? 3 : 1;
} else { // no edge available (1)
return 1;
if (is_inter_anyref_comp_mode(edge_mbmi->mode))
return 1;
else if (!is_inter_block(edge_mbmi))
return 2;
else
return 3;
} else { // no edge available
return 2;
}
}
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
......
......@@ -710,7 +710,8 @@ void av1_make_masked_inter_predictor(const uint8_t *pre, int pre_stride,
int p_col, int p_row, int ref,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
MACROBLOCKD *xd) {
MODE_INFO *mi = xd->mi[0];
const MODE_INFO *mi = xd->mi[0];
const INTERINTER_COMPOUND_DATA comp_data = {
#if CONFIG_WEDGE
mi->mbmi.wedge_index,
......@@ -903,6 +904,10 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
const MODE_INFO *mi = xd->mi[0];
#endif // CONFIG_MOTION_VAR
int is_compound = has_second_ref(&mi->mbmi);
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
int is_comp_mode_pred =
is_compound || is_inter_singleref_comp_mode(mi->mbmi.mode);
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
int ref;
#if CONFIG_INTRABC
const int is_intrabc = is_intrabc_block(&mi->mbmi);
......@@ -914,6 +919,9 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
WarpedMotionParams *const wm = &xd->global_motion[mi->mbmi.ref_frame[ref]];
is_global[ref] = is_global_mv_block(mi, block, wm->wmtype);
}
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
if (!is_compound && is_comp_mode_pred) is_global[1] = is_global[0];
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
#endif // CONFIG_GLOBAL_MOTION
#if CONFIG_CB4X4
......@@ -968,7 +976,8 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
for (idx = 0; idx < b8_w; idx += b4_w) {
MB_MODE_INFO *this_mbmi = &xd->mi[row * xd->mi_stride + col]->mbmi;
is_compound = has_second_ref(this_mbmi);
// TODO(zoeliu): If single ref comp modes are considered here, a
// mismatch was caused. Need a further investigation.
for (ref = 0; ref < 1 + is_compound; ++ref) {
struct buf_2d *const dst_buf = &pd->dst;
......@@ -1065,7 +1074,7 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
#if CONFIG_MOTION_VAR
mi_col_offset, mi_row_offset,
#endif
#endif // CONFIG_MOTION_VAR
xs, ys, xd);
}
++col;
......@@ -1091,7 +1100,11 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
av1_zero(tmp_dst);
#endif // CONFIG_CONVOLVE_ROUND
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
for (ref = 0; ref < 1 + is_comp_mode_pred; ++ref) {
#else
for (ref = 0; ref < 1 + is_compound; ++ref) {
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
#if CONFIG_INTRABC
const struct scale_factors *const sf =
is_intrabc ? &xd->sf_identity : &xd->block_refs[ref]->sf;
......@@ -1149,7 +1162,12 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
#else
ConvolveParams conv_params = get_conv_params(ref, ref, plane);
#endif // CONFIG_CONVOLVE_ROUND
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
for (ref = 0; ref < 1 + is_comp_mode_pred; ++ref) {
#else
for (ref = 0; ref < 1 + is_compound; ++ref) {
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
#if CONFIG_INTRABC
const struct scale_factors *const sf =
is_intrabc ? &xd->sf_identity : &xd->block_refs[ref]->sf;
......@@ -1197,7 +1215,7 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
#if CONFIG_MOTION_VAR
mi_col_offset, mi_row_offset,
#endif
#endif // CONFIG_MOTION_VAR
subpel_params[ref].xs, subpel_params[ref].ys, xd);
}
......@@ -1213,9 +1231,15 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
xd->bd);
else
#endif // CONFIG_HIGHBITDEPTH
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
av1_convolve_rounding(tmp_dst, MAX_SB_SIZE, dst, dst_buf->stride, w, h,
FILTER_BITS * 2 + is_compound -
FILTER_BITS * 2 + is_comp_mode_pred -
conv_params.round_0 - conv_params.round_1);
#else // !(CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF)
av1_convolve_rounding(tmp_dst, MAX_SB_SIZE, dst, dst_buf->stride, w, h,
FILTER_BITS * 2 + is_compound -
conv_params.round_0 - conv_params.round_1);
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
}
#endif // CONFIG_CONVOLVE_ROUND
}
......@@ -1962,6 +1986,14 @@ void modify_neighbor_predictor_for_obmc(MB_MODE_INFO *mbmi) {
is_masked_compound_type(mbmi->interinter_compound_type)) {
mbmi->interinter_compound_type = COMPOUND_AVERAGE;
mbmi->ref_frame[1] = NONE_FRAME;
#if CONFIG_COMPOUND_SINGLEREF
} else if (!has_second_ref(mbmi) &&
is_inter_singleref_comp_mode(mbmi->mode)) {
// mbmi->mode = compound_ref0_mode(mbmi->mode);
mbmi->mode = compound_ref1_mode(mbmi->mode);
assert(is_inter_singleref_mode(mbmi->mode));
mbmi->mv[0].as_int = mbmi->mv[1].as_int;
#endif // CONFIG_COMPOUND_SINGLEREF
}
#endif // CONFIG_EXT_INTER
if (has_second_ref(mbmi)) mbmi->ref_frame[1] = NONE_FRAME;
......@@ -2018,8 +2050,16 @@ void av1_build_prediction_by_above_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
tmp_height[j], tmp_stride[j], 0, i, NULL,
pd->subsampling_x, pd->subsampling_y);
}
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
for (ref = 0; ref < 1 + (is_inter_anyref_comp_mode(above_mbmi->mode));
++ref) {
const MV_REFERENCE_FRAME frame = has_second_ref(above_mbmi)
? above_mbmi->ref_frame[ref]
: above_mbmi->ref_frame[0];
#else // !(CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF)
for (ref = 0; ref < 1 + has_second_ref(above_mbmi); ++ref) {
const MV_REFERENCE_FRAME frame = above_mbmi->ref_frame[ref];
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME];
xd->block_refs[ref] = ref_buf;
......@@ -2107,8 +2147,16 @@ void av1_build_prediction_by_left_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
tmp_height[j], tmp_stride[j], i, 0, NULL,
pd->subsampling_x, pd->subsampling_y);
}
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
for (ref = 0; ref < 1 + (is_inter_anyref_comp_mode(left_mbmi->mode));
++ref) {
const MV_REFERENCE_FRAME frame = has_second_ref(left_mbmi)
? left_mbmi->ref_frame[ref]
: left_mbmi->ref_frame[0];
#else // !(CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF)
for (ref = 0; ref < 1 + has_second_ref(left_mbmi); ++ref) {
const MV_REFERENCE_FRAME frame = left_mbmi->ref_frame[ref];
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME];
xd->block_refs[ref] = ref_buf;
......@@ -2561,6 +2609,7 @@ void av1_build_ncobmc_inter_predictors_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
#endif // CONFIG_HIGHBITDEPTH
const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
// TODO(zoeliu): COMPOUND_SINGLEREF has not worked with NCOBMC yet.
av1_build_prediction_by_bottom_preds(cm, xd, mi_row, mi_col, dst_buf1,
dst_width1, dst_height1, dst_stride1);
av1_build_prediction_by_right_preds(cm, xd, mi_row, mi_col, dst_buf2,
......@@ -2911,7 +2960,13 @@ static void build_inter_predictors_single_buf(MACROBLOCKD *xd, int plane,
#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
WarpTypesAllowed warp_types;
#if CONFIG_GLOBAL_MOTION
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
WarpedMotionParams *const wm =
mi->mbmi.ref_frame[ref] > 0 ? &xd->global_motion[mi->mbmi.ref_frame[ref]]
: &xd->global_motion[mi->mbmi.ref_frame[0]];
#else // !(CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF)
WarpedMotionParams *const wm = &xd->global_motion[mi->mbmi.ref_frame[ref]];
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
warp_types.global_warp_allowed = is_global_mv_block(mi, block, wm->wmtype);
#endif // CONFIG_GLOBAL_MOTION
#if CONFIG_WARPED_MOTION
......@@ -2966,6 +3021,10 @@ void av1_build_inter_predictors_for_planes_single_buf(
const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
assert(bsize == BLOCK_8X8);
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
assert(has_second_ref(&xd->mi[0]->mbmi) ||
!is_inter_singleref_comp_mode(xd->mi[0]->mbmi.mode));
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
for (y = 0; y < num_4x4_h; ++y)
for (x = 0; x < num_4x4_w; ++x)
build_inter_predictors_single_buf(
......@@ -3003,7 +3062,12 @@ static void build_wedge_inter_predictor_from_buf(
mbmi->interinter_compound_type
};
#if CONFIG_COMPOUND_SINGLEREF
if ((is_compound || is_inter_singleref_comp_mode(mbmi->mode)) &&
is_masked_compound_type(mbmi->interinter_compound_type)) {
#else // !CONFIG_COMPOUND_SINGLEREF
if (is_compound && is_masked_compound_type(mbmi->interinter_compound_type)) {
#endif // CONFIG_COMPOUND_SINGLEREF
#if CONFIG_COMPOUND_SEGMENT
if (!plane && comp_data.interinter_compound_type == COMPOUND_SEG) {
#if CONFIG_HIGHBITDEPTH
......@@ -3034,7 +3098,7 @@ static void build_wedge_inter_predictor_from_buf(
dst, dst_buf->stride, ext_dst0, ext_dst_stride0, ext_dst1,
ext_dst_stride1, &comp_data, mbmi->sb_type, wedge_offset_x,
wedge_offset_y, h, w);
#else
#else // !CONFIG_SUPERTX
#if CONFIG_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
build_masked_compound_highbd(
......
......@@ -407,14 +407,23 @@ static INLINE void av1_make_inter_predictor(
#if CONFIG_WARPED_MOTION || CONFIG_GLOBAL_MOTION
WarpedMotionParams final_warp_params;
const int do_warp = allow_warp(mi, warp_types,
const int do_warp = allow_warp(
mi, warp_types,
#if CONFIG_GLOBAL_MOTION
&xd->global_motion[mi->mbmi.ref_frame[ref]],
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
// TODO(zoeliu): To further check the single
// ref comp mode to work together with
// global motion.
has_second_ref(&mi->mbmi) ? &xd->global_motion[mi->mbmi.ref_frame[ref]]
: &xd->global_motion[mi->mbmi.ref_frame[0]],
#else // !(CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF)
&xd->global_motion[mi->mbmi.ref_frame[ref]],
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
#endif // CONFIG_GLOBAL_MOTION
#if CONFIG_MOTION_VAR
mi_col_offset, mi_row_offset,
mi_col_offset, mi_row_offset,
#endif // CONFIG_MOTION_VAR
&final_warp_params);
&final_warp_params);
if (do_warp) {
const struct macroblockd_plane *const pd = &xd->plane[plane];
const struct buf_2d *const pre_buf = &pd->pre[ref];
......
......@@ -215,7 +215,23 @@ static void read_inter_compound_mode_probs(FRAME_CONTEXT *fc, aom_reader *r) {
}
}
}
#if CONFIG_COMPOUND_SINGLEREF
static void read_inter_singleref_comp_mode_probs(FRAME_CONTEXT *fc,
aom_reader *r) {
int i, j;
if (aom_read(r, GROUP_DIFF_UPDATE_PROB, ACCT_STR)) {
for (j = 0; j < INTER_MODE_CONTEXTS; ++j) {
for (i = 0; i < INTER_SINGLEREF_COMP_MODES - 1; ++i) {
av1_diff_update_prob(r, &fc->inter_singleref_comp_mode_probs[j][i],
ACCT_STR);
}
}
}
}
#endif // CONFIG_COMPOUND_SINGLEREF
#endif // CONFIG_EXT_INTER
#if !CONFIG_EC_ADAPT
#if !CONFIG_EXT_TX
static void read_ext_tx_probs(FRAME_CONTEXT *fc, aom_reader *r) {
......@@ -962,7 +978,13 @@ static void set_param_topblock(AV1_COMMON *const cm, MACROBLOCKD *const xd,
static void set_ref(AV1_COMMON *const cm, MACROBLOCKD *const xd, int idx,
int mi_row, int mi_col) {
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
RefBuffer *ref_buffer =
has_second_ref(mbmi) ? &cm->frame_refs[mbmi->ref_frame[idx] - LAST_FRAME]
: &cm->frame_refs[mbmi->ref_frame[0] - LAST_FRAME];
#else
RefBuffer *ref_buffer = &cm->frame_refs[mbmi->ref_frame[idx] - LAST_FRAME];
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
xd->block_refs[idx] = ref_buffer;
if (!av1_is_valid_scale(&ref_buffer->sf))
aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
......@@ -1000,9 +1022,12 @@ static void dec_predict_b_extend(
mbmi = set_offsets_extend(cm, xd, tile, bsize_pred, mi_row_pred, mi_col_pred,
mi_row_ori, mi_col_ori);
set_ref(cm, xd, 0, mi_row_pred, mi_col_pred);
if (has_second_ref(&xd->mi[0]->mbmi))
if (has_second_ref(&xd->mi[0]->mbmi)
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
|| is_inter_singleref_comp_mode(xd->mi[0]->mbmi.mode)
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
)
set_ref(cm, xd, 1, mi_row_pred, mi_col_pred);
if (!bextend) mbmi->tx_size = max_txsize_lookup[bsize_top];
xd->plane[plane].dst.stride = dst_stride;
......@@ -2014,8 +2039,14 @@ static void decode_token_and_recon_block(AV1Decoder *const pbi,
} else {
int ref;
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
for (ref = 0; ref < 1 + is_inter_anyref_comp_mode(mbmi->mode); ++ref) {
const MV_REFERENCE_FRAME frame =
has_second_ref(mbmi) ? mbmi->ref_frame[ref] : mbmi->ref_frame[0];
#else
for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
if (frame < LAST_FRAME) {
#if CONFIG_INTRABC
assert(is_intrabc_block(mbmi));
......@@ -4236,7 +4267,11 @@ static void read_compound_tools(AV1_COMMON *cm,
}
#endif // CONFIG_INTERINTRA
#if CONFIG_WEDGE || CONFIG_COMPOUND_SEGMENT
#if CONFIG_COMPOUND_SINGLEREF
if (!frame_is_intra_only(cm)) {
#else // !CONFIG_COMPOUND_SINGLEREF
if (!frame_is_intra_only(cm) && cm->reference_mode != SINGLE_REFERENCE) {
#endif // CONFIG_COMPOUND_SINGLEREF
cm->allow_masked_compound = aom_rb_read_bit(rb);
} else {
cm->allow_masked_compound = 0;
......@@ -4993,6 +5028,10 @@ static int read_compressed_header(AV1Decoder *pbi, const uint8_t *data,
#if CONFIG_EXT_INTER
read_inter_compound_mode_probs(fc, &r);
#if CONFIG_COMPOUND_SINGLEREF
read_inter_singleref_comp_mode_probs(fc, &r);
#endif // CONFIG_COMPOUND_SINGLEREF
#if CONFIG_INTERINTRA
if (cm->reference_mode != COMPOUND_REFERENCE &&
cm->allow_interintra_compound) {
......@@ -5015,7 +5054,11 @@ static int read_compressed_header(AV1Decoder *pbi, const uint8_t *data,
}
#endif // CONFIG_INTERINTRA
#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
#if CONFIG_COMPOUND_SINGLEREF
if (cm->allow_masked_compound) {
#else // !CONFIG_COMPOUND_SINGLEREF
if (cm->reference_mode != SINGLE_REFERENCE && cm->allow_masked_compound) {
#endif // CONFIG_COMPOUND_SINGLEREF
for (i = 0; i < BLOCK_SIZES; i++) {
for (j = 0; j < COMPOUND_TYPES - 1; j++) {
av1_diff_update_prob(&r, &fc->compound_type_prob[i][j], ACCT_STR);
......@@ -5043,6 +5086,11 @@ static int read_compressed_header(AV1Decoder *pbi, const uint8_t *data,
setup_compound_reference_mode(cm);
read_frame_reference_mode_probs(cm, &r);
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
for (i = 0; i < COMP_INTER_MODE_CONTEXTS; i++)
av1_diff_update_prob(&r, &fc->comp_inter_mode_prob[i], ACCT_STR);
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
#if !CONFIG_EC_ADAPT
for (j = 0; j < BLOCK_SIZE_GROUPS; j++) {
for (i = 0; i < INTRA_MODES - 1; ++i)
......@@ -5120,6 +5168,10 @@ static void debug_check_frame_counts(const AV1_COMMON *const cm) {
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
assert(!memcmp(cm->counts.intra_inter, zero_counts.intra_inter,
sizeof(cm->counts.intra_inter)));
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
assert(!memcmp(cm->counts.comp_inter_mode, zero_counts.comp_inter_mode,
sizeof(cm->counts.comp_inter_mode)));
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
assert(!memcmp(cm->counts.comp_inter, zero_counts.comp_inter,
sizeof(cm->counts.comp_inter)));
assert(!memcmp(cm->counts.single_ref, zero_counts.single_ref,
......
This diff is collapsed.
This diff is collapsed.
......@@ -539,6 +539,21 @@ static void set_ref_and_pred_mvs(MACROBLOCK *const x, int_mv *const mi_pred_mv,
mbmi->pred_mv[1] = this_mv;
mi_pred_mv[1] = this_mv;
}
#if CONFIG_COMPOUND_SINGLEREF
} else if (is_inter_singleref_comp_mode(mbmi->mode)) {
// Special case: SR_NEAR_NEWMV uses 1 + mbmi->ref_mv_idx
// (like NEARMV) instead
if (mbmi->mode == SR_NEAR_NEWMV) ref_mv_idx += 1;
if (compound_ref0_mode(mbmi->mode) == NEWMV ||
compound_ref1_mode(mbmi->mode) == NEWMV) {
int_mv this_mv = curr_ref_mv_stack[ref_mv_idx].this_mv;
clamp_mv_ref(&this_mv.as_mv, bw, bh, xd);
mbmi_ext->ref_mvs[mbmi->ref_frame[0]][0] = this_mv;
mbmi->pred_mv[0] = this_mv;
mi_pred_mv[0] = this_mv;
}
#endif // CONFIG_COMPOUND_SINGLEREF
} else {
#endif // CONFIG_EXT_INTER
if (mbmi->mode == NEWMV) {
......@@ -1619,7 +1634,14 @@ static void update_stats(const AV1_COMMON *const cm, ThreadData *td, int mi_row,
#endif // CONFIG_EXT_REFS
}
#if CONFIG_EXT_INTER && CONFIG_INTERINTRA
#if CONFIG_EXT_INTER
#if CONFIG_COMPOUND_SINGLEREF
if (!has_second_ref(mbmi))
counts->comp_inter_mode[av1_get_inter_mode_context(xd)]
[is_inter_singleref_comp_mode(mbmi->mode)]++;
#endif // CONFIG_COMPOUND_SINGLEREF
#if CONFIG_INTERINTRA
if (cm->reference_mode != COMPOUND_REFERENCE &&
#if CONFIG_SUPERTX
!supertx_enabled &&
......@@ -1635,7 +1657,8 @@ static void update_stats(const AV1_COMMON *const cm, ThreadData *td, int mi_row,
counts->interintra[bsize_group][0]++;
}
}
#endif // CONFIG_EXT_INTER && CONFIG_INTERINTRA
#endif // CONFIG_INTERINTRA
#endif // CONFIG_EXT_INTER
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
const MOTION_MODE motion_allowed = motion_mode_allowed(
......@@ -1663,8 +1686,13 @@ static void update_stats(const AV1_COMMON *const cm, ThreadData *td, int mi_row,
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
#if CONFIG_EXT_INTER
if (cm->reference_mode != SINGLE_REFERENCE &&
if (
#if CONFIG_COMPOUND_SINGLEREF
is_inter_anyref_comp_mode(mbmi->mode)
#else // !CONFIG_COMPOUND_SINGLEREF
cm->reference_mode != SINGLE_REFERENCE &&
is_inter_compound_mode(mbmi->mode)
#endif // CONFIG_COMPOUND_SINGLEREF
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
&& mbmi->motion_mode == SIMPLE_TRANSLATION
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
......@@ -1683,6 +1711,12 @@ static void update_stats(const AV1_COMMON *const cm, ThreadData *td, int mi_row,
if (has_second_ref(mbmi)) {
mode_ctx = mbmi_ext->compound_mode_context[mbmi->ref_frame[0]];
++counts->inter_compound_mode[mode_ctx][INTER_COMPOUND_OFFSET(mode)];
#if CONFIG_COMPOUND_SINGLEREF
} else if (is_inter_singleref_comp_mode(mode)) {
mode_ctx = mbmi_ext->compound_mode_context[mbmi->ref_frame[0]];
++counts->inter_singleref_comp_mode[mode_ctx]
[INTER_SINGLEREF_COMP_OFFSET(mode)];
#endif // CONFIG_COMPOUND_SINGLEREF
} else {
#endif // CONFIG_EXT_INTER
mode_ctx = av1_mode_context_analyzer(mbmi_ext->mode_context,
......@@ -1693,10 +1727,15 @@ static void update_stats(const AV1_COMMON *const cm, ThreadData *td, int mi_row,
#endif // CONFIG_EXT_INTER
#if CONFIG_EXT_INTER
#if CONFIG_COMPOUND_SINGLEREF
if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV ||
mbmi->mode == SR_NEW_NEWMV) {
#else // !CONFIG_COMPOUND_SINGLEREF
if (mbmi->mode == NEWMV || mbmi->mode == NEW_NEWMV) {
#else
#endif // CONFIG_COMPOUND_SINGLEREF
#else // !CONFIG_EXT_INTER
if (mbmi->mode == NEWMV) {
#endif
#endif // CONFIG_EXT_INTER
uint8_t ref_frame_type = av1_ref_frame_type(mbmi->ref_frame);
int idx;
......@@ -4950,7 +4989,11 @@ static void make_consistent_compound_tools(AV1_COMMON *cm) {
cm->allow_interintra_compound = 0;
#endif // CONFIG_INTERINTRA
#if CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
#if CONFIG_COMPOUND_SINGLEREF
if (frame_is_intra_only(cm))
#else // !CONFIG_COMPOUND_SINGLEREF
if (frame_is_intra_only(cm) || cm->reference_mode == SINGLE_REFERENCE)
#endif // CONFIG_COMPOUND_SINGLEREF
cm->allow_masked_compound = 0;
#endif // CONFIG_COMPOUND_SEGMENT || CONFIG_WEDGE
}
......@@ -5588,8 +5631,21 @@ static void encode_superblock(const AV1_COMP *const cpi, ThreadData *td,
av1_setup_pre_planes(xd, ref, cfg, mi_row, mi_col,
&xd->block_refs[ref]->sf);
}
av1_build_inter_predictors_sby(cm, xd, mi_row, mi_col, NULL, block_size);
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
// Single ref compound mode
if (!is_compound && is_inter_singleref_comp_mode(mbmi->mode)) {
xd->block_refs[1] = xd->block_refs[0];
YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, mbmi->ref_frame[0]);
#if CONFIG_INTRABC
assert(IMPLIES(!is_intrabc_block(mbmi), cfg));
#else
assert(cfg != NULL);
#endif // !CONFIG_INTRABC
av1_setup_pre_planes(xd, 1, cfg, mi_row, mi_col, &xd->block_refs[1]->sf);
}
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
av1_build_inter_predictors_sby(cm, xd, mi_row, mi_col, NULL, block_size);
av1_build_inter_predictors_sbuv(cm, xd, mi_row, mi_col, NULL, block_size);
#if CONFIG_MOTION_VAR
if (mbmi->motion_mode == OBMC_CAUSAL) {
......@@ -5888,6 +5944,16 @@ static void predict_superblock(const AV1_COMP *const cpi, ThreadData *td,
&xd->block_refs[ref]->sf);
}
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF