Commit c082bbcb authored by Zoe Liu's avatar Zoe Liu

Add new coding tool of ext-comp-refs

The tool of ext-comp-refs adds the uni-directional compound reference
prediction. In details, 3 pairs of uni-direcitonal compound references
are added for the comp ref prediction:
(LAST_FRAME, LAST2_FRAME),
(LAST_FRAME, GOLDEN_FRAME), and
(BWDREF_FRAME, ALTREF_FRAME).

This new tool of ext-comp-refs will eventually overwrite
one-side-compound and have the two coding tools to merge to one.

It achieves -0.35 ~ -0.55% coding gains in BDRate, compared against
AV1 baseline with the default experiments on, but without
one-sided-compound. It achieves -0.2% ~ -0.3% coding gains when
one-sided-compound is on. It achieves larger gains on higher
resolution.

Change-Id: Icbdb16e97b96aaebaf2213f5f72d5331e2e358eb
parent 0c634c70
......@@ -502,6 +502,33 @@ static INLINE int has_second_ref(const MB_MODE_INFO *mbmi) {
return mbmi->ref_frame[1] > INTRA_FRAME;
}
#if CONFIG_EXT_COMP_REFS
static INLINE int has_uni_comp_refs(const MB_MODE_INFO *mbmi) {
return has_second_ref(mbmi) && (!((mbmi->ref_frame[0] >= BWDREF_FRAME) ^
(mbmi->ref_frame[1] >= BWDREF_FRAME)));
}
static INLINE MV_REFERENCE_FRAME comp_ref0(int ref_idx) {
static const MV_REFERENCE_FRAME lut[] = {
LAST_FRAME, // LAST_LAST2_FRAMES,
LAST_FRAME, // LAST_GOLDEN_FRAMES,
BWDREF_FRAME, // BWDREF_ALTREF_FRAMES,
};
assert(NELEMENTS(lut) == UNIDIR_COMP_REFS);
return lut[ref_idx];
}
static INLINE MV_REFERENCE_FRAME comp_ref1(int ref_idx) {
static const MV_REFERENCE_FRAME lut[] = {
LAST2_FRAME, // LAST_LAST2_FRAMES,
GOLDEN_FRAME, // LAST_GOLDEN_FRAMES,
ALTREF_FRAME, // BWDREF_ALTREF_FRAMES,
};
assert(NELEMENTS(lut) == UNIDIR_COMP_REFS);
return lut[ref_idx];
}
#endif // CONFIG_EXT_COMP_REFS
PREDICTION_MODE av1_left_block_mode(const MODE_INFO *cur_mi,
const MODE_INFO *left_mi, int b);
......
......@@ -1392,6 +1392,17 @@ static const aom_cdf_prob default_comp_inter_cdf[COMP_INTER_CONTEXTS][CDF_SIZE(
{ AOM_ICDF(41 * 128), AOM_ICDF(32768), 0 } };
#endif
#if CONFIG_EXT_COMP_REFS
static const aom_prob default_comp_ref_type_p[COMP_REF_TYPE_CONTEXTS] = {
30, 75, 120, 170, 230
};
static const aom_prob
default_uni_comp_ref_p[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1] = {
{ 30, 20 }, { 75, 70 }, { 130, 130 }, { 165, 165 }, { 215, 220 }
};
#endif // CONFIG_EXT_COMP_REFS
#if CONFIG_EXT_REFS
static const aom_prob default_comp_ref_p[REF_CONTEXTS][FWD_REFS - 1] = {
// TODO(zoeliu): To adjust the initial prob values.
......@@ -4577,6 +4588,10 @@ static void init_mode_probs(FRAME_CONTEXT *fc) {
#if CONFIG_NEW_MULTISYMBOL
av1_copy(fc->comp_inter_cdf, default_comp_inter_cdf);
#endif
#if CONFIG_EXT_COMP_REFS
av1_copy(fc->comp_ref_type_prob, default_comp_ref_type_p);
av1_copy(fc->uni_comp_ref_prob, default_uni_comp_ref_p);
#endif // CONFIG_EXT_COMP_REFS
av1_copy(fc->comp_ref_prob, default_comp_ref_p);
#if CONFIG_LV_MAP
av1_copy(fc->txb_skip, default_txb_skip);
......@@ -4804,6 +4819,17 @@ void av1_adapt_inter_frame_probs(AV1_COMMON *cm) {
fc->comp_inter_prob[i] = av1_mode_mv_merge_probs(pre_fc->comp_inter_prob[i],
counts->comp_inter[i]);
#if CONFIG_EXT_COMP_REFS
for (i = 0; i < COMP_REF_TYPE_CONTEXTS; i++)
fc->comp_ref_type_prob[i] = av1_mode_mv_merge_probs(
pre_fc->comp_ref_type_prob[i], counts->comp_ref_type[i]);
for (i = 0; i < UNI_COMP_REF_CONTEXTS; i++)
for (j = 0; j < (UNIDIR_COMP_REFS - 1); j++)
fc->uni_comp_ref_prob[i][j] = av1_mode_mv_merge_probs(
pre_fc->uni_comp_ref_prob[i][j], counts->uni_comp_ref[i][j]);
#endif // CONFIG_EXT_COMP_REFS
#if CONFIG_EXT_REFS
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < (FWD_REFS - 1); j++)
......
......@@ -218,6 +218,10 @@ typedef struct frame_contexts {
aom_cdf_prob comp_inter_cdf[COMP_INTER_CONTEXTS][CDF_SIZE(2)];
aom_cdf_prob single_ref_cdf[REF_CONTEXTS][SINGLE_REFS - 1][CDF_SIZE(2)];
#endif
#if CONFIG_EXT_COMP_REFS
aom_prob comp_ref_type_prob[COMP_REF_TYPE_CONTEXTS];
aom_prob uni_comp_ref_prob[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1];
#endif // CONFIG_EXT_COMP_REFS
aom_prob single_ref_prob[REF_CONTEXTS][SINGLE_REFS - 1];
#if CONFIG_EXT_REFS
aom_prob comp_ref_prob[REF_CONTEXTS][FWD_REFS - 1];
......@@ -390,6 +394,10 @@ typedef struct FRAME_COUNTS {
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
unsigned int intra_inter[INTRA_INTER_CONTEXTS][2];
unsigned int comp_inter[COMP_INTER_CONTEXTS][2];
#if CONFIG_EXT_COMP_REFS
unsigned int comp_ref_type[COMP_REF_TYPE_CONTEXTS][2];
unsigned int uni_comp_ref[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1][2];
#endif // CONFIG_EXT_COMP_REFS
unsigned int single_ref[REF_CONTEXTS][SINGLE_REFS - 1][2];
#if CONFIG_EXT_REFS
unsigned int comp_ref[REF_CONTEXTS][FWD_REFS - 1][2];
......
......@@ -286,6 +286,18 @@ typedef enum {
#endif // CONFIG_EXT_REFS
} AOM_REFFRAME;
#if CONFIG_EXT_COMP_REFS
#define USE_UNI_COMP_REFS 1
typedef enum {
UNIDIR_COMP_REFERENCE = 0,
BIDIR_COMP_REFERENCE = 1,
COMP_REFERENCE_TYPES = 2,
} COMP_REFERENCE_TYPE;
#else // !CONFIG_EXT_COMP_REFS
#define USE_UNI_COMP_REFS 0
#endif // CONFIG_EXT_COMP_REFS
typedef enum { PLANE_TYPE_Y = 0, PLANE_TYPE_UV = 1, PLANE_TYPES } PLANE_TYPE;
#if CONFIG_CFL
......@@ -487,6 +499,12 @@ typedef enum {
#define INTRA_INTER_CONTEXTS 4
#define COMP_INTER_CONTEXTS 5
#define REF_CONTEXTS 5
#if CONFIG_EXT_COMP_REFS
#define COMP_REF_TYPE_CONTEXTS 5
#define UNI_COMP_REF_CONTEXTS 5
#endif // CONFIG_EXT_COMP_REFS
#if CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
#define COMP_INTER_MODE_CONTEXTS 4
#endif // CONFIG_EXT_INTER && CONFIG_COMPOUND_SINGLEREF
......@@ -526,7 +544,17 @@ typedef uint8_t TXFM_CONTEXT;
#endif // CONFIG_EXT_REFS
#define SINGLE_REFS (FWD_REFS + BWD_REFS)
#if CONFIG_EXT_COMP_REFS
typedef enum {
LAST_LAST2_FRAMES, // { LAST_FRAME, LAST2_FRAME }
LAST_GOLDEN_FRAMES, // { LAST_FRAME, GOLDEN_FRAME }
BWDREF_ALTREF_FRAMES, // { BWDREF_FRAME, ALTREF_FRAME }
UNIDIR_COMP_REFS
} UNIDIR_COMP_REF;
#define COMP_REFS (FWD_REFS * BWD_REFS + UNIDIR_COMP_REFS)
#else // !CONFIG_EXT_COMP_REFS
#define COMP_REFS (FWD_REFS * BWD_REFS)
#endif // CONFIG_EXT_COMP_REFS
#define MODE_CTX_REF_FRAMES (TOTAL_REFS_PER_FRAME + COMP_REFS)
......
......@@ -238,10 +238,41 @@ static INLINE int av1_nmv_ctx(const uint8_t ref_mv_count,
return 0;
}
#if CONFIG_EXT_COMP_REFS
static INLINE int8_t av1_uni_comp_ref_idx(const MV_REFERENCE_FRAME *const rf) {
// Single ref pred
if (rf[1] <= INTRA_FRAME) return -1;
// Bi-directional comp ref pred
if ((rf[0] < BWDREF_FRAME) && (rf[1] >= BWDREF_FRAME)) return -1;
for (int8_t ref_idx = 0; ref_idx < UNIDIR_COMP_REFS; ++ref_idx) {
if (rf[0] == comp_ref0(ref_idx) && rf[1] == comp_ref1(ref_idx))
return ref_idx;
}
return -1;
}
#endif // CONFIG_EXT_COMP_REFS
static INLINE int8_t av1_ref_frame_type(const MV_REFERENCE_FRAME *const rf) {
if (rf[1] > INTRA_FRAME) {
return TOTAL_REFS_PER_FRAME + FWD_RF_OFFSET(rf[0]) +
BWD_RF_OFFSET(rf[1]) * FWD_REFS;
#if CONFIG_EXT_COMP_REFS
int8_t uni_comp_ref_idx = av1_uni_comp_ref_idx(rf);
#if !USE_UNI_COMP_REFS
// NOTE: uni-directional comp refs disabled
assert(uni_comp_ref_idx < 0);
#endif // !USE_UNI_COMP_REFS
if (uni_comp_ref_idx >= 0) {
assert((TOTAL_REFS_PER_FRAME + FWD_REFS * BWD_REFS + uni_comp_ref_idx) <
MODE_CTX_REF_FRAMES);
return TOTAL_REFS_PER_FRAME + FWD_REFS * BWD_REFS + uni_comp_ref_idx;
} else {
#endif // CONFIG_EXT_COMP_REFS
return TOTAL_REFS_PER_FRAME + FWD_RF_OFFSET(rf[0]) +
BWD_RF_OFFSET(rf[1]) * FWD_REFS;
#if CONFIG_EXT_COMP_REFS
}
#endif // CONFIG_EXT_COMP_REFS
}
return rf[0];
......@@ -255,9 +286,15 @@ static MV_REFERENCE_FRAME ref_frame_map[COMP_REFS][2] = {
{ LAST_FRAME, ALTREF_FRAME }, { LAST2_FRAME, ALTREF_FRAME },
{ LAST3_FRAME, ALTREF_FRAME }, { GOLDEN_FRAME, ALTREF_FRAME }
#else
// TODO(zoeliu): Temporarily disable uni-directional comp refs
#if CONFIG_EXT_COMP_REFS
, { LAST_FRAME, LAST2_FRAME }, { LAST_FRAME, GOLDEN_FRAME },
{ BWDREF_FRAME, ALTREF_FRAME }
#endif // CONFIG_EXT_COMP_REFS
#else // !CONFIG_EXT_REFS
{ LAST_FRAME, ALTREF_FRAME }, { GOLDEN_FRAME, ALTREF_FRAME }
#endif
#endif // CONFIG_EXT_REFS
};
// clang-format on
......
......@@ -310,6 +310,280 @@ int av1_get_reference_mode_context(const AV1_COMMON *cm,
return ctx;
}
#if CONFIG_EXT_COMP_REFS
#define CHECK_BWDREF_OR_ALTREF(ref_frame) \
((ref_frame) == BWDREF_FRAME || (ref_frame) == ALTREF_FRAME)
int av1_get_comp_reference_type_context(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int above_in_image = xd->up_available;
const int left_in_image = xd->left_available;
(void)cm;
if (above_in_image && left_in_image) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
if (above_intra && left_intra) { // intra/intra
pred_context = 2;
} else if (above_intra || left_intra) { // intra/inter
const MB_MODE_INFO *inter_mbmi = above_intra ? left_mbmi : above_mbmi;
if (!has_second_ref(inter_mbmi)) // single pred
pred_context = 2;
else // comp pred
pred_context = 1 + 2 * has_uni_comp_refs(inter_mbmi);
} else { // inter/inter
const int a_sg = !has_second_ref(above_mbmi);
const int l_sg = !has_second_ref(left_mbmi);
const MV_REFERENCE_FRAME frfa = above_mbmi->ref_frame[0];
const MV_REFERENCE_FRAME frfl = left_mbmi->ref_frame[0];
if (a_sg && l_sg) { // single/single
pred_context = 1 +
2 * (!(CHECK_BWDREF_OR_ALTREF(frfa) ^
CHECK_BWDREF_OR_ALTREF(frfl)));
} else if (l_sg || a_sg) { // single/comp
const int uni_rfc =
a_sg ? has_uni_comp_refs(left_mbmi) : has_uni_comp_refs(above_mbmi);
if (!uni_rfc) // comp bidir
pred_context = 1;
else // comp unidir
pred_context = 3 + (!(CHECK_BWDREF_OR_ALTREF(frfa) ^
CHECK_BWDREF_OR_ALTREF(frfl)));
} else { // comp/comp
const int a_uni_rfc = has_uni_comp_refs(above_mbmi);
const int l_uni_rfc = has_uni_comp_refs(left_mbmi);
if (!a_uni_rfc && !l_uni_rfc) // bidir/bidir
pred_context = 0;
else if (!a_uni_rfc || !l_uni_rfc) // unidir/bidir
pred_context = 2;
else // unidir/unidir
pred_context =
3 + (!((frfa == BWDREF_FRAME) ^ (frfl == BWDREF_FRAME)));
}
}
} else if (above_in_image || left_in_image) { // one edge available
const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
if (!is_inter_block(edge_mbmi)) { // intra
pred_context = 2;
} else { // inter
if (!has_second_ref(edge_mbmi)) // single pred
pred_context = 2;
else // comp pred
pred_context = 4 * has_uni_comp_refs(edge_mbmi);
}
} else { // no edges available
pred_context = 2;
}
assert(pred_context >= 0 && pred_context < COMP_REF_TYPE_CONTEXTS);
return pred_context;
}
// Returns a context number for the given MB prediction signal
// Signal the uni-directional compound reference frame pair as
// either (BWDREF, ALTREF), or (LAST, LAST2)/(LAST, GOLDEN),
// conditioning on the pair is known as uni-directional.
int av1_get_pred_context_uni_comp_ref_p(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int above_in_image = xd->up_available;
const int left_in_image = xd->left_available;
(void)cm;
if (above_in_image && left_in_image) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
if (above_intra && left_intra) { // intra/intra
pred_context = 2;
} else if (above_intra || left_intra) { // intra/inter
const MB_MODE_INFO *inter_mbmi = above_intra ? left_mbmi : above_mbmi;
if (!has_second_ref(inter_mbmi)) { // single pred
pred_context =
1 + 2 * (!CHECK_BWDREF_OR_ALTREF(inter_mbmi->ref_frame[0]));
} else { // comp pred
if (has_uni_comp_refs(inter_mbmi)) // comp unidir
pred_context = 4 * (inter_mbmi->ref_frame[0] != BWDREF_FRAME);
else // comp_bidir
pred_context = 2;
}
} else { // inter/inter
const int a_sg = !has_second_ref(above_mbmi);
const int l_sg = !has_second_ref(left_mbmi);
const MV_REFERENCE_FRAME frfa = above_mbmi->ref_frame[0];
const MV_REFERENCE_FRAME frfl = left_mbmi->ref_frame[0];
if (CHECK_BWDREF_OR_ALTREF(frfa) && CHECK_BWDREF_OR_ALTREF(frfl)) {
pred_context = 0;
} else if (a_sg && l_sg) { // single/single
pred_context = 2 + (!CHECK_BWDREF_OR_ALTREF(frfa) &&
!CHECK_BWDREF_OR_ALTREF(frfl));
} else if (l_sg || a_sg) { // single/comp
const MV_REFERENCE_FRAME frfc = a_sg ? frfl : frfa;
const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
const int uni_rfc =
a_sg ? has_uni_comp_refs(left_mbmi) : has_uni_comp_refs(above_mbmi);
if (uni_rfc && (frfc == BWDREF_FRAME))
pred_context = 1;
else if (uni_rfc && (frfc == LAST_FRAME))
pred_context = 3 + (!CHECK_BWDREF_OR_ALTREF(rfs));
else if (CHECK_BWDREF_OR_ALTREF(rfs))
pred_context = 2;
else
pred_context = 3;
} else { // comp/comp
const int a_uni_rfc = has_uni_comp_refs(above_mbmi);
const int l_uni_rfc = has_uni_comp_refs(left_mbmi);
if (a_uni_rfc && l_uni_rfc)
pred_context = 2 + 2 * (frfa != BWDREF_FRAME && frfl != BWDREF_FRAME);
else if (a_uni_rfc || l_uni_rfc)
pred_context = 1 + 2 * (frfa != BWDREF_FRAME && frfl != BWDREF_FRAME);
else
pred_context = 2;
}
}
} else if (above_in_image || left_in_image) { // one edge available
const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
if (!is_inter_block(edge_mbmi)) { // intra
pred_context = 2;
} else { // inter
if (!has_second_ref(edge_mbmi)) { // single pred
pred_context =
1 + 2 * (!CHECK_BWDREF_OR_ALTREF(edge_mbmi->ref_frame[0]));
} else { // comp pred
if (has_uni_comp_refs(edge_mbmi)) // comp unidir
pred_context = 4 * (edge_mbmi->ref_frame[0] != BWDREF_FRAME);
else // comp bidir
pred_context = 2;
}
}
} else { // no edges available
pred_context = 2;
}
assert(pred_context >= 0 && pred_context < UNI_COMP_REF_CONTEXTS);
return pred_context;
}
// Returns a context number for the given MB prediction signal
// Signal the uni-directional compound reference frame pair as
// either (BWDREF, ALTREF), or (LAST, LAST2)/(LAST, GOLDEN),
// conditioning on the pair is known as uni-directional.
#define CHECK_LAST2_OR_GOLDEN(ref_frame) \
((ref_frame) == LAST2_FRAME || (ref_frame) == GOLDEN_FRAME)
int av1_get_pred_context_uni_comp_ref_p1(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int above_in_image = xd->up_available;
const int left_in_image = xd->left_available;
(void)cm;
if (above_in_image && left_in_image) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
if (above_intra && left_intra) { // intra/intra
pred_context = 2;
} else if (above_intra || left_intra) { // intra/inter
const MB_MODE_INFO *inter_mbmi = above_intra ? left_mbmi : above_mbmi;
if (!has_second_ref(inter_mbmi)) { // single pred
if (CHECK_LAST2_OR_GOLDEN(inter_mbmi->ref_frame[0]))
pred_context = 1 + 2 * (inter_mbmi->ref_frame[0] == LAST2_FRAME);
else
pred_context = 2;
} else { // comp pred
if (CHECK_LAST2_OR_GOLDEN(inter_mbmi->ref_frame[1]))
pred_context = 4 * (inter_mbmi->ref_frame[1] == LAST2_FRAME);
else
pred_context = 2;
}
} else { // inter/inter
const int a_sg = !has_second_ref(above_mbmi);
const int l_sg = !has_second_ref(left_mbmi);
const MV_REFERENCE_FRAME frfa = above_mbmi->ref_frame[0];
const MV_REFERENCE_FRAME frfl = left_mbmi->ref_frame[0];
const MV_REFERENCE_FRAME brfa = above_mbmi->ref_frame[1];
const MV_REFERENCE_FRAME brfl = left_mbmi->ref_frame[1];
if (a_sg && l_sg) { // single/single
if (CHECK_LAST2_OR_GOLDEN(frfa) && (frfa == frfl || frfl == LAST_FRAME))
pred_context = 1 + 2 * (frfa == LAST2_FRAME);
else if (frfa == LAST_FRAME && CHECK_LAST2_OR_GOLDEN(frfl))
pred_context = 1 + 2 * (frfl == LAST2_FRAME);
else
pred_context = 2;
} else if (l_sg || a_sg) { // single/comp
const MV_REFERENCE_FRAME brfc = a_sg ? brfl : brfa;
if (CHECK_LAST2_OR_GOLDEN(brfc))
pred_context = 4 * (brfc == LAST2_FRAME);
if (CHECK_LAST2_OR_GOLDEN(frfa) && (frfa == frfl || frfl == LAST_FRAME))
pred_context = 1 + 2 * (frfa == LAST2_FRAME);
else if (frfa == LAST_FRAME && CHECK_LAST2_OR_GOLDEN(frfl))
pred_context = 1 + 2 * (frfl == LAST2_FRAME);
else
pred_context = 2;
} else { // comp/comp
if (CHECK_LAST2_OR_GOLDEN(brfa) &&
(brfa == brfl || !CHECK_LAST2_OR_GOLDEN(brfl)))
pred_context = 4 * (brfa == LAST2_FRAME);
else if (!CHECK_LAST2_OR_GOLDEN(brfa) && CHECK_LAST2_OR_GOLDEN(brfl))
pred_context = 4 * (brfl == LAST2_FRAME);
else if (CHECK_LAST2_OR_GOLDEN(frfa) &&
(frfa == frfl || frfl == LAST_FRAME))
pred_context = 1 + 2 * (frfa == LAST2_FRAME);
else if (frfa == LAST_FRAME && CHECK_LAST2_OR_GOLDEN(frfl))
pred_context = 1 + 2 * (frfl == LAST2_FRAME);
else
pred_context = 2;
}
}
} else if (above_in_image || left_in_image) { // one edge available
const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
if (!is_inter_block(edge_mbmi)) { // intra
pred_context = 2;
} else { // inter
if (!has_second_ref(edge_mbmi)) { // single pred
if (CHECK_LAST2_OR_GOLDEN(edge_mbmi->ref_frame[0]))
pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] == LAST2_FRAME);
else
pred_context = 2;
} else { // comp pred
if (CHECK_LAST2_OR_GOLDEN(edge_mbmi->ref_frame[1]))
pred_context = 4 * (edge_mbmi->ref_frame[1] == LAST2_FRAME);
else
pred_context = 2;
}
}
} else { // no edges available
pred_context = 2;
}
assert(pred_context >= 0 && pred_context < UNI_COMP_REF_CONTEXTS);
return pred_context;
}
#endif // CONFIG_EXT_COMP_REFS
#if CONFIG_EXT_REFS
// TODO(zoeliu): Future work will be conducted to optimize the context design
......@@ -327,13 +601,8 @@ int av1_get_reference_mode_context(const AV1_COMMON *cm,
//
// NOTE(zoeliu): The probability of ref_frame[0] is either
// GOLDEN_FRAME or LAST3_FRAME.
#if CONFIG_ONE_SIDED_COMPOUND
int av1_get_pred_context_comp_ref_p(UNUSED const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
#else
int av1_get_pred_context_comp_ref_p(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
#endif
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
......@@ -344,14 +613,16 @@ int av1_get_pred_context_comp_ref_p(const AV1_COMMON *cm,
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
#if CONFIG_ONE_SIDED_COMPOUND // No change to bitstream
#if CONFIG_ONE_SIDED_COMPOUND || CONFIG_EXT_COMP_REFS // No change to bitstream
// Code seems to assume that signbias of cm->comp_bwd_ref[0] is always 1
const int bwd_ref_sign_idx = 1;
#else
const int bwd_ref_sign_idx = cm->ref_frame_sign_bias[cm->comp_bwd_ref[0]];
#endif
#endif // CONFIG_ONE_SIDED_COMPOUND || CONFIG_EXT_COMP_REFS
const int fwd_ref_sign_idx = !bwd_ref_sign_idx;
(void)cm;
if (above_in_image && left_in_image) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
......@@ -403,8 +674,11 @@ int av1_get_pred_context_comp_ref_p(const AV1_COMMON *cm,
if ((CHECK_LAST_OR_LAST2(frfa) && CHECK_LAST_OR_LAST2(frfl))) {
pred_context = 4;
} else {
// NOTE(zoeliu): Following assert may be removed once confirmed.
// NOTE(zoeliu): Following assert may be removed once confirmed.
#if !USE_UNI_COMP_REFS
// TODO(zoeliu): To further study the UNIDIR scenario
assert(CHECK_GOLDEN_OR_LAST3(frfa) || CHECK_GOLDEN_OR_LAST3(frfl));
#endif // !USE_UNI_COMP_REFS
pred_context = 2;
}
}
......@@ -437,13 +711,8 @@ int av1_get_pred_context_comp_ref_p(const AV1_COMMON *cm,
//
// NOTE(zoeliu): The probability of ref_frame[0] is LAST_FRAME,
// conditioning on it is either LAST_FRAME or LAST2_FRAME.
#if CONFIG_ONE_SIDED_COMPOUND
int av1_get_pred_context_comp_ref_p1(UNUSED const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
#else
int av1_get_pred_context_comp_ref_p1(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
#endif
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
......@@ -454,14 +723,16 @@ int av1_get_pred_context_comp_ref_p1(const AV1_COMMON *cm,
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
#if CONFIG_ONE_SIDED_COMPOUND // No change to bitstream
#if CONFIG_ONE_SIDED_COMPOUND || CONFIG_EXT_COMP_REFS // No change to bitstream
// Code seems to assume that signbias of cm->comp_bwd_ref[0] is always 1
const int bwd_ref_sign_idx = 1;
#else
const int bwd_ref_sign_idx = cm->ref_frame_sign_bias[cm->comp_bwd_ref[0]];
#endif
#endif // CONFIG_ONE_SIDED_COMPOUND || CONFIG_EXT_COMP_REFS
const int fwd_ref_sign_idx = !bwd_ref_sign_idx;
(void)cm;
if (above_in_image && left_in_image) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
......@@ -548,13 +819,8 @@ int av1_get_pred_context_comp_ref_p1(const AV1_COMMON *cm,
//
// NOTE(zoeliu): The probability of ref_frame[0] is GOLDEN_FRAME,
// conditioning on it is either GOLDEN or LAST3.
#if CONFIG_ONE_SIDED_COMPOUND
int av1_get_pred_context_comp_ref_p2(UNUSED const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
#else
int av1_get_pred_context_comp_ref_p2(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
#endif
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
......@@ -565,14 +831,16 @@ int av1_get_pred_context_comp_ref_p2(const AV1_COMMON *cm,
// The mode info data structure has a one element border above and to the
// left of the entries correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
#if CONFIG_ONE_SIDED_COMPOUND // No change to bitstream
#if CONFIG_ONE_SIDED_COMPOUND || CONFIG_EXT_COMP_REFS // No change to bitstream
// Code seems to assume that signbias of cm->comp_bwd_ref[0] is always 1
const int bwd_ref_sign_idx = 1;
#else
const int bwd_ref_sign_idx = cm->ref_frame_sign_bias[cm->comp_bwd_ref[0]];
#endif
#endif // CONFIG_ONE_SIDED_COMPOUND || CONFIG_EXT_COMP_REFS
const int fwd_ref_sign_idx = !bwd_ref_sign_idx;
(void)cm;
if (above_in_image && left_in_image) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
......@@ -653,13 +921,8 @@ int av1_get_pred_context_comp_ref_p2(const AV1_COMMON *cm,
}
// Returns a context number for the given MB prediction signal
#if CONFIG_ONE_SIDED_COMPOUND
int av1_get_pred_context_comp_bwdref_p(UNUSED const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
#else
int av1_get_pred_context_comp_bwdref_p(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
#endif
int pred_context;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
......@@ -670,14 +933,16 @@ int av1_get_pred_context_comp_bwdref_p(const AV1_COMMON *cm,
// The mode info data structure has a 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.
#if CONFIG_ONE_SIDED_COMPOUND // No change to bitstream
#if CONFIG_ONE_SIDED_COMPOUND || CONFIG_EXT_COMP_REFS // No change to bitstream
// Code seems to assume that signbias of cm->comp_bwd_ref[0] is always 1
const int bwd_ref_sign_idx = 1;
#else
const int bwd_ref_sign_idx = cm->ref_frame_sign_bias[cm->comp_bwd_ref[0]];
#endif
#endif // CONFIG_ONE_SIDED_COMPOUND || CONFIG_EXT_COMP_REFS
const int fwd_ref_sign_idx = !bwd_ref_sign_idx;
(void)cm;
if (above_in_image && left_in_image) { // both edges available
const int above_intra = !is_inter_block(above_mbmi);
const int left_intra = !is_inter_block(left_mbmi);
......@@ -716,8 +981,11 @@ int av1_get_pred_context_comp_bwdref_p(const AV1_COMMON *cm,
a_brf == cm->comp_bwd_ref[1]) {
pred_context = 1;
} else {
// NOTE: Backward ref should be either BWDREF or ALTREF.
// NOTE: Backward ref should be either BWDREF or ALTREF.
#if !USE_UNI_COMP_REFS
// TODO(zoeliu): To further study the UNIDIR scenario
assert(l_brf == a_brf && l_brf != cm->comp_bwd_ref[1]);
#endif // !USE_UNI_COMP_REFS
pred_context = 3;
}
} else if (!l_comp && !a_comp) { // single/single
......@@ -729,8 +997,11 @@ int av1_get_pred_context_comp_bwdref_p(const AV1_COMMON *cm,
} else if (l_frf == a_frf) {
pred_context = 3;
} else {
#if !USE_UNI_COMP_REFS
// TODO(zoeliu): To further study the UNIDIR scenario
assert(l_frf != a_frf && l_frf != cm->comp_bwd_ref[1] &&
a_frf != cm->comp_bwd_ref[1]);
#endif // !USE_UNI_COMP_REFS
pred_context = 4;
}
} else { // comp/single
......
......@@ -108,6 +108,35 @@ static INLINE aom_cdf_prob *av1_get_reference_mode_cdf(const AV1_COMMON *cm,
}
#endif
#if CONFIG_EXT_COMP_REFS
int av1_get_comp_reference_type_context(const AV1_COMMON *cm,
const MACROBLOCKD *xd);
static INLINE aom_prob av1_get_comp_reference_type_prob(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
return cm->fc
->comp_ref_type_prob[av1_get_comp_reference_type_context(cm, xd)];