Commit 5805a14c authored by Zoe Liu's avatar Zoe Liu

Merge bi-predictive frames to EXT_REFS

This patch removed the experiment of BIDIR_PRED and merged the feature
into the experiment of EXT_REFS:

(1) Each frame now has up to 6 reference frames, namely
    LAST_FRAME, LAST2_FRAME, LAST3_FRAME, GOLDEN_FRAME, (forward) and
    BWDREF_FRAME, ALTREF_FRAME (backward);
    LAST4_FRAME has been removed;
(2) First pass still keeps the 8 updates:
    KF_UPDATE, LF_UPDATE, GF_UPDATE, ARF_UPDATE, OVERLAY_UPDATE, and
    BRF_UPDATE, LAST_BIPRED_UPDATE, BI_PRED_UPDATE;
(3) show_existing_frame==1 is supported in the experiment of EXT_REFS;
(4) New encoding modes are added for both single-ref and compound cases,
    through the use of the 2 extra forward references (LAST2 & LAST3)
    and the 1 extra backward reference (BWDREF).

RD performance wise, using Overall PSNR: Avg/BDRate
        Bipred only      Prev EXT_REFS    Current EXT_REFS with bipred
lowres: -3.474/-3.324    -1.748/-1.586    -4.613/-4.387
derflr: -2.097/-1.353    -1.439/-1.215    -3.120/-2.252
midres: -2.129/-1.901    -1.345/-1.185    -2.898/-2.636

If in vp10/encoder/firstpass.h, change BFG_INTERVAL from 2 to 3, i.e. to
use 2 bi-predictive frames than 1, a further improvement may be
obtained:
                 Current EXT_REFS with bipred
        1 bi-predictive frame    2 bi-predictive frames
lowres: -4.613/-4.387            -4.675/-4.465
derflr: -3.120/-2.252            -3.333/-2.516
midres: -2.898/-2.636            -3.406/-3.095

