Commit cf5083d4 authored by Zoe Liu's avatar Zoe Liu

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 */
......
This diff is collapsed.
......@@ -87,7 +87,7 @@ int vp10_get_reference_mode_context(const VP10_COMMON *cm,
const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_reference_mode_prob(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
const MACROBLOCKD *xd) {
return cm->fc->comp_inter_prob[vp10_get_reference_mode_context(cm, xd)];
}
......@@ -127,6 +127,20 @@ static INLINE vpx_prob vp10_get_pred_prob_comp_ref_p3(const VP10_COMMON *cm,
const int pred_context = vp10_get_pred_context_comp_ref_p3(cm, xd);
return cm->fc->comp_ref_prob[pred_context][3];
}
#else // CONFIG_EXT_REFS
#if CONFIG_BIDIR_PRED
int vp10_get_pred_context_comp_bwdref_p(const VP10_COMMON *cm,
const MACROBLOCKD *xd);
static INLINE vpx_prob vp10_get_pred_prob_comp_bwdref_p(const VP10_COMMON *cm,
const MACROBLOCKD *xd) {
const int pred_context = vp10_get_pred_context_comp_bwdref_p(cm, xd);
return cm->fc->comp_bwdref_prob[pred_context][0];
}
#endif // CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
int vp10_get_pred_context_single_ref_p1(const MACROBLOCKD *xd);
......@@ -143,14 +157,16 @@ static INLINE vpx_prob vp10_get_pred_prob_single_ref_p2(const VP10_COMMON *cm,
return cm->fc->single_ref_prob[vp10_get_pred_context_single_ref_p2(xd)][1];
}
#if CONFIG_EXT_REFS
#if CONFIG_EXT_REFS || CONFIG_BIDIR_PRED
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];
}
#endif // CONFIG_EXT_REFS || CONFIR_BIDIR_PRED
#if CONFIG_EXT_REFS
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,
......
......@@ -57,6 +57,14 @@ static int is_compound_reference_allowed(const VP10_COMMON *cm) {
}
static void setup_compound_reference_mode(VP10_COMMON *cm) {
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
cm->comp_fwd_ref[0] = LAST_FRAME;
cm->comp_fwd_ref[1] = GOLDEN_FRAME;
cm->comp_bwd_ref[0] = BWDREF_FRAME;
cm->comp_bwd_ref[1] = ALTREF_FRAME;
#else // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
if (cm->ref_frame_sign_bias[LAST_FRAME] ==
cm->ref_frame_sign_bias[GOLDEN_FRAME]) {
cm->comp_fixed_ref = ALTREF_FRAME;
......@@ -66,7 +74,7 @@ static void setup_compound_reference_mode(VP10_COMMON *cm) {
cm->comp_var_ref[2] = LAST3_FRAME;
cm->comp_var_ref[3] = LAST4_FRAME;
cm->comp_var_ref[4] = GOLDEN_FRAME;
#else
#else // CONFIG_EXT_REFS
cm->comp_var_ref[1] = GOLDEN_FRAME;
#endif // CONFIG_EXT_REFS
} else if (cm->ref_frame_sign_bias[LAST_FRAME] ==
......@@ -85,6 +93,7 @@ static void setup_compound_reference_mode(VP10_COMMON *cm) {
cm->comp_var_ref[0] = GOLDEN_FRAME;
cm->comp_var_ref[1] = ALTREF_FRAME;
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
}
static int read_is_valid(const uint8_t *start, size_t len, const uint8_t *end) {
......@@ -171,9 +180,15 @@ static void read_frame_reference_mode_probs(VP10_COMMON *cm, vp10_reader *r) {
if (cm->reference_mode != SINGLE_REFERENCE) {
for (i = 0; i < REF_CONTEXTS; ++i) {
for (j = 0; j < (COMP_REFS - 1); ++j) {
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
for (j = 0; j < (FWD_REFS - 1); ++j)
vp10_diff_update_prob(r, &fc->comp_ref_prob[i][j]);
}
for (j = 0; j < (BWD_REFS - 1); ++j)
vp10_diff_update_prob(r, &fc->comp_bwdref_prob[i][j]);
#else
for (j = 0; j < (COMP_REFS - 1); ++j)
vp10_diff_update_prob(r, &fc->comp_ref_prob[i][j]);
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
}
}
}
......@@ -3049,6 +3064,11 @@ static size_t read_uncompressed_header(VP10Decoder *pbi,
cm->last_frame_type = cm->frame_type;
cm->last_intra_only = cm->intra_only;
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// NOTE: By default all coded frames to be used as a reference
cm->is_reference_frame = 1;
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
if (vpx_rb_read_literal(rb, 2) != VP9_FRAME_MARKER)
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Invalid frame marker");
......@@ -3065,9 +3085,11 @@ static size_t read_uncompressed_header(VP10Decoder *pbi,
#endif
cm->show_existing_frame = vpx_rb_read_bit(rb);
if (cm->show_existing_frame) {
// Show an existing frame directly.
const int frame_to_show = cm->ref_frame_map[vpx_rb_read_literal(rb, 3)];
lock_buffer_pool(pool);
if (frame_to_show < 0 || frame_bufs[frame_to_show].ref_count < 1) {
unlock_buffer_pool(pool);
......@@ -3075,17 +3097,72 @@ static size_t read_uncompressed_header(VP10Decoder *pbi,
"Buffer %d does not contain a decoded frame",
frame_to_show);
}
ref_cnt_fb(frame_bufs, &cm->new_fb_idx, frame_to_show);
unlock_buffer_pool(pool);
pbi->refresh_frame_flags = 0;
cm->lf.filter_level = 0;
cm->show_frame = 1;
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// NOTE(zoeliu): The existing frame to show is adopted as a reference frame.
pbi->refresh_frame_flags = vpx_rb_read_literal(rb, REF_FRAMES);
for (i = 0; i < REFS_PER_FRAME; ++i) {
const int ref = vpx_rb_read_literal(rb, REF_FRAMES_LOG2);
const int idx = cm->ref_frame_map[ref];
RefBuffer *const ref_frame = &cm->frame_refs[i];
ref_frame->idx = idx;
ref_frame->buf = &frame_bufs[idx].buf;
cm->ref_frame_sign_bias[LAST_FRAME + i] = vpx_rb_read_bit(rb);
}
for (i = 0; i < REFS_PER_FRAME; ++i) {
RefBuffer *const ref_buf = &cm->frame_refs[i];
#if CONFIG_VP9_HIGHBITDEPTH
vp10_setup_scale_factors_for_frame(&ref_buf->sf,
ref_buf->buf->y_crop_width,
ref_buf->buf->y_crop_height,
cm->width, cm->height,
cm->use_highbitdepth);
#else // CONFIG_VP9_HIGHBITDEPTH
vp10_setup_scale_factors_for_frame(&ref_buf->sf,
ref_buf->buf->y_crop_width,
ref_buf->buf->y_crop_height,
cm->width, cm->height);
#endif // CONFIG_VP9_HIGHBITDEPTH
}
// Generate next_ref_frame_map.
lock_buffer_pool(pool);
for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
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];
}
// 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;
}
unlock_buffer_pool(pool);
pbi->hold_ref_buf = 1;
#else
pbi->refresh_frame_flags = 0;
if (cm->frame_parallel_decode) {
for (i = 0; i < REF_FRAMES; ++i)
cm->next_ref_frame_map[i] = cm->ref_frame_map[i];
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
return 0;
}
......@@ -3149,6 +3226,15 @@ static size_t read_uncompressed_header(VP10Decoder *pbi,
}
} else if (pbi->need_resync != 1) { /* Skip if need resync */
pbi->refresh_frame_flags = vpx_rb_read_literal(rb, REF_FRAMES);
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
if (!pbi->refresh_frame_flags) {
// NOTE: "pbi->refresh_frame_flags == 0" indicates that the coded frame
// will not be used as a reference
cm->is_reference_frame = 0;
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
for (i = 0; i < REFS_PER_FRAME; ++i) {
const int ref = vpx_rb_read_literal(rb, REF_FRAMES_LOG2);
const int idx = cm->ref_frame_map[ref];
......@@ -3470,6 +3556,7 @@ static int read_compressed_header(VP10Decoder *pbi, const uint8_t *data,
if (cm->reference_mode != SINGLE_REFERENCE)
setup_compound_reference_mode(cm);
read_frame_reference_mode_probs(cm, &r);
for (j = 0; j < BLOCK_SIZE_GROUPS; j++)
......@@ -3541,6 +3628,10 @@ static void debug_check_frame_counts(const VP10_COMMON *const cm) {
sizeof(cm->counts.comp_ref)));
assert(!memcmp(&cm->counts.tx_size, &zero_counts.tx_size,
sizeof(cm->counts.tx_size)));
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
assert(!memcmp(cm->counts.comp_bwdref, zero_counts.comp_bwdref,
sizeof(cm->counts.comp_bwdref)));
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
assert(!memcmp(cm->counts.skip, zero_counts.skip, sizeof(cm->counts.skip)));
#if CONFIG_REF_MV
assert(!memcmp(&cm->counts.mv[0], &zero_counts.mv[0],
......@@ -3615,7 +3706,13 @@ void vp10_decode_frame(VP10Decoder *pbi,
if (!first_partition_size) {
// showing a frame directly
*p_data_end = data + (cm->profile <= PROFILE_2 ? 1 : 2);
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
if (cm->show_existing_frame)
*p_data_end = data + vpx_rb_bytes_read(&rb);
else
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
*p_data_end = data + (cm->profile <= PROFILE_2 ? 1 : 2);
return;
}
......
......@@ -759,11 +759,28 @@ static void read_ref_frames(VP10_COMMON *const cm, MACROBLOCKD *const xd,
const REFERENCE_MODE mode = read_block_reference_mode(cm, xd, r);
// FIXME(rbultje) I'm pretty sure this breaks segmentation ref frame coding
if (mode == COMPOUND_REFERENCE) {
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
const int idx = cm->ref_frame_sign_bias[cm->comp_bwd_ref[0]];
#else
const int idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
const int ctx = vp10_get_pred_context_comp_ref_p(cm, xd);
const int bit = vp10_read(r, fc->comp_ref_prob[ctx][0]);
if (counts)
++counts->comp_ref[ctx][0][bit];
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
ref_frame[!idx] = cm->comp_fwd_ref[bit];
{
const int ctx1 = vp10_get_pred_context_comp_bwdref_p(cm, xd);
const int bit1 = vpx_read(r, fc->comp_bwdref_prob[ctx1][0]);
if (counts)
++counts->comp_bwdref[ctx1][0][bit1];
ref_frame[idx] = cm->comp_bwd_ref[bit1];
}
#else // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
ref_frame[idx] = cm->comp_fixed_ref;
#if CONFIG_EXT_REFS
......@@ -788,9 +805,10 @@ static void read_ref_frames(VP10_COMMON *const cm, MACROBLOCKD *const xd,
ref_frame[!idx] = cm->comp_var_ref[4];
}
}
#else
#else // CONFIG_EXT_REFS
ref_frame[!idx] = cm->comp_var_ref[bit];
#endif // CONFIG_EXT_REFS
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
} else if (mode == SINGLE_REFERENCE) {
#if CONFIG_EXT_REFS
const int ctx0 = vp10_get_pred_context_single_ref_p1(xd);
......@@ -822,7 +840,7 @@ static void read_ref_frames(VP10_COMMON *const cm, MACROBLOCKD *const xd,
ref_frame[0] = bit3 ? LAST2_FRAME : LAST_FRAME;
}
}
#else
#else // CONFIG_EXT_REFS
const int ctx0 = vp10_get_pred_context_single_ref_p1(xd);
const int bit0 = vp10_read(r, fc->single_ref_prob[ctx0][0]);
if (counts)
......@@ -832,7 +850,19 @@ static void read_ref_frames(VP10_COMMON *const cm, MACROBLOCKD *const xd,
const int bit1 = vp10_read(r, fc->single_ref_prob[ctx1][1]);
if (counts)
++counts->single_ref[ctx1][1][bit1];
#if CONFIG_BIDIR_PRED
if (bit1) {
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];
ref_frame[0] = bit2 ? ALTREF_FRAME : BWDREF_FRAME;
} else {
ref_frame[0] = GOLDEN_FRAME;
}
#else // CONFIG_BIDIR_PRED
ref_frame[0] = bit1 ? ALTREF_FRAME : GOLDEN_FRAME;
#endif // CONFIG_BIDIR_PRED
} else {
ref_frame[0] = LAST_FRAME;
}
......
......@@ -214,6 +214,9 @@ vpx_codec_err_t vp10_set_reference_dec(VP10_COMMON *cm,
// #else // CONFIG_EXT_REFS
// cpi->gld_fb_idx = 1;
// cpi->alt_fb_idx = 2;
// TODO(zoeliu): To revisit following code and reconsider what assumption we
// may take on the reference frame buffer virtual indexes
if (ref_frame_flag == VP9_LAST_FLAG) {
idx = cm->ref_frame_map[0];
#if CONFIG_EXT_REFS
......@@ -227,11 +230,18 @@ vpx_codec_err_t vp10_set_reference_dec(VP10_COMMON *cm,
idx = cm->ref_frame_map[4];
} else if (ref_frame_flag == VP9_ALT_FLAG) {
idx = cm->ref_frame_map[5];
#else
#else // CONFIG_EXT_REFS
} else if (ref_frame_flag == VP9_GOLD_FLAG) {
idx = cm->ref_frame_map[1];
#if CONFIG_BIDIR_PRED
} else if (ref_frame_flag == VP9_BWD_FLAG) {
idx = cm->ref_frame_map[2];
} else if (ref_frame_flag == VP9_ALT_FLAG) {
idx = cm->ref_frame_map[3];
#else // CONFIG_BIDIR_PRED
} else if (ref_frame_flag == VP9_ALT_FLAG) {
idx = cm->ref_frame_map[2];
#endif // CONFIG_BIDIR_PRED
#endif // CONFIG_EXT_REFS
} else {
vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
......@@ -281,15 +291,25 @@ static void swap_frame_buffers(VP10Decoder *pbi) {
}
// Current thread releases the holding of reference frame.
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
for (; ref_index < REF_FRAMES; ++ref_index) {
const int old_idx = cm->ref_frame_map[ref_index];
decrease_ref_count(old_idx, frame_bufs, pool);
cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
}
#else
for (; ref_index < REF_FRAMES && !cm->show_existing_frame; ++ref_index) {
const int old_idx = cm->ref_frame_map[ref_index];
decrease_ref_count(old_idx, frame_bufs, pool);
cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
unlock_buffer_pool(pool);
pbi->hold_ref_buf = 0;
cm->frame_to_show = get_frame_new_buffer(cm);
// TODO(zoeliu): To fix the ref frame buffer update for the scenario of
// cm->frame_parellel_decode == 1
if (!cm->frame_parallel_decode || !cm->show_frame) {
lock_buffer_pool(pool);
--frame_bufs[cm->new_fb_idx].ref_count;
......@@ -297,8 +317,10 @@ static void swap_frame_buffers(VP10Decoder *pbi) {
}
// Invalidate these references until the next frame starts.
for (ref_index = 0; ref_index < REFS_PER_FRAME; ref_index++)
cm->frame_refs[ref_index].idx = -1;
for (ref_index = 0; ref_index < REFS_PER_FRAME; ref_index++) {
cm->frame_refs[ref_index].idx = INVALID_IDX;
cm->frame_refs[ref_index].buf = NULL;
}
}
int vp10_receive_compressed_data(VP10Decoder *pbi,
......@@ -327,12 +349,16 @@ int vp10_receive_compressed_data(VP10Decoder *pbi,
pbi->ready_for_new_data = 0;
// Find a free buffer for the new frame, releasing the reference previously
// held.
// Check if the previous frame was a frame without any references to it.
// Release frame buffer if not decoding in frame parallel mode.
if (!cm->frame_parallel_decode && cm->new_fb_idx >= 0
&& frame_bufs[cm->new_fb_idx].ref_count == 0)
pool->release_fb_cb(pool->cb_priv,
&frame_bufs[cm->new_fb_idx].raw_frame_buffer);
// Find a free frame buffer. Return error if can not find any.
cm->new_fb_idx = get_free_fb(cm);
if (cm->new_fb_idx == INVALID_IDX)
......@@ -386,10 +412,17 @@ int vp10_receive_compressed_data(VP10Decoder *pbi,
}