Commit e89ca180 authored by Zoe Liu's avatar Zoe Liu

Make the bi-predictive frame group interval adjustable

This is for the bidir-pred experiment. Previously the length of the
bi-predictive frame group interval is fixed at 2, i.e. one
bi-predictive frame may be inserted every other frame. This patch
makes the length adjustable, i.e. any positive number may be
specified, but the use of the backward ref will be turned off if the
bi-predictive frame group interval is larger than the golden frame
group.

Further, an additional rate factor level has been added:
INTER_LOW
, which applies to LAST_BIPRED_UPDATE frames that are not used as
references.

Change-Id: I5514d34a64dd486bbb5756c2d0612946f598a789
parent 6fd7f7dd
......@@ -187,7 +187,8 @@ typedef struct VP10Common {
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
// Flag for a frame used as a reference - not written to the bitstream
int is_reference_frame;
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// Flag signaling that the frame is encoded using only INTRA modes.
......
......@@ -3727,6 +3727,23 @@ void vp10_decode_frame(VP10Decoder *pbi,
!cm->last_intra_only &&
cm->last_show_frame &&
(cm->last_frame_type != KEY_FRAME);
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// NOTE(zoeliu): As cm->prev_frame can take neither a frame of
// show_exisiting_frame=1, nor can it take a frame not used as
// a reference, it is probable that by the time it is being
// referred to, the frame buffer it originally points to may
// already get expired and have been reassigned to the current
// newly coded frame. Hence, we need to check whether this is
// the case, and if yes, we have 2 choices:
// (1) Simply disable the use of previous frame mvs; or
// (2) Have cm->prev_frame point to one reference frame buffer,
// e.g. LAST_FRAME.
if (cm->use_prev_frame_mvs && !dec_is_ref_frame_buf(pbi, cm->prev_frame)) {
// Reassign the LAST_FRAME buffer to cm->prev_frame.
RefBuffer *last_fb_ref_buf = &cm->frame_refs[LAST_FRAME - LAST_FRAME];
cm->prev_frame = &cm->buffer_pool->frame_bufs[last_fb_ref_buf->idx];
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
vp10_setup_block_planes(xd, cm->subsampling_x, cm->subsampling_y);
......
......@@ -152,6 +152,21 @@ static INLINE void decrease_ref_count(int idx, RefCntBuffer *const frame_bufs,
}
}
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
static INLINE int dec_is_ref_frame_buf(VP10Decoder *const pbi,
RefCntBuffer *frame_buf) {
VP10_COMMON *const cm = &pbi->common;
int i;
for (i = 0; i < REFS_PER_FRAME; ++i) {
RefBuffer *const ref_frame = &cm->frame_refs[i];
if (ref_frame->idx == INVALID_IDX) continue;
if (frame_buf == &cm->buffer_pool->frame_bufs[ref_frame->idx])
break;
}
return (i < REFS_PER_FRAME);
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -3057,7 +3057,6 @@ static void write_uncompressed_header(VP10_COMP *cpi,
assert(get_ref_frame_map_idx(cpi, ref_frame) != INVALID_IDX);
vpx_wb_write_literal(wb, get_ref_frame_map_idx(cpi, ref_frame),
REF_FRAMES_LOG2);
// TODO(zoeliu): To further explore whether sign bias bits are needed.
vpx_wb_write_bit(wb, cm->ref_frame_sign_bias[ref_frame]);
}
}
......
......@@ -4527,11 +4527,29 @@ static void encode_frame_internal(VP10_COMP *cpi) {
vp10_initialize_rd_consts(cpi);
vp10_initialize_me_consts(cpi, x, cm->base_qindex);
init_encode_frame_mb_context(cpi);
cm->use_prev_frame_mvs = !cm->error_resilient_mode &&
cm->width == cm->last_width &&
cm->height == cm->last_height &&
!cm->intra_only &&
cm->last_show_frame;
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// NOTE(zoeliu): As cm->prev_frame can take neither a frame of
// show_exisiting_frame=1, nor can it take a frame not used as
// a reference, it is probable that by the time it is being
// referred to, the frame buffer it originally points to may
// already get expired and have been reassigned to the current
// newly coded frame. Hence, we need to check whether this is
// the case, and if yes, we have 2 choices:
// (1) Simply disable the use of previous frame mvs; or
// (2) Have cm->prev_frame point to one reference frame buffer,
// e.g. LAST_FRAME.
if (cm->use_prev_frame_mvs && !enc_is_ref_frame_buf(cpi, cm->prev_frame)) {
// Reassign the LAST_FRAME buffer to cm->prev_frame.
const int last_fb_buf_idx = get_ref_frame_buf_idx(cpi, LAST_FRAME);
cm->prev_frame = &cm->buffer_pool->frame_bufs[last_fb_buf_idx];
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// Special case: set prev_mi to NULL when the previous mode info
// context cannot be used.
......
......@@ -2311,8 +2311,8 @@ void vp10_change_config(struct VP10_COMP *cpi, const VP10EncoderConfig *oxcf) {
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
rc->is_bwd_ref_frame = 0;
rc->is_last_nonref_frame = 0;
rc->is_nonref_frame = 0;
rc->is_last_bipred_frame = 0;
rc->is_bipred_frame = 0;
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#if 0
......@@ -3332,6 +3332,60 @@ static INLINE int upsample_ref_frame(VP10_COMP *cpi,
}
}
#define DUMP_REF_FRAME_IMAGES 0
#if DUMP_REF_FRAME_IMAGES == 1
static int dump_one_image(VP10_COMMON *cm,
const YV12_BUFFER_CONFIG *const ref_buf,
char *file_name) {
int h;
FILE *f_ref = NULL;
if (ref_buf == NULL) {
printf("Frame data buffer is NULL.\n");
return VPX_CODEC_MEM_ERROR;
}
if ((f_ref = fopen(file_name, "wb")) == NULL) {
printf("Unable to open file %s to write.\n", file_name);
return VPX_CODEC_MEM_ERROR;
}
// --- Y ---
for (h = 0; h < cm->height; ++h) {
fwrite(&ref_buf->y_buffer[h*ref_buf->y_stride],
1, cm->width, f_ref);
}
// --- U ---
for (h = 0; h < (cm->height >> 1); ++h) {
fwrite(&ref_buf->u_buffer[h*ref_buf->uv_stride],
1, (cm->width >> 1), f_ref);
}
// --- V ---
for (h = 0; h < (cm->height >> 1); ++h) {
fwrite(&ref_buf->v_buffer[h*ref_buf->uv_stride],
1, (cm->width >> 1), f_ref);
}
fclose(f_ref);
return VPX_CODEC_OK;
}
static void dump_ref_frame_images(VP10_COMP *cpi) {
VP10_COMMON *const cm = &cpi->common;
MV_REFERENCE_FRAME ref_frame;
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
char file_name[256] = "";
snprintf(file_name, sizeof(file_name), "/tmp/enc_F%d_ref_%d.yuv",
cm->current_video_frame, ref_frame);
dump_one_image(
cm, get_ref_frame_buffer(cpi, ref_frame), file_name);
}
}
#endif // DUMP_REF_FRAME_IMAGES == 1
void vp10_update_reference_frames(VP10_COMP *cpi) {
VP10_COMMON * const cm = &cpi->common;
BufferPool *const pool = cm->buffer_pool;
......@@ -3351,12 +3405,12 @@ void vp10_update_reference_frames(VP10_COMP *cpi) {
// TODO(zoeliu): To remove the reference buffer update for the
// show_existing_frame==1 case.
#if 0
if (cpi->rc.is_last_nonref_frame) {
// NOTE: After the encoding of the LAST_NONREF_FRAME, the flag of
if (cpi->rc.is_last_bipred_frame) {
// NOTE: After the encoding of the LAST_BIPRED_FRAME, the flag of
// show_existing_frame will be set, to notify the decoder to show the
// coded BWDREF_FRAME. During the handling of the show_existing_frame,
// no update will be conducted on the reference frame buffer.
// Following is to get the BWDREF_FRAME to show to be taken as the
// Following is to get the BWDREF_FRAME to show to be regarded as the
// LAST_FRAME, preparing for the encoding of the next BWDREF_FRAME.
cpi->lst_fb_idx = cpi->bwd_fb_idx;
return;
......@@ -3554,7 +3608,7 @@ void vp10_update_reference_frames(VP10_COMP *cpi) {
#if CONFIG_BIDIR_PRED
// TODO(zoeliu): To remove the reference buffer update for the
// show_existing_frame==1 case; Instead, we move the reference buffer update
// to the previous coded frame, i.e. the last-nonref-frame. In that case, no
// to the previous coded frame, i.e. the last-bipred-frame. In that case, no
// bit should be set in the refresh-mask, but the visual ref-idx should be
// updated and written to the bitstream accordingly, as the virtual ref-idx
// for LAST_FRAME and BWDREF_FRAME should be switched, i.e. cpi->lst_fb_idx
......@@ -3591,6 +3645,11 @@ void vp10_update_reference_frames(VP10_COMP *cpi) {
#endif // CONFIG_EXT_REFS
}
#if DUMP_REF_FRAME_IMAGES == 1
// Dump out all reference frame images.
dump_ref_frame_images(cpi);
#endif // DUMP_REF_FRAME_IMAGES
#if CONFIG_VP9_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity > 0) {
vp10_denoiser_update_frame_info(&cpi->denoiser,
......@@ -4797,8 +4856,8 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
cpi->refresh_alt_ref_frame = 0;
cpi->rc.is_bwd_ref_frame = 0;
cpi->rc.is_last_nonref_frame = 0;
cpi->rc.is_nonref_frame = 0;
cpi->rc.is_last_bipred_frame = 0;
cpi->rc.is_bipred_frame = 0;
// Build the bitstream
vp10_pack_bitstream(cpi, dest, size);
......@@ -4806,6 +4865,11 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
// Set up frame to show to get ready for stats collection.
cm->frame_to_show = get_frame_new_buffer(cm);
#if DUMP_RECON_FRAMES == 1
// NOTE(zoeliu): For debug - Output the filtered reconstructed video.
dump_filtered_recon_frames(cpi);
#endif // DUMP_RECON_FRAMES
// Update the LAST_FRAME in the reference frame buffer.
vp10_update_reference_frames(cpi);
......@@ -4815,11 +4879,6 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
*frame_flags = cpi->frame_flags & ~FRAMEFLAGS_KEY;
#if DUMP_RECON_FRAMES == 1
// NOTE(zoeliu): For debug - Output the filtered reconstructed video.
dump_filtered_recon_frames(cpi);
#endif // DUMP_RECON_FRAMES
// Update the frame type
cm->last_frame_type = cm->frame_type;
......@@ -4951,9 +5010,9 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
#endif // DUMP_RECON_FRAMES
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
if (cpi->rc.is_last_nonref_frame) {
// NOTE: If the current frame is a LAST_NONREF_FRAME, we need next to show
// the BWDREF_FRAME.
if (cpi->rc.is_last_bipred_frame) {
// NOTE: If the current frame is a LAST_BIPRED_FRAME, next it is needed
// to show the BWDREF_FRAME.
cpi->existing_fb_idx_to_show = cpi->bwd_fb_idx;
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
......@@ -5038,21 +5097,6 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
if (!cm->show_existing_frame)
cm->last_show_frame = cm->show_frame;
#if 0
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
if ((cm->show_frame &&
!(cpi->rc.is_nonref_frame || cpi->rc.is_last_nonref_frame) ||
cpi->rc.is_bwd_ref_frame) {
vp10_swap_mi_and_prev_mi(cm);
}
if (cm->show_frame || cpi->rc.is_bwd_ref_frame) {
// Don't increment frame counters if this was an altref buffer
// update not a real frame
++cm->current_video_frame;
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#endif // 0
if (cm->show_frame) {
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// TODO(zoeliu): We may only swamp mi and prev_mi for those frames that are
......@@ -5065,7 +5109,7 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
}
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// NOTE: It is not supposed to ref to any frame not used as reference
// NOTE: Shall not refer to any frame not used as reference.
if (cm->is_reference_frame)
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
cm->prev_frame = cm->cur_frame;
......@@ -5285,7 +5329,7 @@ static int get_brf_src_index(VP10_COMP *cpi) {
brf_src_index = gf_group->brf_src_offset[gf_group->index];
} else {
// TODO(zoeliu): To re-visit the setup for this scenario
brf_src_index = BIDIR_PRED_PERIOD - 1;
brf_src_index = cpi->rc.bipred_group_interval - 1;
}
}
......@@ -5706,10 +5750,10 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
vpx_clear_system_state();
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
if (cpi->rc.is_last_nonref_frame) {
// NOTE(zoeliu): If the current frame is a last non-reference frame, we need
// next to show the BWDREF_FRAME.
cpi->rc.is_last_nonref_frame = 0;
if (cpi->rc.is_last_bipred_frame) {
// NOTE(zoeliu): If the current frame is a last bi-predictive frame, it is
// needed next to show the BWDREF_FRAME.
cpi->rc.is_last_bipred_frame = 0;
cm->show_existing_frame = 1;
} else {
cm->show_existing_frame = 0;
......
......@@ -710,6 +710,20 @@ static INLINE const YV12_BUFFER_CONFIG *get_upsampled_ref(
return &cpi->upsampled_ref_bufs[buf_idx].buf;
}
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
static INLINE int enc_is_ref_frame_buf(VP10_COMP *cpi,
RefCntBuffer *frame_buf) {
MV_REFERENCE_FRAME ref_frame;
VP10_COMMON *const cm = &cpi->common;
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
const int buf_idx = get_ref_frame_buf_idx(cpi, ref_frame);
if (buf_idx == INVALID_IDX) continue;
if (frame_buf == &cm->buffer_pool->frame_bufs[buf_idx]) break;
}
return (ref_frame <= ALTREF_FRAME);
}
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
static INLINE unsigned int get_token_alloc(int mb_rows, int mb_cols) {
// TODO(JBB): double check we can't exceed this token count if we have a
// 32x32 transform crossing a boundary at a multiple of 16.
......
......@@ -61,7 +61,6 @@
#define RC_FACTOR_MIN 0.75
#define RC_FACTOR_MAX 1.75
#define NCOUNT_INTRA_THRESH 8192
#define NCOUNT_INTRA_FACTOR 3
#define NCOUNT_FRAME_II_THRESH 5.0
......@@ -1630,8 +1629,20 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
int mid_boost_bits = 0;
int mid_frame_idx;
unsigned char arf_buffer_indices[MAX_ACTIVE_ARFS];
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
int bidir_pred_frame_index = 0;
// The use of bi-predictive frames are only enabled when following 3
// conditions are met:
// (1) Alt-ref is enabled;
// (2) The bi-predictive group interval is at least 2; and
// (3) The bi-predictive group interval is strictly smaller than the
// golden group interval.
const int is_bipred_enabled =
rc->source_alt_ref_pending && rc->bipred_group_interval &&
rc->bipred_group_interval <=
(rc->baseline_gf_interval - rc->source_alt_ref_pending);
int bipred_group_end = 0;
int bipred_frame_index = 0;
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
key_frame = cpi->common.frame_type == KEY_FRAME;
......@@ -1671,7 +1682,7 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
frame_index++;
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
bidir_pred_frame_index++;
bipred_frame_index++;
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// Store the bits to spend on the ARF if there is one.
......@@ -1740,38 +1751,39 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
VPXMIN(max_bits, (int)total_group_bits));
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// TODO(zoeliu): Currently only support BIDIR_PRED_PERIOD = 2
assert(BIDIR_PRED_PERIOD == 2);
// NOTE: BIDIR_PRED is only enabled when its interval is strictly
// less than the GOLDEN_FRAME group interval.
// NOTE: BIDIR_PRED is only enabled when the length of the bi-predictive
// frame group interval is strictly smaller than that of the GOLDEN
// FRAME group interval.
// TODO(zoeliu): Currently BIDIR_PRED is only enabled when alt-ref is on.
if (rc->source_alt_ref_pending && BIDIR_PRED_PERIOD <
(rc->baseline_gf_interval - rc->source_alt_ref_pending)) {
if (bidir_pred_frame_index == 1) {
const int curr_brf_src_offset = BIDIR_PRED_PERIOD - 1;
if ((i + curr_brf_src_offset) >=
(rc->baseline_gf_interval - rc->source_alt_ref_pending)) {
gf_group->update_type[frame_index] = LF_UPDATE;
gf_group->bidir_pred_enabled[frame_index] = 0;
gf_group->brf_src_offset[frame_index] = 0;
} else {
gf_group->update_type[frame_index] = BRF_UPDATE;
gf_group->bidir_pred_enabled[frame_index] = 1;
gf_group->brf_src_offset[frame_index] = curr_brf_src_offset;
}
} else if (bidir_pred_frame_index == BIDIR_PRED_PERIOD) {
gf_group->update_type[frame_index] = LASTNRF_UPDATE;
if (is_bipred_enabled && !bipred_group_end) {
const int cur_brf_src_offset = rc->bipred_group_interval - 1;
// --- BRF_UPDATE ---
if (bipred_frame_index == 1) {
gf_group->update_type[frame_index] = BRF_UPDATE;
gf_group->bidir_pred_enabled[frame_index] = 1;
gf_group->brf_src_offset[frame_index] = cur_brf_src_offset;
// --- LAST_BIPRED_UPDATE ---
} else if (bipred_frame_index == rc->bipred_group_interval) {
gf_group->update_type[frame_index] = LAST_BIPRED_UPDATE;
gf_group->bidir_pred_enabled[frame_index] = 1;
gf_group->brf_src_offset[frame_index] = 0;
// Reset the bidir_pred index.
bidir_pred_frame_index = 0;
// Reset the bi-predictive frame index.
bipred_frame_index = 0;
// --- BIPRED_UPDATE ---
} else {
gf_group->update_type[frame_index] = NRF_UPDATE;
gf_group->update_type[frame_index] = BIPRED_UPDATE;
gf_group->bidir_pred_enabled[frame_index] = 1;
gf_group->brf_src_offset[frame_index] = 0;
}
bidir_pred_frame_index++;
bipred_frame_index++;
// Check whether the next bi-predictive frame group would entirely be
// included within the current golden frame group.
if (bipred_frame_index == 1 && (i + 1 + cur_brf_src_offset) >=
(rc->baseline_gf_interval - rc->source_alt_ref_pending)) {
bipred_group_end = 1;
}
} else {
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
gf_group->update_type[frame_index] = LF_UPDATE;
......@@ -1784,14 +1796,19 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
if (gf_group->update_type[frame_index] == BRF_UPDATE) {
// Boost up the allocated bits on BWDREF_FRAME
// (zoeliu)gf_group->rf_level[frame_index] = GF_ARF_LOW;
gf_group->rf_level[frame_index] = INTER_HIGH;
gf_group->bit_allocation[frame_index] =
target_frame_size + (target_frame_size >> 2);
} else if (gf_group->update_type[frame_index] == LASTNRF_UPDATE) {
gf_group->rf_level[frame_index] = INTER_NORMAL;
} else if (gf_group->update_type[frame_index] == LAST_BIPRED_UPDATE) {
// Press down the allocated bits on LAST_BIPRED_UPDATE frames
gf_group->rf_level[frame_index] = INTER_LOW;
gf_group->bit_allocation[frame_index] =
VPXMAX(0, target_frame_size - (target_frame_size >> 1));
target_frame_size - (target_frame_size >> 1);
} else if (gf_group->update_type[frame_index] == BIPRED_UPDATE) {
// TODO(zoeliu): To investigate whether the allocated bits on
// BIPRED_UPDATE frames need to be further adjusted.
gf_group->rf_level[frame_index] = INTER_NORMAL;
gf_group->bit_allocation[frame_index] = target_frame_size;
} else {
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
gf_group->rf_level[frame_index] = INTER_NORMAL;
......@@ -2041,6 +2058,13 @@ static void define_gf_group(VP10_COMP *cpi, FIRSTPASS_STATS *this_frame) {
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
rc->bipred_group_interval = BFG_INTERVAL;
// The minimum bi-predictive frame group interval is 2.
if (rc->bipred_group_interval < 2)
rc->bipred_group_interval = 0;
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// Reset the file position.
reset_fpf_position(twopass, start_pos);
......@@ -2484,8 +2508,8 @@ static void configure_buffer_updates(VP10_COMP *cpi) {
cpi->rc.is_src_frame_alt_ref = 0;
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
cpi->rc.is_bwd_ref_frame = 0;
cpi->rc.is_last_nonref_frame = 0;
cpi->rc.is_nonref_frame = 0;
cpi->rc.is_last_bipred_frame = 0;
cpi->rc.is_bipred_frame = 0;
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
switch (twopass->gf_group.update_type[twopass->gf_group.index]) {
......@@ -2544,23 +2568,20 @@ static void configure_buffer_updates(VP10_COMP *cpi) {
cpi->rc.is_bwd_ref_frame = 1;
break;
// TODO(zoeliu): When BIDIR_PRED and EXT_REFS start to work together, we
// may take both LASTNRF and NRF as one of the last ref
case LASTNRF_UPDATE:
case LAST_BIPRED_UPDATE:
cpi->refresh_last_frame = 0;
cpi->refresh_golden_frame = 0;
cpi->refresh_bwd_ref_frame = 0;
cpi->refresh_alt_ref_frame = 0;
cpi->rc.is_last_nonref_frame = 1;
cpi->rc.is_last_bipred_frame = 1;
break;
case NRF_UPDATE:
cpi->refresh_last_frame = 0;
case BIPRED_UPDATE:
cpi->refresh_last_frame = 1;
cpi->refresh_golden_frame = 0;
cpi->refresh_bwd_ref_frame = 0;
cpi->refresh_alt_ref_frame = 0;
cpi->rc.is_nonref_frame = 1;
cpi->rc.is_bipred_frame = 1;
break;
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
......
......@@ -39,6 +39,13 @@ typedef struct {
} FIRSTPASS_MB_STATS;
#endif
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// Length of the bi-predictive frame group (BFG)
// NOTE: Currently each BFG contains one backward ref (BWF) frame plus a certain
// number of bi-predictive frames.
#define BFG_INTERVAL 2
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
#define VLOW_MOTION_THRESHOLD 950
typedef struct {
......@@ -72,16 +79,14 @@ typedef enum {
GF_UPDATE = 2,
ARF_UPDATE = 3,
OVERLAY_UPDATE = 4,
#if CONFIG_BIDIR_PRED
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
BRF_UPDATE = 5, // Backward Reference Frame
// For NRF's within a BIDIR_PRED period, if it is the last one, then it is
// needed to get LAST_FRAME updated; Otherwise no ref update is needed at all.
LASTNRF_UPDATE = 6, // Last Non-Reference Frame
NRF_UPDATE = 7, // Non-Reference Frame, but not the last one
LAST_BIPRED_UPDATE = 6, // Last Bi-predictive Frame
BIPRED_UPDATE = 7, // Bi-predictive Frame, but not the last one
FRAME_UPDATE_TYPES = 8
#else
FRAME_UPDATE_TYPES = 5
#endif // CONFIG_BIDIR_PRED
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
} FRAME_UPDATE_TYPE;
#define FC_ANIMATION_THRESH 0.15
......@@ -98,10 +103,10 @@ typedef struct {
unsigned char arf_src_offset[(MAX_LAG_BUFFERS * 2) + 1];
unsigned char arf_update_idx[(MAX_LAG_BUFFERS * 2) + 1];
unsigned char arf_ref_idx[(MAX_LAG_BUFFERS * 2) + 1];
#if CONFIG_BIDIR_PRED
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
unsigned char brf_src_offset[(MAX_LAG_BUFFERS * 2) + 1];
unsigned char bidir_pred_enabled[(MAX_LAG_BUFFERS * 2) + 1];
#endif // CONFIG_BIDIR_PRED
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
int bit_allocation[(MAX_LAG_BUFFERS * 2) + 1];
} GF_GROUP;
......
......@@ -950,7 +950,8 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const VP10_COMP *cpi,
int vp10_frame_type_qdelta(const VP10_COMP *cpi, int rf_level, int q) {
static const double rate_factor_deltas[RATE_FACTOR_LEVELS] = {
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
0.80, // INTER_NORMAL
1.00, // INTER_NORMAL
0.80, // INTER_LOW
1.25, // INTER_HIGH
#else
1.00, // INTER_NORMAL
......@@ -961,7 +962,12 @@ int vp10_frame_type_qdelta(const VP10_COMP *cpi, int rf_level, int q) {
2.00, // KF_STD
};
static const FRAME_TYPE frame_type[RATE_FACTOR_LEVELS] =
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
{ INTER_FRAME, INTER_FRAME, INTER_FRAME,
INTER_FRAME, INTER_FRAME, KEY_FRAME };
#else
{INTER_FRAME, INTER_FRAME, INTER_FRAME, INTER_FRAME, KEY_FRAME};
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
const VP10_COMMON *const cm = &cpi->common;
int qdelta = vp10_compute_qdelta_by_rate(&cpi->rc, frame_type[rf_level],
q, rate_factor_deltas[rf_level],
......
......@@ -28,6 +28,17 @@ extern "C" {
#define MAX_GF_INTERVAL 16
#define FIXED_GF_INTERVAL 8 // Used in some testing modes only
#if !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
typedef enum {
INTER_NORMAL = 0,
INTER_LOW = 1,
INTER_HIGH = 2,
GF_ARF_LOW = 3,
GF_ARF_STD = 5,
KF_STD = 6,
RATE_FACTOR_LEVELS = 7
} RATE_FACTOR_LEVEL;
#else
typedef enum {
INTER_NORMAL = 0,
INTER_HIGH = 1,
......@@ -36,6 +47,7 @@ typedef enum {
KF_STD = 4,
RATE_FACTOR_LEVELS = 5
} RATE_FACTOR_LEVEL;
#endif // !CONFIG_EXT_REFS && CONFIG_BIDIR_PRED
// Internal frame scaling level.
typedef enum {
......@@ -91,11 +103,14 @@ typedef struct {
int is_src_frame_alt_ref;
#if CONFIG_BIDIR_PRED
// Length of the bi-predictive frame group interval
int bipred_group_interval;
// NOTE: Different types of frames may have different bits allocated
// accordingly, aiming to achieve the overall optimal RD performance.
int is_bwd_ref_frame;
int is_last_nonref_frame;
int is_nonref_frame;
int is_last_bipred_frame;
int is_bipred_frame;
#endif // CONFIG_BIDIR_PRED