Change-Id: Ib06fe9ea0a5cfd7418a1d79b978ee9d80bf191cb
parent 019dbb4c
......@@ -102,29 +102,18 @@ typedef struct {
#define LAST2_FRAME 2
#define LAST3_FRAME 3
#define LAST4_FRAME 4
#define GOLDEN_FRAME 5
#define GOLDEN_FRAME 4
#define BWDREF_FRAME 5
#define ALTREF_FRAME 6
#define MAX_REF_FRAMES 7
#define LAST_REF_FRAMES (LAST4_FRAME - LAST_FRAME + 1)
#define LAST_REF_FRAMES (LAST3_FRAME - LAST_FRAME + 1)
#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
#else
#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;
......
......@@ -428,32 +428,21 @@ static const vpx_prob default_comp_inter_p[COMP_INTER_CONTEXTS] = {
#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 // 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 }
// TODO(zoeliu): To adjust the initial prob values.
{ 33, 16, 16 },
{ 77, 74, 74 },
{ 142, 142, 142 },
{ 172, 170, 170 },
{ 238, 247, 247 }
};
static const vpx_prob default_comp_bwdref_p[REF_CONTEXTS][BWD_REFS - 1] = {
{ 16 }, { 74 }, { 142 }, { 170 }, { 247 }
};
#else // CONFIG_BIDIR_PRED
#else
static const vpx_prob default_comp_ref_p[REF_CONTEXTS][COMP_REFS - 1] = {
{ 50 }, { 126 }, { 123 }, { 221 }, { 226 }
};
#endif // CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
static const vpx_prob default_single_ref_p[REF_CONTEXTS][SINGLE_REFS - 1] = {
......@@ -463,20 +452,12 @@ 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 // 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
#else
{ 33, 16 },
{ 77, 74 },
{ 142, 142 },
{ 172, 170 },
{ 238, 247 }
#endif // CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
};
......@@ -1311,9 +1292,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
#if CONFIG_EXT_REFS
vp10_copy(fc->comp_bwdref_prob, default_comp_bwdref_p);
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
vp10_copy(fc->single_ref_prob, default_single_ref_p);
vp10_copy(fc->tx_size_probs, default_tx_size_prob);
#if CONFIG_VAR_TX
......@@ -1382,7 +1363,7 @@ void vp10_adapt_inter_frame_probs(VP10_COMMON *cm) {
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
#if CONFIG_EXT_REFS
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(
......@@ -1396,7 +1377,7 @@ void vp10_adapt_inter_frame_probs(VP10_COMMON *cm) {
for (j = 0; j < (COMP_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]);
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < (SINGLE_REFS - 1); j++)
......@@ -1599,7 +1580,7 @@ static void set_default_lf_deltas(struct loopfilter *lf) {
#if CONFIG_EXT_REFS
lf->ref_deltas[LAST2_FRAME] = lf->ref_deltas[LAST_FRAME];
lf->ref_deltas[LAST3_FRAME] = lf->ref_deltas[LAST_FRAME];
lf->ref_deltas[LAST4_FRAME] = lf->ref_deltas[LAST_FRAME];
lf->ref_deltas[BWDREF_FRAME] = lf->ref_deltas[LAST_FRAME];
#endif // CONFIG_EXT_REFS
lf->ref_deltas[GOLDEN_FRAME] = -1;
lf->ref_deltas[ALTREF_FRAME] = -1;
......
......@@ -85,12 +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
#if CONFIG_EXT_REFS
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
#endif // CONFIG_EXT_REFS
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];
......@@ -160,12 +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
#if CONFIG_EXT_REFS
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
#endif // CONFIG_EXT_REFS
unsigned int tx_size_totals[TX_SIZES];
unsigned int tx_size[TX_SIZES - 1][TX_SIZE_CONTEXTS][TX_SIZES];
#if CONFIG_VAR_TX
......
......@@ -204,21 +204,14 @@ typedef enum {
#if CONFIG_EXT_REFS
VP9_LAST2_FLAG = 1 << 1,
VP9_LAST3_FLAG = 1 << 2,
VP9_LAST4_FLAG = 1 << 3,
VP9_GOLD_FLAG = 1 << 4,
VP9_GOLD_FLAG = 1 << 3,
VP9_BWD_FLAG = 1 << 4,
VP9_ALT_FLAG = 1 << 5,
VP9_REFFRAME_ALL = (1 << 6) - 1
#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
#else
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;
......@@ -389,24 +382,14 @@ typedef TX_SIZE TXFM_CONTEXT;
#endif
#if CONFIG_EXT_REFS
#define SINGLE_REFS 6
#define COMP_REFS 5
#else // CONFIG_EXT_REFS
#if CONFIG_BIDIR_PRED
#define FWD_REFS 2
#define FWD_REFS 4
#define BWD_REFS 2
#define SINGLE_REFS (FWD_REFS + BWD_REFS)
#define COMP_REFS (FWD_REFS * BWD_REFS)
#else // CONFIG_BIDIR_PRED
// NOTE(zoeliu): Following parameter is currently not being used
// #define COMP_REFS (FWD_REFS * BWD_REFS)
#else
#define SINGLE_REFS 3
#define COMP_REFS 2
#endif // CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
#if CONFIG_SUPERTX
......
......@@ -44,8 +44,8 @@ struct loopfilter {
uint8_t mode_ref_delta_enabled;
uint8_t mode_ref_delta_update;
// 0 = Intra, Last, Last2+Last3+LAST4(CONFIG_EXT_REFS),
// GF, BRF(CONFIG_BIDIR_PRED), ARF
// 0 = Intra, Last, Last2+Last3(CONFIG_EXT_REFS),
// GF, BRF(CONFIG_EXT_REFS), ARF
signed char ref_deltas[MAX_REF_FRAMES];
signed char last_ref_deltas[MAX_REF_FRAMES];
......
......@@ -178,6 +178,7 @@ typedef struct VP10Common {
#if CONFIG_EXT_REFS
// frame type of the frame before last frame
FRAME_TYPE last2_frame_type;
// TODO(zoeliu): To check whether last3_frame_type is still needed.
// frame type of the frame two frames before last frame
FRAME_TYPE last3_frame_type;
#endif // CONFIG_EXT_REFS
......@@ -186,10 +187,10 @@ typedef struct VP10Common {
int show_frame;
int last_show_frame;
int show_existing_frame;
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#if CONFIG_EXT_REFS
// Flag for a frame used as a reference - not written to the bitstream
int is_reference_frame;
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
// Flag signaling that the frame is encoded using only INTRA modes.
uint8_t intra_only;
......@@ -278,13 +279,13 @@ typedef struct VP10Common {
int frame_parallel_decode; // frame-based threading.
// Context probabilities for reference frame prediction
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#if CONFIG_EXT_REFS
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
#endif // CONFIG_EXT_REFS
REFERENCE_MODE reference_mode;
FRAME_CONTEXT *fc; /* this frame entropy */
......
......@@ -177,10 +177,10 @@ int vp10_get_intra_inter_context(const MACROBLOCKD *xd) {
}
}
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#if CONFIG_EXT_REFS
#define CHECK_COMP_BWD_REF(ref_frame) \
(((ref_frame) == cm->comp_bwd_ref[0]) || ((ref_frame) == cm->comp_bwd_ref[1]))
#define CHECK_BWDREF_OR_ALTREF(ref_frame) \
(((ref_frame) == BWDREF_FRAME) || ((ref_frame) == ALTREF_FRAME))
int vp10_get_reference_mode_context(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
......@@ -189,6 +189,9 @@ int vp10_get_reference_mode_context(const VP10_COMMON *cm,
const MB_MODE_INFO *const left_mbmi = xd->left_mbmi;
const int has_above = xd->up_available;
const int has_left = xd->left_available;
(void)cm;
// Note:
// The mode info data structure has a one element border above and to the
// left of the entries corresponding to real macroblocks.
......@@ -196,15 +199,15 @@ int vp10_get_reference_mode_context(const VP10_COMMON *cm,
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]);
ctx = CHECK_BWDREF_OR_ALTREF(above_mbmi->ref_frame[0]) ^
CHECK_BWDREF_OR_ALTREF(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]) ||
ctx = 2 + (CHECK_BWDREF_OR_ALTREF(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]) ||
ctx = 2 + (CHECK_BWDREF_OR_ALTREF(left_mbmi->ref_frame[0]) ||
!is_inter_block(left_mbmi));
else // both edges use comp pred (4)
ctx = 4;
......@@ -213,7 +216,7 @@ int vp10_get_reference_mode_context(const VP10_COMMON *cm,
if (!has_second_ref(edge_mbmi))
// edge does not use comp pred (0/1)
ctx = CHECK_COMP_BWD_REF(edge_mbmi->ref_frame[0]);
ctx = CHECK_BWDREF_OR_ALTREF(edge_mbmi->ref_frame[0]);
else
// edge uses comp pred (3)
ctx = 3;
......@@ -224,7 +227,7 @@ int vp10_get_reference_mode_context(const VP10_COMMON *cm,
return ctx;
}
#else // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#else // CONFIG_EXT_REFS
int vp10_get_reference_mode_context(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
......@@ -268,26 +271,25 @@ int vp10_get_reference_mode_context(const VP10_COMMON *cm,
return ctx;
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
#if CONFIG_EXT_REFS
// TODO(zoeliu): Future work will be conducted to optimize the context design
// for the coding of the reference frames.
// for the coding of the reference frames.
#define CHECK_LAST_OR_LAST2(ref_frame) \
((ref_frame == LAST_FRAME) || (ref_frame == LAST2_FRAME))
#define CHECK_GOLDEN_LAST3_LAST4(ref_frame) \
((ref_frame == GOLDEN_FRAME) || (ref_frame == LAST3_FRAME) || \
(ref_frame == LAST4_FRAME))
#define CHECK_GOLDEN_OR_LAST3(ref_frame) \
((ref_frame == GOLDEN_FRAME) || (ref_frame == LAST3_FRAME))
// Returns a context number for the given MB prediction signal
// Signal the first reference frame for a compound mode is either
// GOLDEN/LAST3/LAST4, or LAST/LAST2.
// 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/LAST3_FRAME/LAST4_FRAME.
// GOLDEN_FRAME or LAST3_FRAME.
int vp10_get_pred_context_comp_ref_p(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
int pred_context;
......@@ -300,8 +302,8 @@ int vp10_get_pred_context_comp_ref_p(const VP10_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.
const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
const int var_ref_idx = !fix_ref_idx;
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);
......@@ -314,51 +316,46 @@ int vp10_get_pred_context_comp_ref_p(const VP10_COMMON *cm,
if (!has_second_ref(edge_mbmi)) // single pred (1/3)
pred_context = 1 +
2 * (!CHECK_GOLDEN_LAST3_LAST4(edge_mbmi->ref_frame[0]));
2 * (!CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[0]));
else // comp pred (1/3)
pred_context = 1 +
2 * (!CHECK_GOLDEN_LAST3_LAST4(edge_mbmi->ref_frame[var_ref_idx]));
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 vrfa = a_sg ? above_mbmi->ref_frame[0]
: above_mbmi->ref_frame[var_ref_idx];
const MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
: left_mbmi->ref_frame[var_ref_idx];
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 (vrfa == vrfl && CHECK_GOLDEN_LAST3_LAST4(vrfa)) {
if (frfa == frfl && CHECK_GOLDEN_OR_LAST3(frfa)) {
pred_context = 0;
} else if (l_sg && a_sg) { // single/single
if ((vrfa == ALTREF_FRAME && CHECK_LAST_OR_LAST2(vrfl)) ||
(vrfl == ALTREF_FRAME && CHECK_LAST_OR_LAST2(vrfa))) {
if ((CHECK_BWDREF_OR_ALTREF(frfa) && CHECK_LAST_OR_LAST2(frfl)) ||
(CHECK_BWDREF_OR_ALTREF(frfl) && CHECK_LAST_OR_LAST2(frfa))) {
pred_context = 4;
} else if (vrfa == vrfl || (CHECK_LAST_OR_LAST2(vrfa) &&
CHECK_LAST_OR_LAST2(vrfl))) {
pred_context = 3;
} else { // Either vrfa or vrfl is GOLDEN / LAST3 / LAST4
// NOTE(zoeliu): Following assert may be removed once confirmed.
assert(CHECK_GOLDEN_LAST3_LAST4(vrfa) ||
CHECK_GOLDEN_LAST3_LAST4(vrfl));
} 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 vrfc = l_sg ? vrfa : vrfl;
const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
const MV_REFERENCE_FRAME frfc = l_sg ? frfa : frfl;
const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
if (CHECK_GOLDEN_LAST3_LAST4(vrfc) && !CHECK_GOLDEN_LAST3_LAST4(rfs))
if (CHECK_GOLDEN_OR_LAST3(frfc) && !CHECK_GOLDEN_OR_LAST3(rfs))
pred_context = 1;
else if (CHECK_GOLDEN_LAST3_LAST4(rfs) &&
!CHECK_GOLDEN_LAST3_LAST4(vrfc))
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(vrfa) && CHECK_LAST_OR_LAST2(vrfl))) {
if ((CHECK_LAST_OR_LAST2(frfa) && CHECK_LAST_OR_LAST2(frfl))) {
pred_context = 4;
} else {
// NOTE(zoeliu): Following assert may be removed once confirmed.
assert(CHECK_GOLDEN_LAST3_LAST4(vrfa) ||
CHECK_GOLDEN_LAST3_LAST4(vrfl));
assert(CHECK_GOLDEN_OR_LAST3(frfa) || CHECK_GOLDEN_OR_LAST3(frfl));
pred_context = 2;
}
}
......@@ -370,10 +367,10 @@ int vp10_get_pred_context_comp_ref_p(const VP10_COMMON *cm,
pred_context = 2;
} else {
if (has_second_ref(edge_mbmi))
pred_context =
4 * (!CHECK_GOLDEN_LAST3_LAST4(edge_mbmi->ref_frame[var_ref_idx]));
pred_context = 4 *
(!CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[fwd_ref_sign_idx]));
else
pred_context = 3 * (!CHECK_GOLDEN_LAST3_LAST4(edge_mbmi->ref_frame[0]));
pred_context = 3 * (!CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[0]));
}
} else { // no edges available (2)
pred_context = 2;
......@@ -385,7 +382,7 @@ int vp10_get_pred_context_comp_ref_p(const VP10_COMMON *cm,
}
// Returns a context number for the given MB prediction signal
// Signal the first reference frame for a compound mode is LAST,
// 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,
......@@ -402,8 +399,8 @@ int vp10_get_pred_context_comp_ref_p1(const VP10_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.
const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
const int var_ref_idx = !fix_ref_idx;
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);
......@@ -417,45 +414,45 @@ int vp10_get_pred_context_comp_ref_p1(const VP10_COMMON *cm,
if (!has_second_ref(edge_mbmi)) // single pred (1/3)
pred_context = 1 + 2 * (edge_mbmi->ref_frame[0] != LAST_FRAME);
else // comp pred (1/3)
pred_context = 1 + 2 * (edge_mbmi->ref_frame[var_ref_idx]
pred_context = 1 + 2 * (edge_mbmi->ref_frame[fwd_ref_sign_idx]
!= LAST_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 vrfa = a_sg ? above_mbmi->ref_frame[0]
: above_mbmi->ref_frame[var_ref_idx];
const MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
: left_mbmi->ref_frame[var_ref_idx];
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 (vrfa == vrfl && vrfa == LAST_FRAME)
if (frfa == frfl && frfa == LAST_FRAME)
pred_context = 0;
else if (l_sg && a_sg) { // single/single
if (vrfa == LAST_FRAME || vrfl == LAST_FRAME)
if (frfa == LAST_FRAME || frfl == LAST_FRAME)
pred_context = 1;
else if (CHECK_GOLDEN_LAST3_LAST4(vrfa) ||
CHECK_GOLDEN_LAST3_LAST4(vrfl))
pred_context = 2 + (vrfa != vrfl);
else if (vrfa == vrfl)
else if (CHECK_GOLDEN_OR_LAST3(frfa) || CHECK_GOLDEN_OR_LAST3(frfl))
pred_context = 2 + (frfa != frfl);
else if (frfa == frfl ||
(CHECK_BWDREF_OR_ALTREF(frfa) && CHECK_BWDREF_OR_ALTREF(frfl)))
pred_context = 3;
else
pred_context = 4;
} else if (l_sg || a_sg) { // single/comp
const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
const MV_REFERENCE_FRAME frfc = l_sg ? frfa : frfl;
const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
if (vrfc == LAST_FRAME && rfs != LAST_FRAME)
if (frfc == LAST_FRAME && rfs != LAST_FRAME)
pred_context = 1;
else if (rfs == LAST_FRAME && vrfc != LAST_FRAME)
else if (rfs == LAST_FRAME && frfc != LAST_FRAME)
pred_context = 2;
else
pred_context = 3 +
(vrfc == LAST2_FRAME || CHECK_GOLDEN_LAST3_LAST4(rfs));
(frfc == LAST2_FRAME || CHECK_GOLDEN_OR_LAST3(rfs));
} else { // comp/comp
if (vrfa == LAST_FRAME || vrfl == LAST_FRAME)
if (frfa == LAST_FRAME || frfl == LAST_FRAME)
pred_context = 2;
else
pred_context = 3 + (CHECK_GOLDEN_LAST3_LAST4(vrfa) ||
CHECK_GOLDEN_LAST3_LAST4(vrfl));
pred_context = 3 +
(CHECK_GOLDEN_OR_LAST3(frfa) || CHECK_GOLDEN_OR_LAST3(frfl));
}
}
} else if (above_in_image || left_in_image) { // one edge available
......@@ -465,12 +462,13 @@ int vp10_get_pred_context_comp_ref_p1(const VP10_COMMON *cm,
pred_context = 2;
} else {
if (has_second_ref(edge_mbmi)) {
pred_context = 4 * (edge_mbmi->ref_frame[var_ref_idx] != LAST_FRAME);
pred_context = 4 *
(edge_mbmi->ref_frame[fwd_ref_sign_idx] != LAST_FRAME);
} else {
if (edge_mbmi->ref_frame[0] == LAST_FRAME)
pred_context = 0;
else
pred_context = 2 + CHECK_GOLDEN_LAST3_LAST4(edge_mbmi->ref_frame[0]);
pred_context = 2 + CHECK_GOLDEN_OR_LAST3(edge_mbmi->ref_frame[0]);
}
}
} else { // no edges available (2)
......@@ -482,15 +480,12 @@ int vp10_get_pred_context_comp_ref_p1(const VP10_COMMON *cm,
return pred_context;
}
#define CHECK_LAST3_OR_LAST4(ref_frame) \
((ref_frame == LAST3_FRAME) || (ref_frame == LAST4_FRAME))
// Returns a context number for the given MB prediction signal
// Signal the first reference frame for a compound mode is GOLDEN,
// conditioning on that it is known either GOLDEN/LAST3/LAST4.
// 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 / LAST3 / LAST4.
// conditioning on it is either GOLDEN or LAST3.
int vp10_get_pred_context_comp_ref_p2(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
int pred_context;
......@@ -503,8 +498,8 @@ int vp10_get_pred_context_comp_ref_p2(const VP10_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.
const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
const int var_ref_idx = !fix_ref_idx;
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);
......@@ -518,44 +513,45 @@ int vp10_get_pred_context_comp_ref_p2(const VP10_COMMON *cm,
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[var_ref_idx] != GOLDEN_FRAME);
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 vrfa = a_sg ? above_mbmi->ref_frame[0]
: above_mbmi->ref_frame[var_ref_idx];
const MV_REFERENCE_FRAME vrfl = l_sg ? left_mbmi->ref_frame[0]
: left_mbmi->ref_frame[var_ref_idx];
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 (vrfa == vrfl && vrfa == GOLDEN_FRAME)
if (frfa == frfl && frfa == GOLDEN_FRAME)
pred_context = 0;
else if (l_sg && a_sg) { // single/single
if (vrfa == GOLDEN_FRAME || vrfl == GOLDEN_FRAME)
if (frfa == GOLDEN_FRAME || frfl == GOLDEN_FRAME)
pred_context = 1;
else if (CHECK_LAST_OR_LAST2(vrfa) || CHECK_LAST_OR_LAST2(vrfl))
pred_context = 2 + (vrfa != vrfl);
else if (vrfa == vrfl)
else if (CHECK_LAST_OR_LAST2(frfa) || CHECK_LAST_OR_LAST2(frfl))
pred_context = 2 + (frfa != frfl);
else if (frfa == frfl ||
(CHECK_BWDREF_OR_ALTREF(frfa) && CHECK_BWDREF_OR_ALTREF(frfl)))
pred_context = 3;
else
pred_context = 4;
} else if (l_sg || a_sg) { // single/comp
const MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
const MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
const MV_REFERENCE_FRAME frfc = l_sg ? frfa : frfl;
const MV_REFERENCE_FRAME rfs = a_sg ? frfa : frfl;
if (vrfc == GOLDEN_FRAME && rfs != GOLDEN_FRAME)
if (frfc == GOLDEN_FRAME && rfs != GOLDEN_FRAME)
pred_context = 1;
else if (rfs == GOLDEN_FRAME && vrfc != GOLDEN_FRAME)
else if (rfs == GOLDEN_FRAME && frfc != GOLDEN_FRAME)
pred_context = 2;
else
pred_context = 3 +
(CHECK_LAST3_OR_LAST4(vrfc) || CHECK_LAST_OR_LAST2(rfs));
(frfc == LAST3_FRAME || CHECK_LAST_OR_LAST2(rfs));
} else { // comp/comp
if (vrfa == GOLDEN_FRAME || vrfl == GOLDEN_FRAME)
if (frfa == GOLDEN_FRAME || frfl == GOLDEN_FRAME)
pred_context = 2;
else
pred_context = 3 +
(CHECK_LAST_OR_LAST2(vrfa) || CHECK_LAST_OR_LAST2(vrfl));
(CHECK_LAST_OR_LAST2(frfa) || CHECK_LAST_OR_LAST2(frfl));
}
}
} else if (above_in_image || left_in_image) { // one edge available
......@@ -565,7 +561,8 @@ int vp10_get_pred_context_comp_ref_p2(const VP10_COMMON *cm,
pred_context = 2;
} else {
if (has_second_ref(edge_mbmi)) {
pred_context = 4 * (edge_mbmi->ref_frame[var_ref_idx] != GOLDEN_FRAME);
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;
......@@ -582,194 +579,6 @@ int vp10_get_pred_context_comp_ref_p2(const VP10_COMMON *cm,
return pred_context;
}
#define CHECK_LAST_LAST2_GOLDEN(ref_frame) \
((ref_frame == LAST_FRAME) || (ref_frame == LAST2_FRAME) || \
(ref_frame == GOLDEN_FRAME))
// Returns a context number for the given MB prediction signal
// Signal the first reference frame for a compound mode is LAST3,
// conditioning on that it is known either LAST3/LAST4.
//
// NOTE(zoeliu): The probability of ref_frame[0] is LAST3_FRAME,
// conditioning on it is either LAST3 / LAST4.
int vp10_get_pred_context_comp_ref_p3(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 correpsonding to real macroblocks.
// The prediction flags in these dummy entries are initialised to 0.
const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
const int var_ref_idx = !fix_ref_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] != LAST3_FRAME);
else // comp pred (1/3)
pred_context = 1 +