Commit 3ec1601e authored by Zoe Liu's avatar Zoe Liu

Added 3 more reference frames for inter prediction.

Under the experiment of EXT_REFS: LAST2_FRAME, LAST3_FRAME, and
LAST4_FRAME.

Coding efficiency: derflr +1.601%; hevchr +1.895%
Speed: Encoder slowed down by ~75%

Change-Id: Ifeee5f049c2c1f7cb29bc897622ef88897082ecf
parent 0c8110ef
......@@ -65,9 +65,18 @@ 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
#define GOLDEN_FRAME 5
#define ALTREF_FRAME 6
#define MAX_REF_FRAMES 7
#else
#define GOLDEN_FRAME 2
#define ALTREF_FRAME 3
#define MAX_REF_FRAMES 4
#endif // CONFIG_EXT_REFS
typedef int8_t MV_REFERENCE_FRAME;
typedef struct {
......
......@@ -215,16 +215,33 @@ 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] = {
50, 126, 123, 221, 226
static const vpx_prob default_comp_ref_p[REF_CONTEXTS][COMP_REFS - 1] = {
#if CONFIG_EXT_REFS
// 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
{ 50 }, { 126 }, { 123 }, { 221 }, { 226 }
#endif // CONFIG_EXT_REFS
};
static const vpx_prob default_single_ref_p[REF_CONTEXTS][2] = {
static const vpx_prob default_single_ref_p[REF_CONTEXTS][SINGLE_REFS - 1] = {
#if CONFIG_EXT_REFS
{ 33, 16, 16, 16, 16 },
{ 77, 74, 74, 74, 74 },
{ 142, 142, 142, 142, 142 },
{ 172, 170, 170, 170, 170 },
{ 238, 247, 247, 247, 247 }
#else
{ 33, 16 },
{ 77, 74 },
{ 142, 142 },
{ 172, 170 },
{ 238, 247 }
#endif // CONFIG_EXT_REFS
};
static const struct tx_probs default_tx_probs = {
......@@ -1109,10 +1126,11 @@ void vp10_adapt_inter_frame_probs(VP10_COMMON *cm) {
fc->comp_inter_prob[i] = mode_mv_merge_probs(pre_fc->comp_inter_prob[i],
counts->comp_inter[i]);
for (i = 0; i < REF_CONTEXTS; i++)
fc->comp_ref_prob[i] = mode_mv_merge_probs(pre_fc->comp_ref_prob[i],
counts->comp_ref[i]);
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]);
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < 2; j++)
for (j = 0; j < (SINGLE_REFS - 1); j++)
fc->single_ref_prob[i][j] = mode_mv_merge_probs(
pre_fc->single_ref_prob[i][j], counts->single_ref[i][j]);
......@@ -1233,6 +1251,11 @@ static void set_default_lf_deltas(struct loopfilter *lf) {
lf->ref_deltas[INTRA_FRAME] = 1;
lf->ref_deltas[LAST_FRAME] = 0;
#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];
#endif // CONFIG_EXT_REFS
lf->ref_deltas[GOLDEN_FRAME] = -1;
lf->ref_deltas[ALTREF_FRAME] = -1;
......
......@@ -63,8 +63,8 @@ typedef struct frame_contexts {
vpx_prob inter_mode_probs[INTER_MODE_CONTEXTS][INTER_MODES - 1];
vpx_prob intra_inter_prob[INTRA_INTER_CONTEXTS];
vpx_prob comp_inter_prob[COMP_INTER_CONTEXTS];
vpx_prob single_ref_prob[REF_CONTEXTS][2];
vpx_prob comp_ref_prob[REF_CONTEXTS];
vpx_prob single_ref_prob[REF_CONTEXTS][SINGLE_REFS-1];
vpx_prob comp_ref_prob[REF_CONTEXTS][COMP_REFS-1];
struct tx_probs tx_probs;
#if CONFIG_VAR_TX
vpx_prob txfm_partition_prob[TXFM_PARTITION_CONTEXTS];
......@@ -96,8 +96,8 @@ typedef struct FRAME_COUNTS {
unsigned int inter_mode[INTER_MODE_CONTEXTS][INTER_MODES];
unsigned int intra_inter[INTRA_INTER_CONTEXTS][2];
unsigned int comp_inter[COMP_INTER_CONTEXTS][2];
unsigned int single_ref[REF_CONTEXTS][2][2];
unsigned int comp_ref[REF_CONTEXTS][2];
unsigned int single_ref[REF_CONTEXTS][SINGLE_REFS-1][2];
unsigned int comp_ref[REF_CONTEXTS][COMP_REFS-1][2];
struct tx_counts tx;
#if CONFIG_VAR_TX
unsigned int txfm_partition[TXFM_PARTITION_CONTEXTS][2];
......
......@@ -123,8 +123,16 @@ typedef enum {
typedef enum {
VP9_LAST_FLAG = 1 << 0,
#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_ALT_FLAG = 1 << 5,
#else
VP9_GOLD_FLAG = 1 << 1,
VP9_ALT_FLAG = 1 << 2,
#endif // CONFIG_EXT_REFS
} VP9_REFFRAME;
typedef enum {
......@@ -210,6 +218,14 @@ typedef uint8_t PREDICTION_MODE;
typedef TX_SIZE TXFM_CONTEXT;
#endif
#if CONFIG_EXT_REFS
#define SINGLE_REFS 6
#define COMP_REFS 5
#else
#define SINGLE_REFS 3
#define COMP_REFS 2
#endif // CONFIG_EXT_REFS
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -43,7 +43,8 @@ struct loopfilter {
uint8_t mode_ref_delta_enabled;
uint8_t mode_ref_delta_update;
// 0 = Intra, Last, GF, ARF
// 0 = Intra, Last, Last2+Last3+LAST4(CONFIG_EXT_REFS),
// GF, ARF
signed char ref_deltas[MAX_REF_FRAMES];
signed char last_ref_deltas[MAX_REF_FRAMES];
......
......@@ -174,6 +174,12 @@ typedef struct VP10Common {
#endif
FRAME_TYPE last_frame_type; /* last frame's frame type for motion search.*/
#if CONFIG_EXT_REFS
// frame type of the frame before last frame
FRAME_TYPE last2_frame_type;
// frame type of the frame two frames before last frame
FRAME_TYPE last3_frame_type;
#endif // CONFIG_EXT_REFS
FRAME_TYPE frame_type;
int show_frame;
......@@ -260,7 +266,7 @@ typedef struct VP10Common {
// Context probabilities for reference frame prediction
MV_REFERENCE_FRAME comp_fixed_ref;
MV_REFERENCE_FRAME comp_var_ref[2];
MV_REFERENCE_FRAME comp_var_ref[COMP_REFS];
REFERENCE_MODE reference_mode;
FRAME_CONTEXT *fc; /* this frame entropy */
......
This diff is collapsed.
......@@ -87,25 +87,77 @@ int vp10_get_pred_context_comp_ref_p(const VP10_COMMON *cm,
const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_comp_ref_p(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
const MACROBLOCKD *xd) {
const int pred_context = vp10_get_pred_context_comp_ref_p(cm, xd);
return cm->fc->comp_ref_prob[pred_context];
return cm->fc->comp_ref_prob[pred_context][0];
}
#if CONFIG_EXT_REFS
int vp10_get_pred_context_comp_ref_p1(const VP10_COMMON *cm,
const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_comp_ref_p1(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
const int pred_context = vp10_get_pred_context_comp_ref_p1(cm, xd);
return cm->fc->comp_ref_prob[pred_context][1];
}
int vp10_get_pred_context_comp_ref_p2(const VP10_COMMON *cm,
const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_comp_ref_p2(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
const int pred_context = vp10_get_pred_context_comp_ref_p2(cm, xd);
return cm->fc->comp_ref_prob[pred_context][2];
}
int vp10_get_pred_context_comp_ref_p3(const VP10_COMMON *cm,
const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_comp_ref_p3(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
const int pred_context = vp10_get_pred_context_comp_ref_p3(cm, xd);
return cm->fc->comp_ref_prob[pred_context][3];
}
#endif // CONFIG_EXT_REFS
int vp10_get_pred_context_single_ref_p1(const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_single_ref_p1(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
const MACROBLOCKD *xd) {
return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p1(xd)][0];
}
int vp10_get_pred_context_single_ref_p2(const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_single_ref_p2(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
const MACROBLOCKD *xd) {
return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p2(xd)][1];
}
#if CONFIG_EXT_REFS
int vp10_get_pred_context_single_ref_p3(const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_single_ref_p3(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p3(xd)][2];
}
int vp10_get_pred_context_single_ref_p4(const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_single_ref_p4(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p4(xd)][3];
}
int vp10_get_pred_context_single_ref_p5(const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_single_ref_p5(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p5(xd)][4];
}
#endif // CONFIG_EXT_REFS
// Returns a context number for the given MB prediction signal
// The mode info data structure has a one element border above and to the
// left of the entries corresponding to real blocks.
......
......@@ -379,13 +379,14 @@ void vp10_accumulate_frame_counts(VP10_COMMON *cm, FRAME_COUNTS *counts,
cm->counts.comp_inter[i][j] += counts->comp_inter[i][j];
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < 2; j++)
for (j = 0; j < (SINGLE_REFS - 1); j++)
for (k = 0; k < 2; k++)
cm->counts.single_ref[i][j][k] += counts->single_ref[i][j][k];
cm->counts.single_ref[i][j][k] += counts->single_ref[i][j][k];
for (i = 0; i < REF_CONTEXTS; i++)
for (j = 0; j < 2; j++)
cm->counts.comp_ref[i][j] += counts->comp_ref[i][j];
for (j = 0; j < (COMP_REFS - 1); j++)
for (k = 0; k < 2; k++)
cm->counts.comp_ref[i][j][k] += counts->comp_ref[i][j][k];
for (i = 0; i < TX_SIZE_CONTEXTS; i++) {
for (j = 0; j < TX_SIZES; j++)
......
......@@ -61,13 +61,26 @@ static void setup_compound_reference_mode(VP10_COMMON *cm) {
cm->ref_frame_sign_bias[GOLDEN_FRAME]) {
cm->comp_fixed_ref = ALTREF_FRAME;
cm->comp_var_ref[0] = LAST_FRAME;
#if CONFIG_EXT_REFS
cm->comp_var_ref[1] = LAST2_FRAME;
cm->comp_var_ref[2] = LAST3_FRAME;
cm->comp_var_ref[3] = LAST4_FRAME;
cm->comp_var_ref[4] = GOLDEN_FRAME;
#else
cm->comp_var_ref[1] = GOLDEN_FRAME;
#endif // CONFIG_EXT_REFS
} else if (cm->ref_frame_sign_bias[LAST_FRAME] ==
cm->ref_frame_sign_bias[ALTREF_FRAME]) {
#if CONFIG_EXT_REFS
assert(0);
#endif // CONFIG_EXT_REFS
cm->comp_fixed_ref = GOLDEN_FRAME;
cm->comp_var_ref[0] = LAST_FRAME;
cm->comp_var_ref[1] = ALTREF_FRAME;
} else {
#if CONFIG_EXT_REFS
assert(0);
#endif // CONFIG_EXT_REFS
cm->comp_fixed_ref = LAST_FRAME;
cm->comp_var_ref[0] = GOLDEN_FRAME;
cm->comp_var_ref[1] = ALTREF_FRAME;
......@@ -130,21 +143,27 @@ static REFERENCE_MODE read_frame_reference_mode(const VP10_COMMON *cm,
static void read_frame_reference_mode_probs(VP10_COMMON *cm, vpx_reader *r) {
FRAME_CONTEXT *const fc = cm->fc;
int i;
int i, j;
if (cm->reference_mode == REFERENCE_MODE_SELECT)
for (i = 0; i < COMP_INTER_CONTEXTS; ++i)
vp10_diff_update_prob(r, &fc->comp_inter_prob[i]);
if (cm->reference_mode != COMPOUND_REFERENCE)
if (cm->reference_mode != COMPOUND_REFERENCE) {
for (i = 0; i < REF_CONTEXTS; ++i) {
vp10_diff_update_prob(r, &fc->single_ref_prob[i][0]);
vp10_diff_update_prob(r, &fc->single_ref_prob[i][1]);
for (j = 0; j < (SINGLE_REFS - 1); ++j) {
vp10_diff_update_prob(r, &fc->single_ref_prob[i][j]);
}
}
}
if (cm->reference_mode != SINGLE_REFERENCE)
for (i = 0; i < REF_CONTEXTS; ++i)
vp10_diff_update_prob(r, &fc->comp_ref_prob[i]);
if (cm->reference_mode != SINGLE_REFERENCE) {
for (i = 0; i < REF_CONTEXTS; ++i) {
for (j = 0; j < (COMP_REFS - 1); ++j) {
vp10_diff_update_prob(r, &fc->comp_ref_prob[i][j]);
}
}
}
}
static void update_mv_probs(vpx_prob *p, int n, vpx_reader *r) {
......@@ -1938,6 +1957,10 @@ static size_t read_uncompressed_header(VP10Decoder *pbi,
int i, mask, ref_index = 0;
size_t sz;
#if CONFIG_EXT_REFS
cm->last3_frame_type = cm->last2_frame_type;
cm->last2_frame_type = cm->last_frame_type;
#endif // CONFIG_EXT_REFS
cm->last_frame_type = cm->frame_type;
cm->last_intra_only = cm->intra_only;
......@@ -2106,20 +2129,70 @@ static size_t read_uncompressed_header(VP10Decoder *pbi,
// Generate next_ref_frame_map.
lock_buffer_pool(pool);
for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
#if CONFIG_EXT_REFS
// TODO(zoeliu): To move the following #define's to a header file
#define PBI_LST_FB_IDX 0
#define PBI_LST2_FB_IDX 1
#define PBI_LST3_FB_IDX 2
#define PBI_LST4_FB_IDX 3
#define PBI_GLD_FB_IDX 4
#define PBI_ALT_FB_IDX 5
// NOTE(zoeliu):
// (1) When ref_index == PBI_LST2_FB_IDX and the corresponding mask bit is
// set, it indicates that LAST2_FRAME shall be refreshed, but keep in
// mind that this has already been handled when LAST_FRAME is being
// refreshed, i.e., when ref_index == PBI_LST_FB_IDX and the mask bit
// is being set correspondingly;
// (2) The only exception is that when current frame is a KEY_FRAME, where
// all the frames in the frame buffer shall get refreshed;
// (3) Similar handling for when ref_index == PBI_LST3_FB_IDX or when
// ref_indx == PBI_LST4_FB_IDX.
if ((mask & 1) &&
(cm->frame_type == KEY_FRAME || (ref_index != PBI_LST2_FB_IDX &&
ref_index != PBI_LST3_FB_IDX &&
ref_index != PBI_LST4_FB_IDX))) {
// The reference frame map for the decoding of the next frame is updated
// and held by either current thread or possibly another decoder thread.
if (cm->frame_type != KEY_FRAME && ref_index == PBI_LST_FB_IDX &&
(mask & (1 << PBI_LST2_FB_IDX))) {
if (mask & (1 << PBI_LST3_FB_IDX)) {
if (mask & (1 << PBI_LST4_FB_IDX)) {
cm->next_ref_frame_map[PBI_LST4_FB_IDX] =
cm->next_ref_frame_map[PBI_LST3_FB_IDX];
++frame_bufs[cm->next_ref_frame_map[PBI_LST3_FB_IDX]].ref_count;
}
cm->next_ref_frame_map[PBI_LST3_FB_IDX] =
cm->next_ref_frame_map[PBI_LST2_FB_IDX];
++frame_bufs[cm->next_ref_frame_map[PBI_LST2_FB_IDX]].ref_count;
}
cm->next_ref_frame_map[PBI_LST2_FB_IDX] =
cm->next_ref_frame_map[PBI_LST_FB_IDX];
++frame_bufs[cm->next_ref_frame_map[PBI_LST_FB_IDX]].ref_count;
}
cm->next_ref_frame_map[ref_index] = cm->new_fb_idx;
++frame_bufs[cm->new_fb_idx].ref_count;
} else if (!(mask & 1)) {
cm->next_ref_frame_map[ref_index] = cm->ref_frame_map[ref_index];
}
#else
if (mask & 1) {
cm->next_ref_frame_map[ref_index] = cm->new_fb_idx;
++frame_bufs[cm->new_fb_idx].ref_count;
} else {
cm->next_ref_frame_map[ref_index] = cm->ref_frame_map[ref_index];
}
#endif // CONFIG_EXT_REFS
// Current thread holds the reference frame.
if (cm->ref_frame_map[ref_index] >= 0)
++frame_bufs[cm->ref_frame_map[ref_index]].ref_count;
++ref_index;
}
for (; ref_index < REF_FRAMES; ++ref_index) {
cm->next_ref_frame_map[ref_index] = cm->ref_frame_map[ref_index];
// Current thread holds the reference frame.
if (cm->ref_frame_map[ref_index] >= 0)
++frame_bufs[cm->ref_frame_map[ref_index]].ref_count;
......
......@@ -534,12 +534,68 @@ static void read_ref_frames(VP10_COMMON *const cm, MACROBLOCKD *const xd,
if (mode == COMPOUND_REFERENCE) {
const int idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
const int ctx = vp10_get_pred_context_comp_ref_p(cm, xd);
const int bit = vpx_read(r, fc->comp_ref_prob[ctx]);
const int bit = vpx_read(r, fc->comp_ref_prob[ctx][0]);
if (counts)
++counts->comp_ref[ctx][bit];
++counts->comp_ref[ctx][0][bit];
ref_frame[idx] = cm->comp_fixed_ref;
#if CONFIG_EXT_REFS
if (!bit) {
const int ctx1 = vp10_get_pred_context_comp_ref_p1(cm, xd);
const int bit1 = vpx_read(r, fc->comp_ref_prob[ctx1][1]);
if (counts)
++counts->comp_ref[ctx1][1][bit1];
ref_frame[!idx] = cm->comp_var_ref[bit1 ? 0 : 1];
} else {
const int ctx2 = vp10_get_pred_context_comp_ref_p2(cm, xd);
const int bit2 = vpx_read(r, fc->comp_ref_prob[ctx2][2]);
if (counts)
++counts->comp_ref[ctx2][2][bit2];
if (!bit2) {
const int ctx3 = vp10_get_pred_context_comp_ref_p3(cm, xd);
const int bit3 = vpx_read(r, fc->comp_ref_prob[ctx3][3]);
if (counts)
++counts->comp_ref[ctx3][3][bit3];
ref_frame[!idx] = cm->comp_var_ref[bit3 ? 2 : 3];
} else {
ref_frame[!idx] = cm->comp_var_ref[4];
}
}
#else
ref_frame[!idx] = cm->comp_var_ref[bit];
#endif // CONFIG_EXT_REFS
} else if (mode == SINGLE_REFERENCE) {
#if CONFIG_EXT_REFS
const int ctx0 = vp10_get_pred_context_single_ref_p1(xd);
const int bit0 = vpx_read(r, fc->single_ref_prob[ctx0][0]);
if (counts)
++counts->single_ref[ctx0][0][bit0];
if (bit0) {
const int ctx1 = vp10_get_pred_context_single_ref_p2(xd);
const int bit1 = vpx_read(r, fc->single_ref_prob[ctx1][1]);
if (counts)
++counts->single_ref[ctx1][1][bit1];
ref_frame[0] = bit1 ? ALTREF_FRAME : GOLDEN_FRAME;
} else {
const int ctx2 = vp10_get_pred_context_single_ref_p3(xd);
const int bit2 = vpx_read(r, fc->single_ref_prob[ctx2][2]);
if (counts)
++counts->single_ref[ctx2][2][bit2];
if (bit2) {
const int ctx4 = vp10_get_pred_context_single_ref_p5(xd);
const int bit4 = vpx_read(r, fc->single_ref_prob[ctx4][4]);
if (counts)
++counts->single_ref[ctx4][4][bit4];
ref_frame[0] = bit4 ? LAST4_FRAME : LAST3_FRAME;
} else {
const int ctx3 = vp10_get_pred_context_single_ref_p4(xd);
const int bit3 = vpx_read(r, fc->single_ref_prob[ctx3][3]);
if (counts)
++counts->single_ref[ctx3][3][bit3];
ref_frame[0] = bit3 ? LAST2_FRAME : LAST_FRAME;
}
}
#else
const int ctx0 = vp10_get_pred_context_single_ref_p1(xd);
const int bit0 = vpx_read(r, fc->single_ref_prob[ctx0][0]);
if (counts)
......@@ -553,6 +609,7 @@ static void read_ref_frames(VP10_COMMON *const cm, MACROBLOCKD *const xd,
} else {
ref_frame[0] = LAST_FRAME;
}
#endif // CONFIG_EXT_REFS
ref_frame[1] = NONE;
} else {
......
......@@ -196,10 +196,23 @@ vpx_codec_err_t vp10_set_reference_dec(VP10_COMMON *cm,
// later commit that adds VP9-specific controls for this functionality.
if (ref_frame_flag == VP9_LAST_FLAG) {
ref_buf = &cm->frame_refs[0];
#if CONFIG_EXT_REFS
} else if (ref_frame_flag == VP9_LAST2_FLAG) {
ref_buf = &cm->frame_refs[1];
} else if (ref_frame_flag == VP9_LAST3_FLAG) {
ref_buf = &cm->frame_refs[2];
} else if (ref_frame_flag == VP9_LAST4_FLAG) {
ref_buf = &cm->frame_refs[3];
} else if (ref_frame_flag == VP9_GOLD_FLAG) {
ref_buf = &cm->frame_refs[4];
} else if (ref_frame_flag == VP9_ALT_FLAG) {
ref_buf = &cm->frame_refs[5];
#else
} else if (ref_frame_flag == VP9_GOLD_FLAG) {
ref_buf = &cm->frame_refs[1];
} else if (ref_frame_flag == VP9_ALT_FLAG) {
ref_buf = &cm->frame_refs[2];
#endif // CONFIG_EXT_REFS
} else {
vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
"Invalid reference frame");
......@@ -243,10 +256,10 @@ static void swap_frame_buffers(VP10Decoder *pbi) {
// Current thread releases the holding of reference frame.
decrease_ref_count(old_idx, frame_bufs, pool);
// Release the reference frame in reference map.
if ((mask & 1) && old_idx >= 0) {
// Release the reference frame holding in the reference map for the decoding
// of the next frame.
if (mask & 1)
decrease_ref_count(old_idx, frame_bufs, pool);
}
cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
++ref_index;
}
......@@ -268,7 +281,7 @@ static void swap_frame_buffers(VP10Decoder *pbi) {
}
// Invalidate these references until the next frame starts.
for (ref_index = 0; ref_index < 3; ref_index++)
for (ref_index = 0; ref_index < REFS_PER_FRAME; ref_index++)
cm->frame_refs[ref_index].idx = -1;
}
......@@ -326,7 +339,6 @@ int vp10_receive_compressed_data(VP10Decoder *pbi,
pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
}
if (setjmp(cm->error.jmp)) {
const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
int i;
......@@ -350,10 +362,10 @@ int vp10_receive_compressed_data(VP10Decoder *pbi,
// Current thread releases the holding of reference frame.
decrease_ref_count(old_idx, frame_bufs, pool);
// Release the reference frame in reference map.
if ((mask & 1) && old_idx >= 0) {
// Release the reference frame holding in the reference map for the
// decoding of the next frame.
if (mask & 1)
decrease_ref_count(old_idx, frame_bufs, pool);
}
++ref_index;
}
......
......@@ -484,15 +484,58 @@ static void write_ref_frames(const VP10_COMMON *cm, const MACROBLOCKD *xd,
}
if (is_compound) {
vpx_write(w, mbmi->ref_frame[0] == GOLDEN_FRAME,
vp10_get_pred_prob_comp_ref_p(cm, xd));
#if CONFIG_EXT_REFS
const int bit = (mbmi->ref_frame[0] == GOLDEN_FRAME ||
mbmi->ref_frame[0] == LAST3_FRAME ||
mbmi->ref_frame[0] == LAST4_FRAME);
#else
const int bit = mbmi->ref_frame[0] == GOLDEN_FRAME;
#endif // CONFIG_EXT_REFS
vpx_write(w, bit, vp10_get_pred_prob_comp_ref_p(cm, xd));
#if CONFIG_EXT_REFS
if (!bit) {
const int bit1 = mbmi->ref_frame[0] == LAST_FRAME;
vpx_write(w, bit1, vp10_get_pred_prob_comp_ref_p1(cm, xd));
} else {
const int bit2 = mbmi->ref_frame[0] == GOLDEN_FRAME;
vpx_write(w, bit2, vp10_get_pred_prob_comp_ref_p2(cm, xd));
if (!bit2) {
const int bit3 = mbmi->ref_frame[0] == LAST3_FRAME;
vpx_write(w, bit3, vp10_get_pred_prob_comp_ref_p3(cm, xd));
}
}
#endif // CONFIG_EXT_REFS
} else {
#if CONFIG_EXT_REFS
const int bit0 = (mbmi->ref_frame[0] == GOLDEN_FRAME ||
mbmi->ref_frame[0] == ALTREF_FRAME);
vpx_write(w, bit0, vp10_get_pred_prob_single_ref_p1(cm, xd));
if (bit0) {
const int bit1 = mbmi->ref_frame[0] != GOLDEN_FRAME;
vpx_write(w, bit1, vp10_get_pred_prob_single_ref_p2(cm, xd));
} else {
const int bit2 = (mbmi->ref_frame[0] == LAST3_FRAME ||
mbmi->ref_frame[0] == LAST4_FRAME);
vpx_write(w, bit2, vp10_get_pred_prob_single_ref_p3(cm, xd));
if (!bit2) {
const int bit3 = mbmi->ref_frame[0] != LAST_FRAME;
vpx_write(w, bit3, vp10_get_pred_prob_single_ref_p4(cm, xd));
} else {
const int bit4 = mbmi->ref_frame[0] != LAST3_FRAME;
vpx_write(w, bit4, vp10_get_pred_prob_single_ref_p5(cm, xd));
}
}
#else
const int bit0 = mbmi->ref_frame[0] != LAST_FRAME;
vpx_write(w, bit0, vp10_get_pred_prob_single_ref_p1(cm, xd));
if (bit0) {
const int bit1 = mbmi->ref_frame[0] != GOLDEN_FRAME;
vpx_write(w, bit1, vp10_get_pred_prob_single_ref_p2(cm, xd));
}