Commit 4917295b authored by Zoe Liu's avatar Zoe Liu

[NORMATIVE] Unify comp ref context design

This patch uses the neighboring ref counts to design the contexts
for the coding of the first reference frame of a reference pair for
the compound prediction. This aligns the context design with that
for the second reference frame of a reference pair for the
compound prediction.

The new designed contexts are much simpler than that in the baseline.
The number of contexts for each binary symbol is reduced from 5 to
3. Further, the logic for each context only depends on the collected
neighboring ref counts, which is straightforward to derive.

The default CDFs for the first reference frame coding have been
updated using aom_entropy_optimizer.

Experimental results demonstrate a small coding gain for Google test
sets of both lowres and midres, with 30 frames coded for the default
coding tool setup:

lowres: avg_psnr -0.077%; ovr_psnr -0.076%; ssim -0.106%
midres: avg_psnr -0.059%; ovr_psnr -0.066%; ssim -0.037%

BUG=aomedia:1356

Change-Id: I781abbe4616dc3f3a7213ec663946ff9844eb830
parent e571f523
......@@ -237,16 +237,14 @@ static const aom_cdf_prob
#endif // CONFIG_EXT_COMP_REFS
static const aom_cdf_prob
default_comp_ref_cdf[REF_CONTEXTS][FWD_REFS - 1][CDF_SIZE(2)] = {
{ { AOM_CDF2(3556) }, { AOM_CDF2(1217) }, { AOM_CDF2(988) } },
{ { AOM_CDF2(9857) }, { AOM_CDF2(3394) }, { AOM_CDF2(3303) } },
{ { AOM_CDF2(16237) }, { AOM_CDF2(7946) }, { AOM_CDF2(7195) } },
{ { AOM_CDF2(23826) }, { AOM_CDF2(16124) }, { AOM_CDF2(20536) } },
{ { AOM_CDF2(30195) }, { AOM_CDF2(18344) }, { AOM_CDF2(21980) } }
default_comp_ref_cdf[COMP_REF_CONTEXTS][FWD_REFS - 1][CDF_SIZE(2)] = {
{ { AOM_CDF2(4412) }, { AOM_CDF2(11499) }, { AOM_CDF2(478) } },
{ { AOM_CDF2(17926) }, { AOM_CDF2(26419) }, { AOM_CDF2(8615) } },
{ { AOM_CDF2(30449) }, { AOM_CDF2(31477) }, { AOM_CDF2(28035) } }
};
static const aom_cdf_prob
default_comp_bwdref_cdf[COMP_BWDREF_CONTEXTS][BWD_REFS - 1][CDF_SIZE(2)] = {
default_comp_bwdref_cdf[COMP_REF_CONTEXTS][BWD_REFS - 1][CDF_SIZE(2)] = {
{ { AOM_CDF2(2762) }, { AOM_CDF2(1614) } },
{ { AOM_CDF2(17976) }, { AOM_CDF2(15912) } },
{ { AOM_CDF2(30894) }, { AOM_CDF2(30639) } },
......
......@@ -132,8 +132,8 @@ typedef struct frame_contexts {
aom_cdf_prob uni_comp_ref_cdf[UNI_COMP_REF_CONTEXTS][UNIDIR_COMP_REFS - 1]
[CDF_SIZE(2)];
#endif // CONFIG_EXT_COMP_REFS
aom_cdf_prob comp_ref_cdf[REF_CONTEXTS][FWD_REFS - 1][CDF_SIZE(2)];
aom_cdf_prob comp_bwdref_cdf[COMP_BWDREF_CONTEXTS][BWD_REFS - 1][CDF_SIZE(2)];
aom_cdf_prob comp_ref_cdf[COMP_REF_CONTEXTS][FWD_REFS - 1][CDF_SIZE(2)];
aom_cdf_prob comp_bwdref_cdf[COMP_REF_CONTEXTS][BWD_REFS - 1][CDF_SIZE(2)];
aom_cdf_prob txfm_partition_cdf[TXFM_PARTITION_CONTEXTS][CDF_SIZE(2)];
#if CONFIG_JNT_COMP
aom_cdf_prob compound_index_cdf[COMP_INDEX_CONTEXTS][CDF_SIZE(2)];
......@@ -274,8 +274,8 @@ typedef struct FRAME_COUNTS {
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];
unsigned int comp_ref[REF_CONTEXTS][FWD_REFS - 1][2];
unsigned int comp_bwdref[COMP_BWDREF_CONTEXTS][BWD_REFS - 1][2];
unsigned int comp_ref[COMP_REF_CONTEXTS][FWD_REFS - 1][2];
unsigned int comp_bwdref[COMP_REF_CONTEXTS][BWD_REFS - 1][2];
#if CONFIG_INTRABC
unsigned int intrabc[2];
#endif // CONFIG_INTRABC
......
......@@ -599,7 +599,7 @@ typedef enum ATTRIBUTE_PACKED {
#define INTRA_INTER_CONTEXTS 4
#define COMP_INTER_CONTEXTS 5
#define COMP_BWDREF_CONTEXTS 3
#define COMP_REF_CONTEXTS 3
#define REF_CONTEXTS 5
#if CONFIG_EXT_COMP_REFS
......
......@@ -372,309 +372,59 @@ int av1_get_pred_context_uni_comp_ref_p2(const MACROBLOCKD *xd) {
}
#endif // CONFIG_EXT_COMP_REFS
#define CHECK_LAST_OR_LAST2(ref_frame) \
((ref_frame == LAST_FRAME) || (ref_frame == LAST2_FRAME))
// Returns a context number for the given MB prediction signal
// Signal the first reference frame for a compound mode be either
// GOLDEN/LAST3, or LAST/LAST2.
//
// NOTE(zoeliu): The probability of ref_frame[0] is either
// GOLDEN_FRAME or LAST3_FRAME.
int av1_get_pred_context_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;
// Note:
// 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.
const int bwd_ref_sign_idx = 1;
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);
if (above_intra && left_intra) { // intra/intra (2)
pred_context = 2;
} else if (above_intra || left_intra) { // intra/inter
const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
if (!has_second_ref(edge_mbmi)) // single pred (1/3)
pred_context =
1 + 2 * (!CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[0]));
else // comp pred (1/3)
pred_context = 1 + 2 * (!CHECK_GOLDEN_OR_LAST3(
edge_mbmi->ref_frame[fwd_ref_sign_idx]));
} else { // inter/inter
const int l_sg = !has_second_ref(left_mbmi);
const int a_sg = !has_second_ref(above_mbmi);
const MV_REFERENCE_FRAME frfa =
a_sg ? above_mbmi->ref_frame[0]
: above_mbmi->ref_frame[fwd_ref_sign_idx];
const MV_REFERENCE_FRAME frfl =
l_sg ? left_mbmi->ref_frame[0]
: left_mbmi->ref_frame[fwd_ref_sign_idx];
if (frfa == frfl && CHECK_GOLDEN_OR_LAST3(frfa)) {
pred_context = 0;
} else if (l_sg && a_sg) { // single/single
if ((CHECK_BACKWARD_REFS(frfa) && CHECK_LAST_OR_LAST2(frfl)) ||
(CHECK_BACKWARD_REFS(frfl) && CHECK_LAST_OR_LAST2(frfa))) {
pred_context = 4;
} else if (CHECK_GOLDEN_OR_LAST3(frfa) || CHECK_GOLDEN_OR_LAST3(frfl)) {
pred_context = 1;
} else {
pred_context = 3;
}
} else if (l_sg || a_sg) { // single/comp
const MV_REFERENCE_FRAME frfc = l_sg ? frfa : frfl;
const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
if (CHECK_GOLDEN_OR_LAST3(frfc) && !CHECK_GOLDEN_OR_LAST3(rfs))
pred_context = 1;
else if (CHECK_GOLDEN_OR_LAST3(rfs) && !CHECK_GOLDEN_OR_LAST3(frfc))
pred_context = 2;
else
pred_context = 4;
} else { // comp/comp
if ((CHECK_LAST_OR_LAST2(frfa) && CHECK_LAST_OR_LAST2(frfl))) {
pred_context = 4;
} 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;
int av1_get_pred_context_comp_ref_p(const MACROBLOCKD *xd) {
const uint8_t *const ref_counts = &xd->neighbors_ref_counts[0];
if (!is_inter_block(edge_mbmi)) {
pred_context = 2;
} else {
if (has_second_ref(edge_mbmi))
pred_context =
4 *
(!CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[fwd_ref_sign_idx]));
else
pred_context = 3 * (!CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[0]));
}
} else { // no edges available (2)
pred_context = 2;
}
// Count of LAST + LAST2
const int last_last2_count = ref_counts[LAST_FRAME] + ref_counts[LAST2_FRAME];
// Count of LAST3 + GOLDEN
const int last3_gld_count =
ref_counts[LAST3_FRAME] + ref_counts[GOLDEN_FRAME];
assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
const int pred_context = (last_last2_count == last3_gld_count)
? 1
: ((last_last2_count < last3_gld_count) ? 0 : 2);
assert(pred_context >= 0 && pred_context < COMP_REF_CONTEXTS);
return pred_context;
}
// Returns a context number for the given MB prediction signal
// Signal the first reference frame for a compound mode be LAST,
// conditioning on that it is known either LAST/LAST2.
//
// NOTE(zoeliu): The probability of ref_frame[0] is LAST_FRAME,
// conditioning on it is either LAST_FRAME or LAST2_FRAME.
int av1_get_pred_context_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;
// Note:
// 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.
const int bwd_ref_sign_idx = 1;
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);
if (above_intra && left_intra) { // intra/intra (2)
pred_context = 2;
} else if (above_intra || left_intra) { // intra/inter
const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
if (!has_second_ref(edge_mbmi)) // single pred (1/3)
pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != LAST2_FRAME);
else // comp pred (1/3)
pred_context =
1 + 2 * (edge_mbmi->ref_frame[fwd_ref_sign_idx] != LAST2_FRAME);
} else { // inter/inter
const int l_sg = !has_second_ref(left_mbmi);
const int a_sg = !has_second_ref(above_mbmi);
const MV_REFERENCE_FRAME frfa =
a_sg ? above_mbmi->ref_frame[0]
: above_mbmi->ref_frame[fwd_ref_sign_idx];
const MV_REFERENCE_FRAME frfl =
l_sg ? left_mbmi->ref_frame[0]
: left_mbmi->ref_frame[fwd_ref_sign_idx];
if (frfa == frfl && frfa == LAST2_FRAME)
pred_context = 0;
else if (l_sg && a_sg) { // single/single
if (frfa == LAST2_FRAME || frfl == LAST2_FRAME)
pred_context = 1;
else if (CHECK_GOLDEN_OR_LAST3(frfa) || CHECK_GOLDEN_OR_LAST3(frfl))
pred_context = 2 + (frfa != frfl);
else if (frfa == frfl ||
(CHECK_BACKWARD_REFS(frfa) && CHECK_BACKWARD_REFS(frfl)))
pred_context = 3;
else
pred_context = 4;
} else if (l_sg || a_sg) { // single/comp
const MV_REFERENCE_FRAME frfc = l_sg ? frfa : frfl;
const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
if (frfc == LAST2_FRAME && rfs != LAST2_FRAME)
pred_context = 1;
else if (rfs == LAST2_FRAME && frfc != LAST2_FRAME)
pred_context = 2;
else
pred_context = 3 + (frfc == LAST_FRAME || CHECK_GOLDEN_OR_LAST3(rfs));
} else { // comp/comp
if (frfa == LAST2_FRAME || frfl == LAST2_FRAME)
pred_context = 2;
else
pred_context =
3 + (CHECK_GOLDEN_OR_LAST3(frfa) || CHECK_GOLDEN_OR_LAST3(frfl));
}
}
} else if (above_in_image || left_in_image) { // one edge available
const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
int av1_get_pred_context_comp_ref_p1(const MACROBLOCKD *xd) {
const uint8_t *const ref_counts = &xd->neighbors_ref_counts[0];
if (!is_inter_block(edge_mbmi)) {
pred_context = 2;
} else {
if (has_second_ref(edge_mbmi)) {
pred_context =
4 * (edge_mbmi->ref_frame[fwd_ref_sign_idx] != LAST2_FRAME);
} else {
if (edge_mbmi->ref_frame[0] == LAST2_FRAME)
pred_context = 0;
else
pred_context = 2 + CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[0]);
}
}
} else { // no edges available (2)
pred_context = 2;
}
// Count of LAST
const int last_count = ref_counts[LAST_FRAME];
// Count of LAST2
const int last2_count = ref_counts[LAST2_FRAME];
assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
const int pred_context =
(last_count == last2_count) ? 1 : ((last_count < last2_count) ? 0 : 2);
assert(pred_context >= 0 && pred_context < COMP_REF_CONTEXTS);
return pred_context;
}
// Returns a context number for the given MB prediction signal
// Signal the first reference frame for a compound mode be GOLDEN,
// conditioning on that it is known either GOLDEN or LAST3.
//
// NOTE(zoeliu): The probability of ref_frame[0] is GOLDEN_FRAME,
// conditioning on it is either GOLDEN or LAST3.
int av1_get_pred_context_comp_ref_p2(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;
// Note:
// 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.
const int bwd_ref_sign_idx = 1;
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);
if (above_intra && left_intra) { // intra/intra (2)
pred_context = 2;
} else if (above_intra || left_intra) { // intra/inter
const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
if (!has_second_ref(edge_mbmi)) // single pred (1/3)
pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != GOLDEN_FRAME);
else // comp pred (1/3)
pred_context =
1 + 2 * (edge_mbmi->ref_frame[fwd_ref_sign_idx] != GOLDEN_FRAME);
} else { // inter/inter
const int l_sg = !has_second_ref(left_mbmi);
const int a_sg = !has_second_ref(above_mbmi);
const MV_REFERENCE_FRAME frfa =
a_sg ? above_mbmi->ref_frame[0]
: above_mbmi->ref_frame[fwd_ref_sign_idx];
const MV_REFERENCE_FRAME frfl =
l_sg ? left_mbmi->ref_frame[0]
: left_mbmi->ref_frame[fwd_ref_sign_idx];
if (frfa == frfl && frfa == GOLDEN_FRAME)
pred_context = 0;
else if (l_sg && a_sg) { // single/single
if (frfa == GOLDEN_FRAME || frfl == GOLDEN_FRAME)
pred_context = 1;
else if (CHECK_LAST_OR_LAST2(frfa) || CHECK_LAST_OR_LAST2(frfl))
pred_context = 2 + (frfa != frfl);
else if (frfa == frfl ||
(CHECK_BACKWARD_REFS(frfa) && CHECK_BACKWARD_REFS(frfl)))
pred_context = 3;
else
pred_context = 4;
} else if (l_sg || a_sg) { // single/comp
const MV_REFERENCE_FRAME frfc = l_sg ? frfa : frfl;
const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
if (frfc == GOLDEN_FRAME && rfs != GOLDEN_FRAME)
pred_context = 1;
else if (rfs == GOLDEN_FRAME && frfc != GOLDEN_FRAME)
pred_context = 2;
else
pred_context = 3 + (frfc == LAST3_FRAME || CHECK_LAST_OR_LAST2(rfs));
} else { // comp/comp
if (frfa == GOLDEN_FRAME || frfl == GOLDEN_FRAME)
pred_context = 2;
else
pred_context =
3 + (CHECK_LAST_OR_LAST2(frfa) || CHECK_LAST_OR_LAST2(frfl));
}
}
} else if (above_in_image || left_in_image) { // one edge available
const MB_MODE_INFO *edge_mbmi = above_in_image ? above_mbmi : left_mbmi;
int av1_get_pred_context_comp_ref_p2(const MACROBLOCKD *xd) {
const uint8_t *const ref_counts = &xd->neighbors_ref_counts[0];
if (!is_inter_block(edge_mbmi)) {
pred_context = 2;
} else {
if (has_second_ref(edge_mbmi)) {
pred_context =
4 * (edge_mbmi->ref_frame[fwd_ref_sign_idx] != GOLDEN_FRAME);
} else {
if (edge_mbmi->ref_frame[0] == GOLDEN_FRAME)
pred_context = 0;
else
pred_context = 2 + CHECK_LAST_OR_LAST2(edge_mbmi->ref_frame[0]);
}
}
} else { // no edges available (2)
pred_context = 2;
}
// Count of LAST3
const int last3_count = ref_counts[LAST3_FRAME];
// Count of GOLDEN
const int gld_count = ref_counts[GOLDEN_FRAME];
assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
const int pred_context =
(last3_count == gld_count) ? 1 : ((last3_count < gld_count) ? 0 : 2);
assert(pred_context >= 0 && pred_context < COMP_REF_CONTEXTS);
return pred_context;
}
......@@ -691,7 +441,7 @@ int av1_get_pred_context_brfarf2_or_arf(const MACROBLOCKD *xd) {
const int pred_context =
(brfarf2_count == arf_count) ? 1 : ((brfarf2_count < arf_count) ? 0 : 2);
assert(pred_context >= 0 && pred_context < COMP_BWDREF_CONTEXTS);
assert(pred_context >= 0 && pred_context < COMP_REF_CONTEXTS);
return pred_context;
}
......@@ -707,7 +457,7 @@ int av1_get_pred_context_brf_or_arf2(const MACROBLOCKD *xd) {
const int pred_context =
(brf_count == arf2_count) ? 1 : ((brf_count < arf2_count) ? 0 : 2);
assert(pred_context >= 0 && pred_context < COMP_BWDREF_CONTEXTS);
assert(pred_context >= 0 && pred_context < COMP_REF_CONTEXTS);
return pred_context;
}
......@@ -792,6 +542,9 @@ int av1_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
return av1_get_pred_context_brfarf2_or_arf(xd);
}
#define CHECK_LAST_OR_LAST2(ref_frame) \
((ref_frame == LAST_FRAME) || (ref_frame == LAST2_FRAME))
// For the bit to signal whether the single reference is LAST3/GOLDEN or
// LAST2/LAST, knowing that it shall be either of these 2 choices.
int av1_get_pred_context_single_ref_p3(const MACROBLOCKD *xd) {
......
......@@ -215,6 +215,8 @@ static INLINE aom_cdf_prob *av1_get_reference_mode_cdf(const AV1_COMMON *cm,
#if CONFIG_EXT_COMP_REFS
int av1_get_comp_reference_type_context(const MACROBLOCKD *xd);
// == Uni-directional contexts ==
int av1_get_pred_context_uni_comp_ref_p(const MACROBLOCKD *xd);
int av1_get_pred_context_uni_comp_ref_p1(const MACROBLOCKD *xd);
......@@ -246,49 +248,49 @@ static INLINE aom_cdf_prob *av1_get_pred_cdf_uni_comp_ref_p2(
}
#endif // CONFIG_EXT_COMP_REFS
int av1_get_pred_context_comp_ref_p(const AV1_COMMON *cm,
const MACROBLOCKD *xd);
// == Bi-directional contexts ==
int av1_get_pred_context_comp_ref_p(const MACROBLOCKD *xd);
int av1_get_pred_context_comp_ref_p1(const MACROBLOCKD *xd);
static INLINE aom_cdf_prob *av1_get_pred_cdf_comp_ref_p(const AV1_COMMON *cm,
const MACROBLOCKD *xd) {
const int pred_context = av1_get_pred_context_comp_ref_p(cm, xd);
int av1_get_pred_context_comp_ref_p2(const MACROBLOCKD *xd);
int av1_get_pred_context_comp_bwdref_p(const MACROBLOCKD *xd);
int av1_get_pred_context_comp_bwdref_p1(const MACROBLOCKD *xd);
static INLINE aom_cdf_prob *av1_get_pred_cdf_comp_ref_p(const MACROBLOCKD *xd) {
const int pred_context = av1_get_pred_context_comp_ref_p(xd);
return xd->tile_ctx->comp_ref_cdf[pred_context][0];
}
int av1_get_pred_context_comp_ref_p1(const AV1_COMMON *cm,
const MACROBLOCKD *xd);
static INLINE aom_cdf_prob *av1_get_pred_cdf_comp_ref_p1(
const AV1_COMMON *cm, const MACROBLOCKD *xd) {
const int pred_context = av1_get_pred_context_comp_ref_p1(cm, xd);
const MACROBLOCKD *xd) {
const int pred_context = av1_get_pred_context_comp_ref_p1(xd);
return xd->tile_ctx->comp_ref_cdf[pred_context][1];
}
int av1_get_pred_context_comp_ref_p2(const AV1_COMMON *cm,
const MACROBLOCKD *xd);
static INLINE aom_cdf_prob *av1_get_pred_cdf_comp_ref_p2(
const AV1_COMMON *cm, const MACROBLOCKD *xd) {
const int pred_context = av1_get_pred_context_comp_ref_p2(cm, xd);
const MACROBLOCKD *xd) {
const int pred_context = av1_get_pred_context_comp_ref_p2(xd);
return xd->tile_ctx->comp_ref_cdf[pred_context][2];
}
int av1_get_pred_context_comp_bwdref_p(const MACROBLOCKD *xd);
static INLINE aom_cdf_prob *av1_get_pred_cdf_comp_bwdref_p(
const MACROBLOCKD *xd) {
const int pred_context = av1_get_pred_context_comp_bwdref_p(xd);
return xd->tile_ctx->comp_bwdref_cdf[pred_context][0];
}
int av1_get_pred_context_comp_bwdref_p1(const MACROBLOCKD *xd);
static INLINE aom_cdf_prob *av1_get_pred_cdf_comp_bwdref_p1(
const MACROBLOCKD *xd) {
const int pred_context = av1_get_pred_context_comp_bwdref_p1(xd);
return xd->tile_ctx->comp_bwdref_cdf[pred_context][1];
}
// == Single contexts ==
int av1_get_pred_context_single_ref_p1(const MACROBLOCKD *xd);
int av1_get_pred_context_single_ref_p2(const MACROBLOCKD *xd);
......
......@@ -1210,8 +1210,6 @@ static REFERENCE_MODE read_block_reference_mode(AV1_COMMON *cm,
}
#define READ_REF_BIT(pname) \
aom_read_symbol(r, av1_get_pred_cdf_##pname(cm, xd), 2, ACCT_STR)
#define READ_REF_BIT2(pname) \
aom_read_symbol(r, av1_get_pred_cdf_##pname(xd), 2, ACCT_STR)
#if CONFIG_EXT_COMP_REFS
......@@ -1266,14 +1264,14 @@ static void read_ref_frames(AV1_COMMON *const cm, MACROBLOCKD *const xd,
const COMP_REFERENCE_TYPE comp_ref_type = read_comp_reference_type(xd, r);
if (comp_ref_type == UNIDIR_COMP_REFERENCE) {
const int bit = READ_REF_BIT2(uni_comp_ref_p);
const int bit = READ_REF_BIT(uni_comp_ref_p);
if (bit) {
ref_frame[0] = BWDREF_FRAME;
ref_frame[1] = ALTREF_FRAME;
} else {
const int bit1 = READ_REF_BIT2(uni_comp_ref_p1);
const int bit1 = READ_REF_BIT(uni_comp_ref_p1);
if (bit1) {
const int bit2 = READ_REF_BIT2(uni_comp_ref_p2);
const int bit2 = READ_REF_BIT(uni_comp_ref_p2);
if (bit2) {
ref_frame[0] = LAST_FRAME;
ref_frame[1] = GOLDEN_FRAME;
......@@ -1305,30 +1303,30 @@ static void read_ref_frames(AV1_COMMON *const cm, MACROBLOCKD *const xd,
}
// Decode backward references.
const int bit_bwd = READ_REF_BIT2(comp_bwdref_p);
const int bit_bwd = READ_REF_BIT(comp_bwdref_p);
if (!bit_bwd) {
const int bit1_bwd = READ_REF_BIT2(comp_bwdref_p1);
const int bit1_bwd = READ_REF_BIT(comp_bwdref_p1);
ref_frame[idx] = cm->comp_bwd_ref[bit1_bwd];
} else {
ref_frame[idx] = cm->comp_bwd_ref[2];
}
} else if (mode == SINGLE_REFERENCE) {
const int bit0 = READ_REF_BIT2(single_ref_p1);
const int bit0 = READ_REF_BIT(single_ref_p1);
if (bit0) {
const int bit1 = READ_REF_BIT2(single_ref_p2);
const int bit1 = READ_REF_BIT(single_ref_p2);
if (!bit1) {
const int bit5 = READ_REF_BIT2(single_ref_p6);
const int bit5 = READ_REF_BIT(single_ref_p6);
ref_frame[0] = bit5 ? ALTREF2_FRAME : BWDREF_FRAME;
} else {
ref_frame[0] = ALTREF_FRAME;
}
} else {
const int bit2 = READ_REF_BIT2(single_ref_p3);
const int bit2 = READ_REF_BIT(single_ref_p3);
if (bit2) {
const int bit4 = READ_REF_BIT2(single_ref_p5);
const int bit4 = READ_REF_BIT(single_ref_p5);
ref_frame[0] = bit4 ? GOLDEN_FRAME : LAST3_FRAME;
} else {
const int bit3 = READ_REF_BIT2(single_ref_p4);
const int bit3 = READ_REF_BIT(single_ref_p4);
ref_frame[0] = bit3 ? LAST2_FRAME : LAST_FRAME;
}
}
......
......@@ -648,8 +648,6 @@ static void write_segment_id(aom_writer *w, const struct segmentation *seg,
#endif
#define WRITE_REF_BIT(bname, pname) \
aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(cm, xd), 2)
#define WRITE_REF_BIT2(bname, pname) \
aom_write_symbol(w, bname, av1_get_pred_cdf_##pname(xd), 2)
// This function encodes the reference frame
......@@ -695,16 +693,16 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd,
if (comp_ref_type == UNIDIR_COMP_REFERENCE) {
const int bit = mbmi->ref_frame[0] == BWDREF_FRAME;
WRITE_REF_BIT2(bit, uni_comp_ref_p);
WRITE_REF_BIT(bit, uni_comp_ref_p);
if (!bit) {
assert(mbmi->ref_frame[0] == LAST_FRAME);
const int bit1 = mbmi->ref_frame[1] == LAST3_FRAME ||
mbmi->ref_frame[1] == GOLDEN_FRAME;
WRITE_REF_BIT2(bit1, uni_comp_ref_p1);
WRITE_REF_BIT(bit1, uni_comp_ref_p1);
if (bit1) {
const int bit2 = mbmi->ref_frame[1] == GOLDEN_FRAME;
WRITE_REF_BIT2(bit2, uni_comp_ref_p2);
WRITE_REF_BIT(bit2, uni_comp_ref_p2);
}
} else {
assert(mbmi->ref_frame[1] == ALTREF_FRAME);
......@@ -729,35 +727,35 @@ static void write_ref_frames(const AV1_COMMON *cm, const MACROBLOCKD *xd,
}
const int bit_bwd = mbmi->ref_frame[1] == ALTREF_FRAME;
WRITE_REF_BIT2(bit_bwd, comp_bwdref_p);
WRITE_REF_BIT(bit_bwd, comp_bwdref_p);