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[] = { ...@@ -273,6 +273,11 @@ static const int mode_lf_lut[] = {
#endif // CONFIG_ALT_INTRA #endif // CONFIG_ALT_INTRA
1, 1, 0, 1, // INTER_MODES (ZEROMV == 0) 1, 1, 0, 1, // INTER_MODES (ZEROMV == 0)
#if CONFIG_EXT_INTER #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) 1, 1, 1, 1, 1, 1, 0, 1 // INTER_COMPOUND_MODES (ZERO_ZEROMV == 0)
#endif // CONFIG_EXT_INTER #endif // CONFIG_EXT_INTER
}; };
......
...@@ -119,14 +119,17 @@ typedef struct { ...@@ -119,14 +119,17 @@ typedef struct {
static INLINE int is_inter_singleref_mode(PREDICTION_MODE mode) { static INLINE int is_inter_singleref_mode(PREDICTION_MODE mode) {
return mode >= NEARESTMV && mode <= NEWMV; 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 #if CONFIG_COMPOUND_SINGLEREF
static INLINE int is_inter_singleref_comp_mode(PREDICTION_MODE mode) { static INLINE int is_inter_singleref_comp_mode(PREDICTION_MODE mode) {
return mode >= SR_NEAREST_NEARMV && mode <= SR_NEW_NEWMV; return mode >= SR_NEAREST_NEARMV && mode <= SR_NEW_NEWMV;
} }
#endif // CONFIG_COMPOUND_SINGLEREF static INLINE int is_inter_anyref_comp_mode(PREDICTION_MODE mode) {
static INLINE int is_inter_compound_mode(PREDICTION_MODE mode) { return is_inter_compound_mode(mode) || is_inter_singleref_comp_mode(mode);
return mode >= NEAREST_NEARESTMV && mode <= NEW_NEWMV;
} }
#endif // CONFIG_COMPOUND_SINGLEREF
static INLINE PREDICTION_MODE compound_ref0_mode(PREDICTION_MODE mode) { static INLINE PREDICTION_MODE compound_ref0_mode(PREDICTION_MODE mode) {
static PREDICTION_MODE lut[] = { static PREDICTION_MODE lut[] = {
...@@ -153,7 +156,7 @@ static INLINE PREDICTION_MODE compound_ref0_mode(PREDICTION_MODE mode) { ...@@ -153,7 +156,7 @@ static INLINE PREDICTION_MODE compound_ref0_mode(PREDICTION_MODE mode) {
MB_MODE_COUNT, // NEWMV MB_MODE_COUNT, // NEWMV
#if CONFIG_COMPOUND_SINGLEREF #if CONFIG_COMPOUND_SINGLEREF
NEARESTMV, // SR_NEAREST_NEARMV NEARESTMV, // SR_NEAREST_NEARMV
NEARESTMV, // SR_NEAREST_NEWMV // NEARESTMV, // SR_NEAREST_NEWMV
NEARMV, // SR_NEAR_NEWMV NEARMV, // SR_NEAR_NEWMV
ZEROMV, // SR_ZERO_NEWMV ZEROMV, // SR_ZERO_NEWMV
NEWMV, // SR_NEW_NEWMV NEWMV, // SR_NEW_NEWMV
...@@ -168,7 +171,11 @@ static INLINE PREDICTION_MODE compound_ref0_mode(PREDICTION_MODE mode) { ...@@ -168,7 +171,11 @@ static INLINE PREDICTION_MODE compound_ref0_mode(PREDICTION_MODE mode) {
NEWMV, // NEW_NEWMV NEWMV, // NEW_NEWMV
}; };
assert(NELEMENTS(lut) == MB_MODE_COUNT); 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)); assert(is_inter_compound_mode(mode));
#endif // CONFIG_COMPOUND_SINGLEREF
return lut[mode]; return lut[mode];
} }
...@@ -196,8 +203,8 @@ static INLINE PREDICTION_MODE compound_ref1_mode(PREDICTION_MODE mode) { ...@@ -196,8 +203,8 @@ static INLINE PREDICTION_MODE compound_ref1_mode(PREDICTION_MODE mode) {
MB_MODE_COUNT, // ZEROMV MB_MODE_COUNT, // ZEROMV
MB_MODE_COUNT, // NEWMV MB_MODE_COUNT, // NEWMV
#if CONFIG_COMPOUND_SINGLEREF #if CONFIG_COMPOUND_SINGLEREF
NEARMV, // SR_NEAREST_NEARMV NEARMV, // SR_NEAREST_NEARMV
NEWMV, // SR_NEAREST_NEWMV // NEWMV, // SR_NEAREST_NEWMV
NEWMV, // SR_NEAR_NEWMV NEWMV, // SR_NEAR_NEWMV
NEWMV, // SR_ZERO_NEWMV NEWMV, // SR_ZERO_NEWMV
NEWMV, // SR_NEW_NEWMV NEWMV, // SR_NEW_NEWMV
...@@ -212,17 +219,28 @@ static INLINE PREDICTION_MODE compound_ref1_mode(PREDICTION_MODE mode) { ...@@ -212,17 +219,28 @@ static INLINE PREDICTION_MODE compound_ref1_mode(PREDICTION_MODE mode) {
NEWMV, // NEW_NEWMV NEWMV, // NEW_NEWMV
}; };
assert(NELEMENTS(lut) == MB_MODE_COUNT); 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)); assert(is_inter_compound_mode(mode));
#endif // CONFIG_COMPOUND_SINGLEREF
return lut[mode]; return lut[mode];
} }
static INLINE int have_nearmv_in_inter_mode(PREDICTION_MODE mode) { static INLINE int have_nearmv_in_inter_mode(PREDICTION_MODE mode) {
return (mode == NEARMV || mode == NEAR_NEARMV || mode == NEAR_NEWMV || 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); mode == NEW_NEARMV);
} }
static INLINE int have_newmv_in_inter_mode(PREDICTION_MODE mode) { static INLINE int have_newmv_in_inter_mode(PREDICTION_MODE mode) {
return (mode == NEWMV || mode == NEW_NEWMV || mode == NEAREST_NEWMV || 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); mode == NEW_NEARESTMV || mode == NEAR_NEWMV || mode == NEW_NEARMV);
} }
...@@ -246,7 +264,8 @@ static INLINE int is_masked_compound_type(COMPOUND_TYPE type) { ...@@ -246,7 +264,8 @@ static INLINE int is_masked_compound_type(COMPOUND_TYPE type) {
(void)type; (void)type;
return 0; return 0;
} }
#else
#else // !CONFIG_EXT_INTER
static INLINE int have_nearmv_in_inter_mode(PREDICTION_MODE mode) { static INLINE int have_nearmv_in_inter_mode(PREDICTION_MODE mode) {
return (mode == NEARMV); return (mode == NEARMV);
...@@ -1256,7 +1275,11 @@ static INLINE int is_motion_variation_allowed_bsize(BLOCK_SIZE bsize) { ...@@ -1256,7 +1275,11 @@ static INLINE int is_motion_variation_allowed_bsize(BLOCK_SIZE bsize) {
static INLINE int is_motion_variation_allowed_compound( static INLINE int is_motion_variation_allowed_compound(
const MB_MODE_INFO *mbmi) { 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)) if (!has_second_ref(mbmi))
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
return 1; return 1;
else else
return 0; return 0;
......
...@@ -1027,6 +1027,7 @@ static const aom_prob default_inter_compound_mode_probs ...@@ -1027,6 +1027,7 @@ static const aom_prob default_inter_compound_mode_probs
#if CONFIG_COMPOUND_SINGLEREF #if CONFIG_COMPOUND_SINGLEREF
// TODO(zoeliu): Default values to be further adjusted based on the collected // TODO(zoeliu): Default values to be further adjusted based on the collected
// stats. // stats.
/*
static const aom_prob default_inter_singleref_comp_mode_probs static const aom_prob default_inter_singleref_comp_mode_probs
[INTER_MODE_CONTEXTS][INTER_SINGLEREF_COMP_MODES - 1] = { [INTER_MODE_CONTEXTS][INTER_SINGLEREF_COMP_MODES - 1] = {
{ 2, 173, 68, 180 }, // 0 = both zero mv { 2, 173, 68, 180 }, // 0 = both zero mv
...@@ -1036,6 +1037,16 @@ static const aom_prob default_inter_singleref_comp_mode_probs ...@@ -1036,6 +1037,16 @@ static const aom_prob default_inter_singleref_comp_mode_probs
{ 8, 64, 64, 180 }, // 4 = two new mvs { 8, 64, 64, 180 }, // 4 = two new mvs
{ 17, 81, 52, 180 }, // 5 = one intra neighbour { 17, 81, 52, 180 }, // 5 = one intra neighbour
{ 25, 29, 50, 180 }, // 6 = two intra neighbours { 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 #endif // CONFIG_COMPOUND_SINGLEREF
...@@ -1280,6 +1291,8 @@ const aom_tree_index av1_inter_compound_mode_tree ...@@ -1280,6 +1291,8 @@ const aom_tree_index av1_inter_compound_mode_tree
}; };
#if CONFIG_COMPOUND_SINGLEREF #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 const aom_tree_index av1_inter_singleref_comp_mode_tree
[TREE_SIZE(INTER_SINGLEREF_COMP_MODES)] = { [TREE_SIZE(INTER_SINGLEREF_COMP_MODES)] = {
-INTER_SINGLEREF_COMP_OFFSET(SR_ZERO_NEWMV), 2, -INTER_SINGLEREF_COMP_OFFSET(SR_ZERO_NEWMV), 2,
...@@ -1287,6 +1300,14 @@ const aom_tree_index av1_inter_singleref_comp_mode_tree ...@@ -1287,6 +1300,14 @@ const aom_tree_index av1_inter_singleref_comp_mode_tree
6, -INTER_SINGLEREF_COMP_OFFSET(SR_NEW_NEWMV), 6, -INTER_SINGLEREF_COMP_OFFSET(SR_NEW_NEWMV),
-INTER_SINGLEREF_COMP_OFFSET(SR_NEAREST_NEWMV), -INTER_SINGLEREF_COMP_OFFSET(SR_NEAREST_NEWMV),
-INTER_SINGLEREF_COMP_OFFSET(SR_NEAR_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 #endif // CONFIG_COMPOUND_SINGLEREF
...@@ -1368,7 +1389,7 @@ static const aom_prob default_single_ref_p[REF_CONTEXTS][SINGLE_REFS - 1] = { ...@@ -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 // TODO(zoeliu): Default values to be further adjusted based on the collected
// stats. // stats.
static const aom_prob default_comp_inter_mode_p[COMP_INTER_MODE_CONTEXTS] = { 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 #endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
......
...@@ -346,7 +346,7 @@ typedef enum ATTRIBUTE_PACKED { ...@@ -346,7 +346,7 @@ typedef enum ATTRIBUTE_PACKED {
#if CONFIG_COMPOUND_SINGLEREF #if CONFIG_COMPOUND_SINGLEREF
// Single ref compound modes // Single ref compound modes
SR_NEAREST_NEARMV, SR_NEAREST_NEARMV,
SR_NEAREST_NEWMV, // SR_NEAREST_NEWMV,
SR_NEAR_NEWMV, SR_NEAR_NEWMV,
SR_ZERO_NEWMV, SR_ZERO_NEWMV,
SR_NEW_NEWMV, SR_NEW_NEWMV,
......
...@@ -66,7 +66,7 @@ static const int mode_2_counter[] = { ...@@ -66,7 +66,7 @@ static const int mode_2_counter[] = {
#if CONFIG_EXT_INTER #if CONFIG_EXT_INTER
#if CONFIG_COMPOUND_SINGLEREF #if CONFIG_COMPOUND_SINGLEREF
0, // SR_NEAREST_NEARMV 0, // SR_NEAREST_NEARMV
1, // SR_NEAREST_NEWMV // 1, // SR_NEAREST_NEWMV
1, // SR_NEAR_NEWMV 1, // SR_NEAR_NEWMV
3, // SR_ZERO_NEWMV 3, // SR_ZERO_NEWMV
1, // SR_NEW_NEWMV 1, // SR_NEW_NEWMV
......
...@@ -223,27 +223,34 @@ int av1_get_intra_inter_context(const MACROBLOCKD *xd) { ...@@ -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 // The compound/single mode info data structure has one element border above and
// to the left of the entries corresponding to real macroblocks. // to the left of the entries corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0. // 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) { int av1_get_inter_mode_context(const MACROBLOCKD *xd) {
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi; const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi; const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int has_above = xd->up_available; const int has_above = xd->up_available;
const int has_left = xd->left_available; const int has_left = xd->left_available;
if (has_above && has_left) { // both edges available (0/2/3) if (has_above && has_left) { // both edges available
const int above_inter_comp_mode = is_inter_compound_mode(above_mbmi->mode); const int above_inter_comp_mode =
const int left_inter_comp_mode = is_inter_compound_mode(left_mbmi->mode); is_inter_anyref_comp_mode(above_mbmi->mode);
return (above_inter_comp_mode && left_inter_comp_mode) const int left_inter_comp_mode = is_inter_anyref_comp_mode(left_mbmi->mode);
? 3 if (above_inter_comp_mode && left_inter_comp_mode)
: (above_inter_comp_mode || left_inter_comp_mode) * 2; return 0;
} else if (has_above || has_left) { // one edge available (1/3) 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; const MB_MODE_INFO *const edge_mbmi = has_above ? above_mbmi : left_mbmi;
return is_inter_compound_mode(edge_mbmi->mode) ? 3 : 1; if (is_inter_anyref_comp_mode(edge_mbmi->mode))
} else { // no edge available (1) return 1;
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 #endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
......
...@@ -710,7 +710,8 @@ void av1_make_masked_inter_predictor(const uint8_t *pre, int pre_stride, ...@@ -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, int p_col, int p_row, int ref,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION #endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
MACROBLOCKD *xd) { MACROBLOCKD *xd) {
MODE_INFO *mi = xd->mi[0]; const MODE_INFO *mi = xd->mi[0];
const INTERINTER_COMPOUND_DATA comp_data = { const INTERINTER_COMPOUND_DATA comp_data = {
#if CONFIG_WEDGE #if CONFIG_WEDGE
mi->mbmi.wedge_index, mi->mbmi.wedge_index,
...@@ -903,6 +904,10 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane, ...@@ -903,6 +904,10 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
const MODE_INFO *mi = xd->mi[0]; const MODE_INFO *mi = xd->mi[0];
#endif // CONFIG_MOTION_VAR #endif // CONFIG_MOTION_VAR
int is_compound = has_second_ref(&mi->mbmi); 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; int ref;
#if CONFIG_INTRABC #if CONFIG_INTRABC
const int is_intrabc = is_intrabc_block(&mi->mbmi); 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, ...@@ -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]]; WarpedMotionParams *const wm = &xd->global_motion[mi->mbmi.ref_frame[ref]];
is_global[ref] = is_global_mv_block(mi, block, wm->wmtype); 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 #endif // CONFIG_GLOBAL_MOTION
#if CONFIG_CB4X4 #if CONFIG_CB4X4
...@@ -968,7 +976,8 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane, ...@@ -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) { for (idx = 0; idx < b8_w; idx += b4_w) {
MB_MODE_INFO *this_mbmi = &xd->mi[row * xd->mi_stride + col]->mbmi; MB_MODE_INFO *this_mbmi = &xd->mi[row * xd->mi_stride + col]->mbmi;
is_compound = has_second_ref(this_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) { for (ref = 0; ref < 1 + is_compound; ++ref) {
struct buf_2d *const dst_buf = &pd->dst; struct buf_2d *const dst_buf = &pd->dst;
...@@ -1065,7 +1074,7 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane, ...@@ -1065,7 +1074,7 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION #endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
#if CONFIG_MOTION_VAR #if CONFIG_MOTION_VAR
mi_col_offset, mi_row_offset, mi_col_offset, mi_row_offset,
#endif #endif // CONFIG_MOTION_VAR
xs, ys, xd); xs, ys, xd);
} }
++col; ++col;
...@@ -1091,7 +1100,11 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane, ...@@ -1091,7 +1100,11 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
av1_zero(tmp_dst); av1_zero(tmp_dst);
#endif // CONFIG_CONVOLVE_ROUND #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) { for (ref = 0; ref < 1 + is_compound; ++ref) {
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
#if CONFIG_INTRABC #if CONFIG_INTRABC
const struct scale_factors *const sf = const struct scale_factors *const sf =
is_intrabc ? &xd->sf_identity : &xd->block_refs[ref]->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, ...@@ -1149,7 +1162,12 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
#else #else
ConvolveParams conv_params = get_conv_params(ref, ref, plane); ConvolveParams conv_params = get_conv_params(ref, ref, plane);
#endif // CONFIG_CONVOLVE_ROUND #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) { for (ref = 0; ref < 1 + is_compound; ++ref) {
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
#if CONFIG_INTRABC #if CONFIG_INTRABC
const struct scale_factors *const sf = const struct scale_factors *const sf =
is_intrabc ? &xd->sf_identity : &xd->block_refs[ref]->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, ...@@ -1197,7 +1215,7 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
#endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION #endif // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
#if CONFIG_MOTION_VAR #if CONFIG_MOTION_VAR
mi_col_offset, mi_row_offset, mi_col_offset, mi_row_offset,
#endif #endif // CONFIG_MOTION_VAR
subpel_params[ref].xs, subpel_params[ref].ys, xd); 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, ...@@ -1213,9 +1231,15 @@ void build_inter_predictors(const AV1_COMMON *cm, MACROBLOCKD *xd, int plane,
xd->bd); xd->bd);
else else
#endif // CONFIG_HIGHBITDEPTH #endif // CONFIG_HIGHBITDEPTH
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
av1_convolve_rounding(tmp_dst, MAX_SB_SIZE, dst, dst_buf->stride, w, h, 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); 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 #endif // CONFIG_CONVOLVE_ROUND
} }
...@@ -1962,6 +1986,14 @@ void modify_neighbor_predictor_for_obmc(MB_MODE_INFO *mbmi) { ...@@ -1962,6 +1986,14 @@ void modify_neighbor_predictor_for_obmc(MB_MODE_INFO *mbmi) {
is_masked_compound_type(mbmi->interinter_compound_type)) { is_masked_compound_type(mbmi->interinter_compound_type)) {
mbmi->interinter_compound_type = COMPOUND_AVERAGE; mbmi->interinter_compound_type = COMPOUND_AVERAGE;
mbmi->ref_frame[1] = NONE_FRAME; 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 #endif // CONFIG_EXT_INTER
if (has_second_ref(mbmi)) mbmi->ref_frame[1] = NONE_FRAME; 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, ...@@ -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, tmp_height[j], tmp_stride[j], 0, i, NULL,
pd->subsampling_x, pd->subsampling_y); 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) { for (ref = 0; ref < 1 + has_second_ref(above_mbmi); ++ref) {
const MV_REFERENCE_FRAME frame = above_mbmi->ref_frame[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]; const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME];
xd->block_refs[ref] = ref_buf; xd->block_refs[ref] = ref_buf;
...@@ -2107,8 +2147,16 @@ void av1_build_prediction_by_left_preds(const AV1_COMMON *cm, MACROBLOCKD *xd, ...@@ -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, tmp_height[j], tmp_stride[j], i, 0, NULL,
pd->subsampling_x, pd->subsampling_y); 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) { for (ref = 0; ref < 1 + has_second_ref(left_mbmi); ++ref) {
const MV_REFERENCE_FRAME frame = left_mbmi->ref_frame[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]; const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME];
xd->block_refs[ref] = ref_buf; xd->block_refs[ref] = ref_buf;
...@@ -2561,6 +2609,7 @@ void av1_build_ncobmc_inter_predictors_sb(const AV1_COMMON *cm, MACROBLOCKD *xd, ...@@ -2561,6 +2609,7 @@ void av1_build_ncobmc_inter_predictors_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
#endif // CONFIG_HIGHBITDEPTH #endif // CONFIG_HIGHBITDEPTH
const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type; 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, av1_build_prediction_by_bottom_preds(cm, xd, mi_row, mi_col, dst_buf1,
dst_width1, dst_height1, dst_stride1); dst_width1, dst_height1, dst_stride1);
av1_build_prediction_by_right_preds(cm, xd, mi_row, mi_col, dst_buf2, 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, ...@@ -2911,7 +2960,13 @@ static void build_inter_predictors_single_buf(MACROBLOCKD *xd, int plane,
#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION #if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
WarpTypesAllowed warp_types; WarpTypesAllowed warp_types;
#if CONFIG_GLOBAL_MOTION #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]]; 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); warp_types.global_warp_allowed = is_global_mv_block(mi, block, wm->wmtype);
#endif // CONFIG_GLOBAL_MOTION #endif // CONFIG_GLOBAL_MOTION
#if CONFIG_WARPED_MOTION #if CONFIG_WARPED_MOTION
...@@ -2966,6 +3021,10 @@ void av1_build_inter_predictors_for_planes_single_buf( ...@@ -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_w = num_4x4_blocks_wide_lookup[plane_bsize];
const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize]; const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
assert(bsize == BLOCK_8X8); 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 (y = 0; y < num_4x4_h; ++y)
for (x = 0; x < num_4x4_w; ++x) for (x = 0; x < num_4x4_w; ++x)
build_inter_predictors_single_buf( build_inter_predictors_single_buf(
...@@ -3003,7 +3062,12 @@ static void build_wedge_inter_predictor_from_buf( ...@@ -3003,7 +3062,12 @@ static void build_wedge_inter_predictor_from_buf(
mbmi->interinter_compound_type 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)) { if (is_compound && is_masked_compound_type(mbmi->interinter_compound_type)) {
#endif // CONFIG_COMPOUND_SINGLEREF
#if CONFIG_COMPOUND_SEGMENT #if CONFIG_COMPOUND_SEGMENT
if (!plane && comp_data.interinter_compound_type == COMPOUND_SEG) { if (!plane && comp_data.interinter_compound_type == COMPOUND_SEG) {
#if CONFIG_HIGHBITDEPTH #if CONFIG_HIGHBITDEPTH
...@@ -3034,7 +3098,7 @@ static void build_wedge_inter_predictor_from_buf( ...@@ -3034,7 +3098,7 @@ static void build_wedge_inter_predictor_from_buf(
dst, dst_buf->stride, ext_dst0, ext_dst_stride0, ext_dst1, dst, dst_buf->stride, ext_dst0, ext_dst_stride0, ext_dst1,
ext_dst_stride1, &comp_data, mbmi->sb_type, wedge_offset_x, ext_dst_stride1, &comp_data, mbmi->sb_type, wedge_offset_x,
wedge_offset_y, h, w); wedge_offset_y, h, w);
#else #else // !CONFIG_SUPERTX
#if CONFIG_HIGHBITDEPTH #if CONFIG_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
build_masked_compound_highbd( build_masked_compound_highbd(
......
...@@ -407,14 +407,23 @@ static INLINE void av1_make_inter_predictor( ...@@ -407,14 +407,23 @@ static INLINE void av1_make_inter_predictor(
#if CONFIG_WARPED_MOTION || CONFIG_GLOBAL_MOTION #if CONFIG_WARPED_MOTION || CONFIG_GLOBAL_MOTION
WarpedMotionParams final_warp_params; 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 #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 #endif // CONFIG_GLOBAL_MOTION
#if CONFIG_MOTION_VAR #if CONFIG_MOTION_VAR
mi_col_offset, mi_row_offset, mi_col_offset, mi_row_offset,
#endif // CONFIG_MOTION_VAR #endif // CONFIG_MOTION_VAR
&final_warp_params); &final_warp_params);
if (do_warp) { if (do_warp) {
const struct macroblockd_plane *const pd = &xd->plane[plane]; const struct macroblockd_plane *const pd = &xd->plane[plane];
const struct buf_2d *const pre_buf = &pd->pre[ref]; 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) { ...@@ -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 #endif // CONFIG_EXT_INTER
#if !CONFIG_EC_ADAPT #if !CONFIG_EC_ADAPT
#if !CONFIG_EXT_TX #if !CONFIG_EXT_TX
static void read_ext_tx_probs(FRAME_CONTEXT *fc, aom_reader *r) { 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, ...@@ -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, static void set_ref(AV1_COMMON *const cm, MACROBLOCKD *const xd, int idx,
int mi_row, int mi_col) { int mi_row, int mi_col) {
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi; 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]; 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; xd->block_refs[idx] = ref_buffer;
if (!av1_is_valid_scale(&ref_buffer->sf)) if (!av1_is_valid_scale(&ref_buffer->sf))
aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM,