Commit cf5083d4 authored by Zoe Liu's avatar Zoe Liu
Browse files

Added an experiment "bidir_pred" for backward prediction

Major parts have been implemented as follows:
(1) Added BRF_UPDATE, LASTNRF_UPDATE, and NRF_UPDATE in firstpass.c;
(2) Added the handling for the scenario of
"cpi->common.show_existing_frame == 1" at the encoder;
(3) Added a new reference frame of BWDREF_FRAME;
(4) Have bwd-ref work with upsampled references.

Note that when the experiment of "ext_refs" turned on, this experiment
will be turned off automatically currently.

RD performance in Overall PSNR has been improved, compared against the
VP10 baseline:

lowres: Avg -3.312; BDRate -3.154
derflr: Avg -1.927; BDRate -1.176
midres: Avg -2.149; BDRate -2.001
hdres : Avg -0.567; BDRate -0.588

Change-Id: I4c06ff51cc20194bffbd4d2346e57ba3dcf6b62c
parent 89f5b6a0
......@@ -96,7 +96,9 @@ typedef struct {
#define NONE -1
#define INTRA_FRAME 0
#define LAST_FRAME 1
#if CONFIG_EXT_REFS
#define LAST2_FRAME 2
#define LAST3_FRAME 3
#define LAST4_FRAME 4
......@@ -104,10 +106,24 @@ typedef struct {
#define ALTREF_FRAME 6
#define MAX_REF_FRAMES 7
#define LAST_REF_FRAMES (LAST4_FRAME - LAST_FRAME + 1)
#else
#else // CONFIG_EXT_REFS
#if CONFIG_BIDIR_PRED
#define GOLDEN_FRAME 2
#define BWDREF_FRAME 3
#define ALTREF_FRAME 4
#define MAX_REF_FRAMES 5
#else // CONFIG_BIDIR_PRED
#define GOLDEN_FRAME 2
#define ALTREF_FRAME 3
#define MAX_REF_FRAMES 4
#endif // CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
typedef int8_t MV_REFERENCE_FRAME;
......
......@@ -383,18 +383,35 @@ static const vpx_prob default_comp_inter_p[COMP_INTER_CONTEXTS] = {
239, 183, 119, 96, 41
};
static const vpx_prob default_comp_ref_p[REF_CONTEXTS][COMP_REFS - 1] = {
#if CONFIG_EXT_REFS
static const vpx_prob default_comp_ref_p[REF_CONTEXTS][COMP_REFS - 1] = {
// TODO(zoeliu): To adjust the initial prob values.
{ 33, 16, 16, 16 },
{ 77, 74, 74, 74 },
{ 142, 142, 142, 142 },
{ 172, 170, 170, 170 },
{ 238, 247, 247, 247 }
#else
};
#else // CONFIG_EXT_REFS
#if CONFIG_BIDIR_PRED
// TODO(zoeliu): To adjust the initial prob values.
static const vpx_prob default_comp_ref_p[REF_CONTEXTS][FWD_REFS - 1] = {
// { 50 }, { 126 }, { 123 }, { 221 }, { 226 }
{ 33 }, { 77 }, { 142 }, { 172 }, { 238 }
};
static const vpx_prob default_comp_bwdref_p[REF_CONTEXTS][BWD_REFS - 1] = {
{ 16 }, { 74 }, { 142 }, { 170 }, { 247 }
};
#else // CONFIG_BIDIR_PRED
static const vpx_prob default_comp_ref_p[REF_CONTEXTS][COMP_REFS - 1] = {
{ 50 }, { 126 }, { 123 }, { 221 }, { 226 }
#endif // CONFIG_EXT_REFS
};
#endif // CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
static const vpx_prob default_single_ref_p[REF_CONTEXTS][SINGLE_REFS - 1] = {
#if CONFIG_EXT_REFS
......@@ -403,12 +420,20 @@ static const vpx_prob default_single_ref_p[REF_CONTEXTS][SINGLE_REFS - 1] = {
{ 142, 142, 142, 142, 142 },
{ 172, 170, 170, 170, 170 },
{ 238, 247, 247, 247, 247 }
#else
#else // CONFIG_EXT_REFS
#if CONFIG_BIDIR_PRED
{ 33, 16, 16 },
{ 77, 74, 74 },
{ 142, 142, 142 },
{ 172, 170, 170 },
{ 238, 247, 247 }
#else // CONFIG_BIDIR_PRED
{ 33, 16 },
{ 77, 74 },
{ 142, 142 },
{ 172, 170 },
{ 238, 247 }
#endif // CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
};
......@@ -1243,6 +1268,9 @@ static void init_mode_probs(FRAME_CONTEXT *fc) {
vp10_copy(fc->intra_inter_prob, default_intra_inter_p);
vp10_copy(fc->comp_inter_prob, default_comp_inter_p);
vp10_copy(fc->comp_ref_prob, default_comp_ref_p);
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
vp10_copy(fc->comp_bwdref_prob, default_comp_bwdref_p);
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
vp10_copy(fc->single_ref_prob, default_single_ref_p);
vp10_copy(fc->tx_size_probs, default_tx_size_prob);
#if CONFIG_VAR_TX
......@@ -1310,10 +1338,23 @@ void vp10_adapt_inter_frame_probs(VP10_COMMON *cm) {
for (i = 0; i < COMP_INTER_CONTEXTS; i++)
fc->comp_inter_prob[i] = vp10_mode_mv_merge_probs(
pre_fc->comp_inter_prob[i], counts->comp_inter[i]);
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < (FWD_REFS - 1); j++)
fc->comp_ref_prob[i][j] = mode_mv_merge_probs(
pre_fc->comp_ref_prob[i][j], counts->comp_ref[i][j]);
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < (BWD_REFS - 1); j++)
fc->comp_bwdref_prob[i][j] = mode_mv_merge_probs(
pre_fc->comp_bwdref_prob[i][j], counts->comp_bwdref[i][j]);
#else
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < (COMP_REFS - 1); j++)
fc->comp_ref_prob[i][j] = vp10_mode_mv_merge_probs(
fc->comp_ref_prob[i][j] = mode_mv_merge_probs(
pre_fc->comp_ref_prob[i][j], counts->comp_ref[i][j]);
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < (SINGLE_REFS - 1); j++)
fc->single_ref_prob[i][j] = vp10_mode_mv_merge_probs(
......
......@@ -85,7 +85,12 @@ typedef struct frame_contexts {
vpx_prob intra_inter_prob[INTRA_INTER_CONTEXTS];
vpx_prob comp_inter_prob[COMP_INTER_CONTEXTS];
vpx_prob single_ref_prob[REF_CONTEXTS][SINGLE_REFS-1];
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
vpx_prob comp_ref_prob[REF_CONTEXTS][FWD_REFS-1];
vpx_prob comp_bwdref_prob[REF_CONTEXTS][BWD_REFS-1];
#else
vpx_prob comp_ref_prob[REF_CONTEXTS][COMP_REFS-1];
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
vpx_prob tx_size_probs[TX_SIZES - 1][TX_SIZE_CONTEXTS][TX_SIZES - 1];
#if CONFIG_VAR_TX
vpx_prob txfm_partition_prob[TXFM_PARTITION_CONTEXTS];
......@@ -155,7 +160,12 @@ typedef struct FRAME_COUNTS {
unsigned int intra_inter[INTRA_INTER_CONTEXTS][2];
unsigned int comp_inter[COMP_INTER_CONTEXTS][2];
unsigned int single_ref[REF_CONTEXTS][SINGLE_REFS-1][2];
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
unsigned int comp_ref[REF_CONTEXTS][FWD_REFS-1][2];
unsigned int comp_bwdref[REF_CONTEXTS][BWD_REFS-1][2];
#else
unsigned int comp_ref[REF_CONTEXTS][COMP_REFS-1][2];
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
unsigned int tx_size_totals[TX_SIZES];
unsigned int tx_size[TX_SIZES - 1][TX_SIZE_CONTEXTS][TX_SIZES];
#if CONFIG_VAR_TX
......
......@@ -204,10 +204,17 @@ typedef enum {
VP9_GOLD_FLAG = 1 << 4,
VP9_ALT_FLAG = 1 << 5,
VP9_REFFRAME_ALL = (1 << 6) - 1
#else
#else // CONFIG_EXT_REFS
#if CONFIG_BIDIR_PRED
VP9_GOLD_FLAG = 1 << 1,
VP9_BWD_FLAG = 1 << 2,
VP9_ALT_FLAG = 1 << 3,
VP9_REFFRAME_ALL = (1 << 4) - 1
#else // CONFIG_BIDIR_PRED
VP9_GOLD_FLAG = 1 << 1,
VP9_ALT_FLAG = 1 << 2,
VP9_REFFRAME_ALL = (1 << 3) - 1
#endif // CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
} VP9_REFFRAME;
......@@ -367,11 +374,24 @@ typedef TX_SIZE TXFM_CONTEXT;
#endif
#if CONFIG_EXT_REFS
#define SINGLE_REFS 6
#define COMP_REFS 5
#else
#else // CONFIG_EXT_REFS
#if CONFIG_BIDIR_PRED
#define FWD_REFS 2
#define BWD_REFS 2
#define SINGLE_REFS (FWD_REFS + BWD_REFS)
#define COMP_REFS (FWD_REFS * BWD_REFS)
#else // CONFIG_BIDIR_PRED
#define SINGLE_REFS 3
#define COMP_REFS 2
#endif // CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
#if CONFIG_SUPERTX
......
......@@ -45,7 +45,7 @@ struct loopfilter {
uint8_t mode_ref_delta_update;
// 0 = Intra, Last, Last2+Last3+LAST4(CONFIG_EXT_REFS),
// GF, ARF
// GF, BRF(CONFIG_BIDIR_PRED), ARF
signed char ref_deltas[MAX_REF_FRAMES];
signed char last_ref_deltas[MAX_REF_FRAMES];
......
......@@ -186,6 +186,9 @@ typedef struct VP10Common {
int show_frame;
int last_show_frame;
int show_existing_frame;
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
int is_reference_frame; // A frame used as a reference
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// Flag signaling that the frame is encoded using only INTRA modes.
uint8_t intra_only;
......@@ -270,8 +273,13 @@ typedef struct VP10Common {
int frame_parallel_decode; // frame-based threading.
// Context probabilities for reference frame prediction
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
MV_REFERENCE_FRAME comp_fwd_ref[FWD_REFS];
MV_REFERENCE_FRAME comp_bwd_ref[BWD_REFS];
#else
MV_REFERENCE_FRAME comp_fixed_ref;
MV_REFERENCE_FRAME comp_var_ref[COMP_REFS];
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
REFERENCE_MODE reference_mode;
FRAME_CONTEXT *fc; /* this frame entropy */
......
......@@ -177,8 +177,57 @@ int vp10_get_intra_inter_context(const MACROBLOCKD *xd) {
}
}
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#define CHECK_COMP_BWD_REF(ref_frame) \
(((ref_frame) == cm->comp_bwd_ref[0]) || ((ref_frame) == cm->comp_bwd_ref[1]))
int vp10_get_reference_mode_context(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
int ctx;
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;
// Note:
// 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 (has_above && has_left) { // both edges available
if (!has_second_ref(above_mbmi) && !has_second_ref(left_mbmi))
// neither edge uses comp pred (0/1)
ctx = CHECK_COMP_BWD_REF(above_mbmi->ref_frame[0]) ^
CHECK_COMP_BWD_REF(left_mbmi->ref_frame[0]);
else if (!has_second_ref(above_mbmi))
// one of two edges uses comp pred (2/3)
ctx = 2 + (CHECK_COMP_BWD_REF(above_mbmi->ref_frame[0]) ||
!is_inter_block(above_mbmi));
else if (!has_second_ref(left_mbmi))
// one of two edges uses comp pred (2/3)
ctx = 2 + (CHECK_COMP_BWD_REF(left_mbmi->ref_frame[0]) ||
!is_inter_block(left_mbmi));
else // both edges use comp pred (4)
ctx = 4;
} else if (has_above || has_left) { // one edge available
const MB_MODE_INFO *edge_mbmi = has_above ? above_mbmi : left_mbmi;
if (!has_second_ref(edge_mbmi))
// edge does not use comp pred (0/1)
ctx = CHECK_COMP_BWD_REF(edge_mbmi->ref_frame[0]);
else
// edge uses comp pred (3)
ctx = 3;
} else { // no edges available (1)
ctx = 1;
}
assert(ctx >= 0 && ctx < COMP_INTER_CONTEXTS);
return ctx;
}
#else // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
int vp10_get_reference_mode_context(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
const MACROBLOCKD *xd) {
int ctx;
const MB_MODE_INFO *const above_mbmi = xd->above_mbmi;
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
......@@ -219,6 +268,8 @@ int vp10_get_reference_mode_context(const VP10_COMMON *cm,
return ctx;
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#if CONFIG_EXT_REFS
// TODO(zoeliu): Future work will be conducted to optimize the context design
......@@ -634,6 +685,200 @@ int vp10_get_pred_context_comp_ref_p3(const VP10_COMMON *cm,
#else // CONFIG_EXT_REFS
#if CONFIG_BIDIR_PRED
// Returns a context number for the given MB prediction signal
int vp10_get_pred_context_comp_ref_p(const VP10_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 corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
const int bwd_ref_sign_idx = cm->ref_frame_sign_bias[cm->comp_bwd_ref[0]];
const int fwd_ref_sign_idx = !bwd_ref_sign_idx;
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] != cm->comp_fwd_ref[1]);
else // comp pred (1/3)
pred_context = 1 + 2 * (edge_mbmi->ref_frame[fwd_ref_sign_idx]
!= cm->comp_fwd_ref[1]);
} 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 == cm->comp_fwd_ref[1]) {
pred_context = 0;
} else if (l_sg && a_sg) { // single/single
if ((frfa != frfl) &&
(frfa != cm->comp_fwd_ref[1]) && (frfl != cm->comp_fwd_ref[1]))
pred_context = 4;
else if (frfa == frfl)
pred_context = 3;
else
pred_context = 1;
} 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 == cm->comp_fwd_ref[1] && rfs != cm->comp_fwd_ref[1])
pred_context = 1;
else if (rfs == cm->comp_fwd_ref[1] && frfc != cm->comp_fwd_ref[1])
pred_context = 2;
else
pred_context = 4;
} else if (frfa == frfl) { // comp/comp
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;
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]
!= cm->comp_fwd_ref[1]);
else
pred_context = 3 * (edge_mbmi->ref_frame[0] != cm->comp_fwd_ref[1]);
}
} else { // no edges available (2)
pred_context = 2;
}
assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
return pred_context;
}
// Returns a context number for the given MB prediction signal
int vp10_get_pred_context_comp_bwdref_p(const VP10_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 corresponding to real macroblocks.
// The prediction flags in these dummy entries are initialized to 0.
const int bwd_ref_sign_idx = cm->ref_frame_sign_bias[cm->comp_bwd_ref[0]];
const int fwd_ref_sign_idx = !bwd_ref_sign_idx;
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[1] != cm->comp_bwd_ref[1]);
else // comp pred (1/3)
pred_context = 1 + 2 * (edge_mbmi->ref_frame[bwd_ref_sign_idx]
!= cm->comp_bwd_ref[1]);
} else { // inter/inter
const int l_comp = has_second_ref(left_mbmi);
const int a_comp = has_second_ref(above_mbmi);
const MV_REFERENCE_FRAME l_brf = l_comp ?
left_mbmi->ref_frame[bwd_ref_sign_idx] : NONE;
const MV_REFERENCE_FRAME a_brf = a_comp ?
above_mbmi->ref_frame[bwd_ref_sign_idx] : NONE;
const MV_REFERENCE_FRAME l_frf = !l_comp ?
left_mbmi->ref_frame[0] : left_mbmi->ref_frame[fwd_ref_sign_idx];
const MV_REFERENCE_FRAME a_frf = !a_comp ?
above_mbmi->ref_frame[0] : above_mbmi->ref_frame[fwd_ref_sign_idx];
if (l_comp && a_comp) {
if (l_brf == a_brf && l_brf == cm->comp_bwd_ref[1]) {
pred_context = 0;
} else if (l_brf == cm->comp_bwd_ref[1] ||
a_brf == cm->comp_bwd_ref[1]) {
pred_context = 1;
} else {
// NOTE: Backward ref should be either BWDREF or ALTREF.
assert(l_brf == a_brf && l_brf != cm->comp_bwd_ref[1]);
pred_context = 3;
}
} else if (!l_comp && !a_comp) {
if (l_frf == a_frf && l_frf == cm->comp_bwd_ref[1]) {
pred_context = 0;
} else if (l_frf == cm->comp_bwd_ref[1] ||
a_frf == cm->comp_bwd_ref[1]) {
pred_context = 1;
} else if (l_frf == a_frf) {
pred_context = 3;
} else {
assert(l_frf != a_frf &&
l_frf != cm->comp_bwd_ref[1] && a_frf != cm->comp_bwd_ref[1]);
pred_context = 4;
}
} else {
assert((l_comp && !a_comp) || (!l_comp && a_comp));
if ((l_comp && l_brf == cm->comp_bwd_ref[1] &&
a_frf == cm->comp_bwd_ref[1]) ||
(a_comp && a_brf == cm->comp_bwd_ref[1] &&
l_frf == cm->comp_bwd_ref[1])) {
pred_context = 1;
} else if ((l_comp && l_brf == cm->comp_bwd_ref[1]) ||
(a_comp && a_brf == cm->comp_bwd_ref[1]) ||
(!l_comp && l_frf == cm->comp_bwd_ref[1]) ||
(!a_comp && a_frf == cm->comp_bwd_ref[1])) {
pred_context = 2;
} else {
pred_context = 4;
}
}
}
} 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)) {
pred_context = 2;
} else {
if (has_second_ref(edge_mbmi)) {
pred_context = 4 * (edge_mbmi->ref_frame[bwd_ref_sign_idx]
!= cm->comp_bwd_ref[1]);
} else {
pred_context = 3 * (edge_mbmi->ref_frame[0] != cm->comp_bwd_ref[1]);
}
}
} else { // no edges available (2)
pred_context = 2;
}
assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
return pred_context;
}
#else // CONFIG_BIDIR_PRED
// Returns a context number for the given MB prediction signal
int vp10_get_pred_context_comp_ref_p(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
......@@ -717,6 +962,8 @@ int vp10_get_pred_context_comp_ref_p(const VP10_COMMON *cm,
return pred_context;
}
#endif // CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
#if CONFIG_EXT_REFS
......@@ -1300,7 +1547,7 @@ int vp10_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
if (rfs == GOLDEN_FRAME)
pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
else if (rfs == ALTREF_FRAME)
else if (rfs != GOLDEN_FRAME && rfs != LAST_FRAME)
pred_context = crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME;
else
pred_context = 1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
......@@ -1312,8 +1559,8 @@ int vp10_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
: above0;
pred_context = 4 * (edge0 == GOLDEN_FRAME);
} else {
pred_context = 2 * (above0 == GOLDEN_FRAME) +
2 * (left0 == GOLDEN_FRAME);
pred_context =
2 * (above0 == GOLDEN_FRAME) + 2 * (left0 == GOLDEN_FRAME);
}
}
}
......@@ -1335,4 +1582,105 @@ int vp10_get_pred_context_single_ref_p2(const MACROBLOCKD *xd) {
return pred_context;
}
#if CONFIG_BIDIR_PRED
#define CHECK_BWDREF_OR_ALTREF(ref_frame) \
((ref_frame == BWDREF_FRAME) || (ref_frame == ALTREF_FRAME))
// For the bit to signal whether the single reference is ALTREF_FRAME or
// BWDREF_FRAME, knowing that it shall be either of these 2 choices.
//
// NOTE(zoeliu): The probability of ref_frame[0] is ALTREF_FRAME, conditioning
// on it is either ALTREF_FRAME or BWDREF_FRAME.
int vp10_get_pred_context_single_ref_p3(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 has_above = xd->up_available;
const int has_left = 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.
if (has_above && has_left) { // 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 or inter/intra
const MB_MODE_INFO *edge_mbmi = above_intra ? left_mbmi : above_mbmi;
if (!has_second_ref(edge_mbmi)) {
if (!CHECK_BWDREF_OR_ALTREF(edge_mbmi->ref_frame[0]))
pred_context = 3;
else
pred_context = 4 * (edge_mbmi->ref_frame[0] == BWDREF_FRAME);
} else {
pred_context = 1 +
2 * (edge_mbmi->ref_frame[0] == BWDREF_FRAME ||
edge_mbmi->ref_frame[1] == BWDREF_FRAME);
}
} else { // inter/inter
const int above_has_second = has_second_ref(above_mbmi);
const int left_has_second = has_second_ref(left_mbmi);
const MV_REFERENCE_FRAME above0 = above_mbmi->ref_frame[0];
const MV_REFERENCE_FRAME above1 = above_mbmi->ref_frame[1];
const MV_REFERENCE_FRAME left0 = left_mbmi->ref_frame[0];
const MV_REFERENCE_FRAME left1 = left_mbmi->ref_frame[1];
if (above_has_second && left_has_second) {
if (above0 == left0 && above1 == left1)
pred_context =
3 * (above0 == BWDREF_FRAME || above1 == BWDREF_FRAME ||
left0 == BWDREF_FRAME || left1 == BWDREF_FRAME);
else
pred_context = 2;
} else if (above_has_second || left_has_second) {
const MV_REFERENCE_FRAME srf = !above_has_second ? above0 : left0;
const MV_REFERENCE_FRAME crf0 = above_has_second ? above0 : left0;
const MV_REFERENCE_FRAME crf1 = above_has_second ? above1 : left1;
if (srf == BWDREF_FRAME)
pred_context = 3 + (crf0 == BWDREF_FRAME || crf0 == BWDREF_FRAME);
else if (srf == ALTREF_FRAME)
pred_context = (crf0 == BWDREF_FRAME || crf1 == BWDREF_FRAME);
else
pred_context = 1 + 2 * (crf0 == BWDREF_FRAME || crf1 == BWDREF_FRAME);
} else {