if (cm->log2_tile_rows != 0) vpx_wb_write_bit(wb, cm->log2_tile_rows != 1);
#endif // CONFIG_EXT_TILE
}
+
static int get_refresh_mask(VP10_COMP *cpi) {
int refresh_mask = 0;
// LAST3_FRAME.
refresh_mask |=
(cpi->refresh_last_frame << cpi->lst_fb_idxes[LAST_REF_FRAMES - 1]);
-
- refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->bwd_fb_idx);
+ if (cpi->rc.is_bwd_ref_frame && cpi->num_extra_arfs) {
+ // We have swapped the virtual indices
+ refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->arf_map[0]);
+ } else {
+ refresh_mask |= (cpi->refresh_bwd_ref_frame << cpi->bwd_fb_idx);
+ }
#else
refresh_mask |= (cpi->refresh_last_frame << cpi->lst_fb_idx);
#endif // CONFIG_EXT_REFS
return refresh_mask | (cpi->refresh_golden_frame << cpi->alt_fb_idx);
} else {
int arf_idx = cpi->alt_fb_idx;
+#if CONFIG_EXT_REFS
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ arf_idx = cpi->arf_map[gf_group->arf_update_idx[gf_group->index]];
+#else
if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) {
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
arf_idx = gf_group->arf_update_idx[gf_group->index];
}
+#endif // CONFIG_EXT_REFS
return refresh_mask | (cpi->refresh_golden_frame << cpi->gld_fb_idx) |
(cpi->refresh_alt_ref_frame << arf_idx);
}
static INLINE int vp10_preserve_existing_gf(VP10_COMP *cpi) {
#if CONFIG_EXT_REFS
- return !cpi->multi_arf_allowed && cpi->rc.is_src_frame_alt_ref;
+ // Do not swap gf and arf indices for internal overlay frames
+ return !cpi->multi_arf_allowed &&
+ cpi->rc.is_src_frame_alt_ref && !cpi->rc.is_src_frame_ext_arf;
#else
return !cpi->multi_arf_allowed && cpi->refresh_golden_frame &&
cpi->rc.is_src_frame_alt_ref;
-#endif
+#endif // CONFIG_EXT_REFS
}
#ifdef __cplusplus
static MV_REFERENCE_FRAME get_frame_type(const VP10_COMP *cpi) {
if (frame_is_intra_only(&cpi->common))
return INTRA_FRAME;
+#if CONFIG_EXT_REFS
+ // We will not update the golden frame with an internal overlay frame
+ else if ((cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame) ||
+ cpi->rc.is_src_frame_ext_arf)
+#else
else if (cpi->rc.is_src_frame_alt_ref && cpi->refresh_golden_frame)
+#endif
return ALTREF_FRAME;
else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)
return GOLDEN_FRAME;
// now so that HIGH_PRECISION is always
// chosen.
// #define OUTPUT_YUV_REC
-
#ifdef OUTPUT_YUV_DENOISED
FILE *yuv_denoised_file = NULL;
#endif
cpi->gld_fb_idx = LAST_REF_FRAMES;
cpi->bwd_fb_idx = LAST_REF_FRAMES + 1;
cpi->alt_fb_idx = LAST_REF_FRAMES + 2;
+ for (fb_idx = 0; fb_idx < MAX_EXT_ARFS + 1; ++fb_idx)
+ cpi->arf_map[fb_idx] = LAST_REF_FRAMES + 2 + fb_idx;
#else
cpi->lst_fb_idx = 0;
cpi->gld_fb_idx = 1;
VP10_COMMON *const cm = &cpi->common;
const FRAME_UPDATE_TYPE next_frame_update_type =
gf_group->update_type[gf_group->index];
-
+ const int which_arf = gf_group->arf_update_idx[gf_group->index];
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, which is pointed by
cpi->rc.is_last_bipred_frame = 0;
cm->show_existing_frame = 1;
cpi->existing_fb_idx_to_show = cpi->lst_fb_idxes[0];
- } else if (next_frame_update_type == OVERLAY_UPDATE &&
- cpi->is_arf_filter_off) {
+ } else if (cpi->is_arf_filter_off[which_arf] &&
+ (next_frame_update_type == OVERLAY_UPDATE ||
+ next_frame_update_type == INTNL_OVERLAY_UPDATE)) {
// Other parameters related to OVERLAY_UPDATE will be taken care of
// in vp10_rc_get_second_pass_params(cpi)
cm->show_existing_frame = 1;
cpi->rc.is_src_frame_alt_ref = 1;
cpi->existing_fb_idx_to_show = cpi->alt_fb_idx;
- cpi->is_arf_filter_off = 0;
+ cpi->is_arf_filter_off[which_arf] = 0;
} else {
cm->show_existing_frame = 0;
}
+ cpi->rc.is_src_frame_ext_arf = 0;
}
-#endif
+#endif // CONFIG_EXT_REFS
#ifdef OUTPUT_YUV_REC
void vp10_write_one_yuv_frame(VP10_COMMON *cm, YV12_BUFFER_CONFIG *s) {
}
#endif // DUMP_REF_FRAME_IMAGES == 1
+#if CONFIG_EXT_REFS
+// This function is used to shift the virtual indices of last reference frames
+// as follows:
+// LAST_FRAME -> LAST2_FRAME -> LAST3_FRAME
+// when the LAST_FRAME is updated.
+static INLINE void shift_last_ref_frames(VP10_COMP *cpi) {
+ int ref_frame;
+ for (ref_frame = LAST_REF_FRAMES - 1; ref_frame > 0; --ref_frame) {
+ cpi->lst_fb_idxes[ref_frame] = cpi->lst_fb_idxes[ref_frame - 1];
+
+ // [0] is allocated to the current coded frame. The statistics for the
+ // reference frames start at [1].
+ if (!cpi->rc.is_src_frame_alt_ref) {
+ memcpy(cpi->interp_filter_selected[ref_frame + 1],
+ cpi->interp_filter_selected[ref_frame],
+ sizeof(cpi->interp_filter_selected[ref_frame]));
+ }
+ }
+}
+#endif
+
void vp10_update_reference_frames(VP10_COMP *cpi) {
VP10_COMMON *const cm = &cpi->common;
BufferPool *const pool = cm->buffer_pool;
new_uidx = upsample_ref_frame(cpi, ref);
#if CONFIG_EXT_REFS
+ assert(new_uidx != INVALID_IDX);
}
#endif // CONFIG_EXT_REFS
}
-
// At this point the new frame has been encoded.
// If any buffer copy / swapping is signaled it should be done here.
if (cm->frame_type == KEY_FRAME) {
cpi->alt_fb_idx = cpi->gld_fb_idx;
cpi->gld_fb_idx = tmp;
-// TODO(zoeliu): Do we need to copy cpi->interp_filter_selected[0] over to
-// cpi->interp_filter_selected[GOLDEN_FRAME]?
+#if CONFIG_EXT_REFS
+ // We need to modify the mapping accordingly
+ cpi->arf_map[0] = cpi->alt_fb_idx;
+#endif
+ // TODO(zoeliu): Do we need to copy cpi->interp_filter_selected[0] over to
+ // cpi->interp_filter_selected[GOLDEN_FRAME]?
#if CONFIG_EXT_REFS
} else if (cpi->rc.is_last_bipred_frame) {
// Refresh the LAST_FRAME with the BWDREF_FRAME and retire the LAST3_FRAME
// by updating the virtual indices. Note that the frame BWDREF_FRAME points
// to now should be retired, and it should not be used before refreshed.
- int ref_frame, tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES - 1];
- for (ref_frame = LAST_REF_FRAMES - 1; ref_frame > 0; --ref_frame) {
- cpi->lst_fb_idxes[ref_frame] = cpi->lst_fb_idxes[ref_frame - 1];
+ int tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES-1];
+
+ shift_last_ref_frames(cpi);
- if (!cpi->rc.is_src_frame_alt_ref) {
- memcpy(cpi->interp_filter_selected[ref_frame],
- cpi->interp_filter_selected[ref_frame - 1],
- sizeof(cpi->interp_filter_selected[ref_frame - 1]));
- }
- }
cpi->lst_fb_idxes[0] = cpi->bwd_fb_idx;
if (!cpi->rc.is_src_frame_alt_ref) {
memcpy(cpi->interp_filter_selected[0],
}
cpi->bwd_fb_idx = tmp;
#endif // CONFIG_EXT_REFS
+#if CONFIG_EXT_REFS
+ } else if (cpi->rc.is_src_frame_ext_arf && cm->show_existing_frame) {
+ // Deal with the special case for showing existing internal ALTREF_FRAME
+ // Refresh the LAST_FRAME with the ALTREF_FRAME and retire the LAST3_FRAME
+ // by updating the virtual indices.
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ int which_arf = gf_group->arf_ref_idx[gf_group->index];
+ int tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES-1];
+
+ shift_last_ref_frames(cpi);
+
+ cpi->lst_fb_idxes[0] = cpi->alt_fb_idx;
+ memcpy(cpi->interp_filter_selected[LAST_FRAME],
+ cpi->interp_filter_selected[ALTREF_FRAME + which_arf],
+ sizeof(cpi->interp_filter_selected[ALTREF_FRAME + which_arf]));
+
+ cpi->alt_fb_idx = tmp;
+ // We need to modify the mapping accordingly
+ cpi->arf_map[which_arf] = cpi->alt_fb_idx;
+#endif // CONFIG_EXT_REFS
} else { /* For non key/golden frames */
if (cpi->refresh_alt_ref_frame) {
int arf_idx = cpi->alt_fb_idx;
+ int which_arf = 0;
+#if CONFIG_EXT_REFS
+ if (cpi->oxcf.pass == 2) {
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ which_arf = gf_group->arf_update_idx[gf_group->index];
+ arf_idx = cpi->arf_map[which_arf];
+ }
+#else
if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) {
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
arf_idx = gf_group->arf_update_idx[gf_group->index];
}
-
+#endif // CONFIG_EXT_REFS
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[arf_idx], cm->new_fb_idx);
if (use_upsampled_ref)
uref_cnt_fb(cpi->upsampled_ref_bufs, &cpi->upsampled_ref_idx[arf_idx],
new_uidx);
- memcpy(cpi->interp_filter_selected[ALTREF_FRAME],
+ memcpy(cpi->interp_filter_selected[ALTREF_FRAME + which_arf],
cpi->interp_filter_selected[0],
sizeof(cpi->interp_filter_selected[0]));
}
uref_cnt_fb(cpi->upsampled_ref_bufs,
&cpi->upsampled_ref_idx[cpi->gld_fb_idx], new_uidx);
- if (!cpi->rc.is_src_frame_alt_ref)
+ if (!cpi->rc.is_src_frame_alt_ref) {
memcpy(cpi->interp_filter_selected[GOLDEN_FRAME],
cpi->interp_filter_selected[0],
sizeof(cpi->interp_filter_selected[0]));
- else
+ } else {
+ int which_arf = 0;
+#if CONFIG_EXT_REFS
+ if (cpi->oxcf.pass == 2) {
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ which_arf = gf_group->arf_update_idx[gf_group->index];
+ }
+#endif // CONFIG_EXT_REFS
memcpy(cpi->interp_filter_selected[GOLDEN_FRAME],
- cpi->interp_filter_selected[ALTREF_FRAME],
- sizeof(cpi->interp_filter_selected[ALTREF_FRAME]));
+ cpi->interp_filter_selected[ALTREF_FRAME + which_arf],
+ sizeof(cpi->interp_filter_selected[ALTREF_FRAME + which_arf]));
+ }
}
#if CONFIG_EXT_REFS
if (cpi->refresh_bwd_ref_frame) {
+ if (cpi->rc.is_bwd_ref_frame && cpi->num_extra_arfs) {
+ // We have swapped the virtual indices to allow bwd_ref_frame to use
+ // ALT0 as reference frame. We need to swap them back.
+ // NOTE: The ALT_REFs' are indexed reversely, and ALT0 refers to the
+ // farthest ALT_REF from the first frame in the gf group.
+ int tmp = cpi->arf_map[0];
+ cpi->arf_map[0] = cpi->bwd_fb_idx;
+ cpi->bwd_fb_idx = tmp;
+ }
ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->bwd_fb_idx],
cm->new_fb_idx);
if (use_upsampled_ref)
&cpi->upsampled_ref_idx[cpi->lst_fb_idxes[LAST_REF_FRAMES - 1]],
new_uidx);
- tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES - 1];
- for (ref_frame = LAST_REF_FRAMES - 1; ref_frame > 0; --ref_frame) {
- cpi->lst_fb_idxes[ref_frame] = cpi->lst_fb_idxes[ref_frame - 1];
+ tmp = cpi->lst_fb_idxes[LAST_REF_FRAMES-1];
+
+ shift_last_ref_frames(cpi);
- if (!cpi->rc.is_src_frame_alt_ref) {
- memcpy(cpi->interp_filter_selected[ref_frame],
- cpi->interp_filter_selected[ref_frame - 1],
- sizeof(cpi->interp_filter_selected[ref_frame - 1]));
- }
- }
cpi->lst_fb_idxes[0] = tmp;
if (!cpi->rc.is_src_frame_alt_ref) {
#if CONFIG_EXT_REFS
// Disable the use of BWDREF_FRAME for non-bipredictive frames.
- if (!(cpi->rc.is_bipred_frame || cpi->rc.is_last_bipred_frame))
+ if (!(cpi->rc.is_bipred_frame || cpi->rc.is_last_bipred_frame ||
+ (cpi->rc.is_bwd_ref_frame && cpi->num_extra_arfs)))
flags &= ~VPX_BWD_FLAG;
#endif // CONFIG_EXT_REFS
static void set_arf_sign_bias(VP10_COMP *cpi) {
VP10_COMMON *const cm = &cpi->common;
int arf_sign_bias;
-
+#if CONFIG_EXT_REFS
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ // The arf_sign_bias will be one for internal ARFs'
+ arf_sign_bias = cpi->rc.source_alt_ref_active &&
+ (!cpi->refresh_alt_ref_frame ||
+ (gf_group->rf_level[gf_group->index] == GF_ARF_LOW));
+#else
if ((cpi->oxcf.pass == 2) && cpi->multi_arf_allowed) {
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
arf_sign_bias = cpi->rc.source_alt_ref_active &&
arf_sign_bias =
(cpi->rc.source_alt_ref_active && !cpi->refresh_alt_ref_frame);
}
+#endif
cm->ref_frame_sign_bias[ALTREF_FRAME] = arf_sign_bias;
#if CONFIG_EXT_REFS
cm->ref_frame_sign_bias[BWDREF_FRAME] = cm->ref_frame_sign_bias[ALTREF_FRAME];
int ref_total[TOTAL_REFS_PER_FRAME] = { 0 };
MV_REFERENCE_FRAME ref;
int mask = 0;
+ int arf_idx = ALTREF_FRAME;
+
+#if CONFIG_EXT_REFS
+ // Get which arf used as ALTREF_FRAME
+ if (cpi->oxcf.pass == 2)
+ arf_idx += cpi->twopass.gf_group.arf_ref_idx[cpi->twopass.gf_group.index];
+#endif
+
if (cpi->common.last_frame_type == KEY_FRAME || cpi->refresh_alt_ref_frame)
return mask;
- for (ref = LAST_FRAME; ref <= ALTREF_FRAME; ++ref)
+
+#if CONFIG_EXT_REFS
+ for (ref = LAST_FRAME; ref < ALTREF_FRAME; ++ref)
for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter)
ref_total[ref] += cpi->interp_filter_selected[ref][ifilter];
+ for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter)
+ ref_total[ref] += cpi->interp_filter_selected[arf_idx][ifilter];
+#else
+ for (ref = LAST_FRAME; ref <= ALTREF_FRAME; ++ref)
+ for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter)
+ ref_total[ref] += cpi->interp_filter_selected[ref][ifilter];
+#endif
+
for (ifilter = EIGHTTAP_REGULAR; ifilter < SWITCHABLE_FILTERS; ++ifilter) {
if ((ref_total[LAST_FRAME] &&
cpi->interp_filter_selected[LAST_FRAME][ifilter] == 0) &&
ref_total[BWDREF_FRAME]) &&
#endif // CONFIG_EXT_REFS
(ref_total[ALTREF_FRAME] == 0 ||
- cpi->interp_filter_selected[ALTREF_FRAME][ifilter] * 50 <
- ref_total[ALTREF_FRAME]))
+ cpi->interp_filter_selected[arf_idx][ifilter] * 50 <
+ ref_total[ALTREF_FRAME]))
mask |= 1 << ifilter;
}
return mask;
const VP10EncoderConfig *const oxcf = &cpi->oxcf;
struct segmentation *const seg = &cm->seg;
TX_SIZE t;
-
set_ext_overrides(cpi);
vpx_clear_system_state();
if (cm->show_existing_frame) {
// NOTE(zoeliu): In BIDIR_PRED, the existing frame to show is the current
// BWDREF_FRAME in the reference frame buffer.
-
cm->frame_type = INTER_FRAME;
cm->show_frame = 1;
cpi->frame_flags = *frame_flags;
+ // In the case of show_existing frame, we will not send fresh flag
+ // to decoder. Any change in the reference frame buffer can be done by
+ // switching the virtual indices.
+
cpi->refresh_last_frame = 0;
cpi->refresh_golden_frame = 0;
cpi->refresh_bwd_ref_frame = 0;
const struct lookahead_entry *source) {
RATE_CONTROL *const rc = &cpi->rc;
+ // If pass == 2, the parameters set here will be reset in
+ // vp10_rc_get_second_pass_params()
+
if (cpi->oxcf.pass == 2) {
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
rc->is_src_frame_alt_ref =
- (gf_group->update_type[gf_group->index] == OVERLAY_UPDATE);
+#if CONFIG_EXT_REFS
+ (gf_group->update_type[gf_group->index] == INTNL_OVERLAY_UPDATE) ||
+#endif
+ (gf_group->update_type[gf_group->index] == OVERLAY_UPDATE);
} else {
rc->is_src_frame_alt_ref =
cpi->alt_ref_source && (source == cpi->alt_ref_source);
return -1;
}
cpi->Source = &source->img;
-
// TODO(zoeliu): To track down to determine whether it's needed to adjust
// the frame rate.
*time_stamp = source->ts_start;
vpx_clear_system_state();
cm->show_existing_frame = 0;
-
return 0;
}
#endif // CONFIG_EXT_REFS
cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
+#if CONFIG_EXT_REFS
+ if (oxcf->pass == 2) {
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+ cpi->alt_fb_idx = cpi->arf_map[gf_group->arf_ref_idx[gf_group->index]];
+ }
+#else
if (cpi->multi_arf_allowed) {
if (cm->frame_type == KEY_FRAME) {
init_buffer_indices(cpi);
cpi->alt_fb_idx = gf_group->arf_ref_idx[gf_group->index];
}
}
-
+#endif
// Start with a 0 size frame.
*size = 0;
#if CONFIG_EXT_REFS
int refresh_frame_mask;
int existing_fb_idx_to_show;
- int is_arf_filter_off;
+ int is_arf_filter_off[MAX_EXT_ARFS + 1];
+ int num_extra_arfs;
+ int arf_map[MAX_EXT_ARFS + 1];
#endif // CONFIG_EXT_REFS
#if CONFIG_GLOBAL_MOTION
int global_motion_used[TOTAL_REFS_PER_FRAME];
0);
}
+#if !CONFIG_EXT_REFS
// Current limit on maximum number of active arfs in a GF/ARF group.
#define MAX_ACTIVE_ARFS 2
#define ARF_SLOT1 2
arf_buffer_indices[0] = ARF_SLOT1;
arf_buffer_indices[1] = ARF_SLOT2;
}
+#endif
static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits,
double group_error, int gf_arf_bits) {
double modified_err = 0.0;
double err_fraction;
int mid_boost_bits = 0;
+#if !CONFIG_EXT_REFS
int mid_frame_idx;
unsigned char arf_buffer_indices[MAX_ACTIVE_ARFS];
-
+#endif
#if CONFIG_EXT_REFS
// The use of bi-predictive frames are only enabled when following 3
// conditions are met:
(rc->baseline_gf_interval - rc->source_alt_ref_pending);
int bipred_group_end = 0;
int bipred_frame_index = 0;
+ int arf_pos[MAX_EXT_ARFS+1];
+ const unsigned char ext_arf_interval = (unsigned char)
+ (rc->baseline_gf_interval / (cpi->num_extra_arfs + 1) - 1);
+ int which_arf = cpi->num_extra_arfs;
+ int subgroup_interval[MAX_EXT_ARFS+1];
+ int ext_arf_boost[MAX_EXT_ARFS];
+ int is_sg_bipred_enabled = is_bipred_enabled;
+ int accumulative_subgroup_interval = 0;
#endif // CONFIG_EXT_REFS
+#if CONFIG_EXT_REFS
+ vp10_zero_array(ext_arf_boost, MAX_EXT_ARFS);
+#endif
+
key_frame = cpi->common.frame_type == KEY_FRAME;
+#if !CONFIG_EXT_REFS
get_arf_buffer_indices(arf_buffer_indices);
+#endif
// For key frames the frame target rate is already set and it
// is also the golden frame.
gf_group->rf_level[frame_index] = GF_ARF_STD;
gf_group->bit_allocation[frame_index] = gf_arf_bits;
}
+#if CONFIG_EXT_REFS
+ gf_group->arf_update_idx[frame_index] = 0;
+ gf_group->arf_ref_idx[frame_index] = 0;
+#else
gf_group->arf_update_idx[frame_index] = arf_buffer_indices[0];
gf_group->arf_ref_idx[frame_index] = arf_buffer_indices[0];
-
+#endif
// Step over the golden frame / overlay frame
if (EOF == input_stats(twopass, &frame_stats)) return;
}
gf_group->arf_src_offset[frame_index] =
(unsigned char)(rc->baseline_gf_interval - 1);
+#if CONFIG_EXT_REFS
+ gf_group->arf_update_idx[frame_index] = 0;
+ gf_group->arf_ref_idx[frame_index] = 0;
+#else
gf_group->arf_update_idx[frame_index] = arf_buffer_indices[0];
gf_group->arf_ref_idx[frame_index] =
arf_buffer_indices[cpi->multi_arf_last_grp_enabled &&
rc->source_alt_ref_active];
-
+#endif // CONFIG_EXT_REFS && CONFIG_EXT_ARFS
#if CONFIG_EXT_REFS
gf_group->bidir_pred_enabled[frame_index] = 0;
gf_group->brf_src_offset[frame_index] = 0;
// NOTE: "bidir_pred_frame_index" stays unchanged for ARF_UPDATE frames.
#endif // CONFIG_EXT_REFS
+#if CONFIG_EXT_REFS
+ // Work out the ARFs' positions in this gf group
+ // NOTE(weitinglin): ALT_REFs' are indexed inversely, but coded in display
+ // order (except for the original ARF). In the example of three ALT_REF's,
+ // We index ALTREF's as: KEY ----- ALT2 ----- ALT1 ----- ALT0
+ // but code them in the following order:
+ // KEY-ALT0-ALT2 ----- OVERLAY2-ALT1 ----- OVERLAY1 ----- OVERLAY0
+ arf_pos[0] = frame_index + cpi->num_extra_arfs +
+ gf_group->arf_src_offset[1] + 1;
+ for (i = 0; i < cpi->num_extra_arfs; ++i) {
+ arf_pos[i + 1] = frame_index +
+ (cpi->num_extra_arfs - i)*(ext_arf_interval + 2);
+ subgroup_interval[i] = arf_pos[i] - arf_pos[i + 1] - (i == 0 ? 1 : 2);
+ }
+ subgroup_interval[cpi->num_extra_arfs] = arf_pos[cpi->num_extra_arfs] -
+ frame_index - (cpi->num_extra_arfs == 0 ? 1 : 2);
+#endif // CONFIG_EXT_REFS
+
++frame_index;
+#if CONFIG_EXT_REFS
+ // Insert an extra ARF
+ if (cpi->num_extra_arfs) {
+ gf_group->update_type[frame_index] = ARF_UPDATE;
+ // Note (weitinglin): GF_ARF_LOW is also used as an identifier
+ // for internal ALT_REF's:
+ gf_group->rf_level[frame_index] = GF_ARF_LOW;
+ gf_group->arf_src_offset[frame_index] = ext_arf_interval;
+ gf_group->arf_update_idx[frame_index] = which_arf;
+ gf_group->arf_ref_idx[frame_index] = 0;
+ ++frame_index;
+ }
+ accumulative_subgroup_interval += subgroup_interval[cpi->num_extra_arfs];
+#else
if (cpi->multi_arf_enabled) {
// Set aside a slot for a level 1 arf.
gf_group->update_type[frame_index] = ARF_UPDATE;
gf_group->arf_ref_idx[frame_index] = arf_buffer_indices[0];
++frame_index;
}
+#endif // CONFIG_EXT_ARFS
}
+#if !CONFIG_EXT_REFS
// Define middle frame
mid_frame_idx = frame_index + (rc->baseline_gf_interval >> 1) - 1;
+#endif
// Allocate bits to the other frames in the group.
for (i = 0; i < rc->baseline_gf_interval - rc->source_alt_ref_pending; ++i) {
+#if !CONFIG_EXT_REFS
int arf_idx = 0;
+#endif
if (EOF == input_stats(twopass, &frame_stats)) break;
modified_err = calculate_modified_err(cpi, twopass, oxcf, &frame_stats);
if (rc->source_alt_ref_pending && cpi->multi_arf_enabled) {
mid_boost_bits += (target_frame_size >> 4);
target_frame_size -= (target_frame_size >> 4);
-
+#if !CONFIG_EXT_REFS
if (frame_index <= mid_frame_idx) arf_idx = 1;
+#endif
}
+#if CONFIG_EXT_REFS
+ gf_group->arf_update_idx[frame_index] = which_arf;
+ gf_group->arf_ref_idx[frame_index] = which_arf;
+#else
gf_group->arf_update_idx[frame_index] = arf_buffer_indices[arf_idx];
gf_group->arf_ref_idx[frame_index] = arf_buffer_indices[arf_idx];
-
+#endif // CONFIG_EXT_REFS
target_frame_size =
clamp(target_frame_size, 0, VPXMIN(max_bits, (int)total_group_bits));
#if CONFIG_EXT_REFS
+ // If we are going to have ARFs, check if we can have BWDREF in this
+ // subgroup.
+ if (rc->source_alt_ref_pending) {
+ is_sg_bipred_enabled = is_bipred_enabled &&
+ (subgroup_interval[which_arf] > rc->bipred_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 (is_bipred_enabled && !bipred_group_end) {
+ if (is_sg_bipred_enabled && !bipred_group_end) {
const int cur_brf_src_offset = rc->bipred_group_interval - 1;
// --- BRF_UPDATE ---
// included within the current golden frame group.
// In addition, we need to avoid coding a BRF right before an ARF.
if (bipred_frame_index == 1 &&
- (i + 2 + cur_brf_src_offset) >=
- (rc->baseline_gf_interval - rc->source_alt_ref_pending)) {
- bipred_group_end = 1;
+ (i + 2 + cur_brf_src_offset) >= accumulative_subgroup_interval) {
+ bipred_group_end = 1;
}
} else {
#endif // CONFIG_EXT_REFS
#endif // CONFIG_EXT_REFS
++frame_index;
+#if CONFIG_EXT_REFS
+ // Check if we need to update the ARF
+ if (cpi->num_extra_arfs && frame_index > arf_pos[which_arf]) {
+ --which_arf;
+ accumulative_subgroup_interval += subgroup_interval[which_arf] + 1;
+ // Meet the new subgroup. Reset the bipred_group_end flag;
+ bipred_group_end = 0;
+ // Insert another extra ARF after the overlay frame
+ if (which_arf) {
+ gf_group->update_type[frame_index] = ARF_UPDATE;
+ gf_group->rf_level[frame_index] = GF_ARF_LOW;
+ gf_group->arf_src_offset[frame_index] = ext_arf_interval;
+ gf_group->arf_update_idx[frame_index] = which_arf;
+ gf_group->arf_ref_idx[frame_index] = 0;
+ ++frame_index;
+ }
+ }
+#endif
}
// Note:
// We need to configure the frame at the end of the sequence + 1 that will be
// the start frame for the next group. Otherwise prior to the call to
// vp10_rc_get_second_pass_params() the data will be undefined.
+#if CONFIG_EXT_REFS
+ gf_group->arf_update_idx[frame_index] = 0;
+ gf_group->arf_ref_idx[frame_index] = 0;
+#else
gf_group->arf_update_idx[frame_index] = arf_buffer_indices[0];
gf_group->arf_ref_idx[frame_index] = arf_buffer_indices[0];
-
+#endif
if (rc->source_alt_ref_pending) {
gf_group->update_type[frame_index] = OVERLAY_UPDATE;
gf_group->rf_level[frame_index] = INTER_NORMAL;
+#if CONFIG_EXT_REFS
+ if (cpi->num_extra_arfs) {
+ for (i = cpi->num_extra_arfs; i > 0; --i) {
+ int arf_pos_in_gf = (i == cpi->num_extra_arfs ? 2 : arf_pos[i + 1] + 1);
+ gf_group->bit_allocation[arf_pos_in_gf] =
+ gf_group->bit_allocation[arf_pos[i]];
+ gf_group->update_type[arf_pos[i]] = INTNL_OVERLAY_UPDATE;
+ gf_group->bit_allocation[arf_pos[i]] = 0;
+ gf_group->rf_level[arf_pos[i]] = INTER_LOW;
+ }
+ }
+#endif
+#if !CONFIG_EXT_REFS
// Final setup for second arf and its overlay.
if (cpi->multi_arf_enabled) {
gf_group->bit_allocation[2] =
gf_group->update_type[mid_frame_idx] = OVERLAY_UPDATE;
gf_group->bit_allocation[mid_frame_idx] = 0;
}
+#endif
} else {
gf_group->update_type[frame_index] = GF_UPDATE;
gf_group->rf_level[frame_index] = GF_ARF_STD;
// Note whether multi-arf was enabled this group for next time.
cpi->multi_arf_last_grp_enabled = cpi->multi_arf_enabled;
}
-
// Analyse and define a gf/arf group.
static void define_gf_group(VP10_COMP *cpi, FIRSTPASS_STATS *this_frame) {
VP10_COMMON *const cm = &cpi->common;
// Set the interval until the next gf.
rc->baseline_gf_interval = i - (is_key_frame || rc->source_alt_ref_pending);
+#if CONFIG_EXT_REFS
+ // Compute how many extra alt_refs we can have
+ cpi->num_extra_arfs =
+ get_number_of_extra_arfs(rc->baseline_gf_interval,
+ rc->source_alt_ref_pending);
+ // Currently at maximum two extra ARFs' are allowed
+ assert(cpi->num_extra_arfs <= 2);
+#endif
+
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
#if CONFIG_EXT_REFS
cpi->rc.is_bwd_ref_frame = 0;
cpi->rc.is_last_bipred_frame = 0;
cpi->rc.is_bipred_frame = 0;
+ cpi->rc.is_src_frame_ext_arf = 0;
#endif // CONFIG_EXT_REFS
switch (twopass->gf_group.update_type[twopass->gf_group.index]) {
- case KF_UPDATE: cpi->refresh_last_frame = 1; cpi->refresh_golden_frame = 1;
+ case KF_UPDATE:
+ cpi->refresh_last_frame = 1;
+ cpi->refresh_golden_frame = 1;
#if CONFIG_EXT_REFS
cpi->refresh_bwd_ref_frame = 1;
#endif // CONFIG_EXT_REFS
cpi->refresh_alt_ref_frame = 1;
break;
- case LF_UPDATE: cpi->refresh_last_frame = 1; cpi->refresh_golden_frame = 0;
+ case LF_UPDATE:
+ cpi->refresh_last_frame = 1;
+ cpi->refresh_golden_frame = 0;
#if CONFIG_EXT_REFS
cpi->refresh_bwd_ref_frame = 0;
#endif // CONFIG_EXT_REFS
cpi->refresh_alt_ref_frame = 0;
break;
- case GF_UPDATE: cpi->refresh_last_frame = 1; cpi->refresh_golden_frame = 1;
+ case GF_UPDATE:
+ cpi->refresh_last_frame = 1;
+ cpi->refresh_golden_frame = 1;
#if CONFIG_EXT_REFS
cpi->refresh_bwd_ref_frame = 0;
#endif // CONFIG_EXT_REFS
cpi->rc.is_src_frame_alt_ref = 1;
break;
- case ARF_UPDATE: cpi->refresh_last_frame = 0; cpi->refresh_golden_frame = 0;
+ case ARF_UPDATE:
+ cpi->refresh_last_frame = 0;
+ cpi->refresh_golden_frame = 0;
#if CONFIG_EXT_REFS
- cpi->refresh_bwd_ref_frame = 0;
+ cpi->refresh_bwd_ref_frame = 1;
#endif // CONFIG_EXT_REFS
cpi->refresh_alt_ref_frame = 1;
break;
cpi->refresh_bwd_ref_frame = 1;
cpi->refresh_alt_ref_frame = 0;
cpi->rc.is_bwd_ref_frame = 1;
+ if (cpi->num_extra_arfs) {
+ // Allow BRF uses the farthest ALT_REF (ALT0) as BWD_REF by swapping
+ // the virtual indices.
+ // NOTE: The indices will be swapped back after this frame is encoded
+ // (in vp10_update_reference_frames()).
+ int tmp = cpi->bwd_fb_idx;
+ cpi->bwd_fb_idx = cpi->arf_map[0];
+ cpi->arf_map[0] = tmp;
+ }
break;
-
case LAST_BIPRED_UPDATE:
cpi->refresh_last_frame = 0;
cpi->refresh_golden_frame = 0;
cpi->refresh_alt_ref_frame = 0;
cpi->rc.is_bipred_frame = 1;
break;
+
+ case INTNL_OVERLAY_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_src_frame_alt_ref = 1;
+ cpi->rc.is_src_frame_ext_arf = 1;
+ break;
#endif // CONFIG_EXT_REFS
default: assert(0); break;
// 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
+#define BFG_INTERVAL 2
+// The maximum number of extra ALT_REF's
+// NOTE: This number cannot be greater than 2 or the reference frame buffer will
+// overflow.
+#define MAX_EXT_ARFS 2
+#define MIN_EXT_ARF_INTERVAL 4
#endif // CONFIG_EXT_REFS
#define VLOW_MOTION_THRESHOLD 950
ARF_UPDATE = 3,
OVERLAY_UPDATE = 4,
#if CONFIG_EXT_REFS
- BRF_UPDATE = 5, // Backward Reference Frame
- LAST_BIPRED_UPDATE = 6, // Last Bi-predictive Frame
- BIPRED_UPDATE = 7, // Bi-predictive Frame, but not the last one
- FRAME_UPDATE_TYPES = 8
+ BRF_UPDATE = 5, // Backward Reference Frame
+ LAST_BIPRED_UPDATE = 6, // Last Bi-predictive Frame
+ BIPRED_UPDATE = 7, // Bi-predictive Frame, but not the last one
+ INTNL_OVERLAY_UPDATE = 8, // Internal Overlay Frame
+ FRAME_UPDATE_TYPES = 9
#else
FRAME_UPDATE_TYPES = 5
#endif // CONFIG_EXT_REFS
void vp10_calculate_coded_size(struct VP10_COMP *cpi, int *scaled_frame_width,
int *scaled_frame_height);
+#if CONFIG_EXT_REFS
+static inline int get_number_of_extra_arfs(int interval, int arf_pending) {
+ if (arf_pending && MAX_EXT_ARFS > 0)
+ return interval >= MIN_EXT_ARF_INTERVAL*(MAX_EXT_ARFS+1) ? MAX_EXT_ARFS :
+ interval >= MIN_EXT_ARF_INTERVAL*MAX_EXT_ARFS ? MAX_EXT_ARFS - 1 : 0;
+ else
+ return 0;
+}
+#endif
+
#ifdef __cplusplus
} // extern "C"
#endif
#define MAX_BPB_FACTOR 50
#define FRAME_OVERHEAD_BITS 200
-
#if CONFIG_VP9_HIGHBITDEPTH
#define ASSIGN_MINQ_TABLE(bit_depth, name) \
do { \
#if CONFIG_EXT_REFS
0.80, // INTER_LOW
1.50, // INTER_HIGH
+ 1.25, // GF_ARF_LOW
#else
1.00, // INTER_HIGH
-#endif // CONFIG_EXT_REFS
1.50, // GF_ARF_LOW
+#endif // CONFIG_EXT_REFS
2.00, // GF_ARF_STD
2.00, // KF_STD
};
#if CONFIG_EXT_REFS
// Update the Golden frame usage counts.
- // Wei-Ting: If we use show_existing_frame for an OVERLAY frame, only the
- // virtual indices for the reference frame will be updated and
- // cpi->refresh_golden_frame will still be zero.
+ // NOTE(weitinglin): If we use show_existing_frame for an OVERLAY frame,
+ // only the virtual indices for the reference frame will be
+ // updated and cpi->refresh_golden_frame will still be zero.
if (cpi->refresh_golden_frame || rc->is_src_frame_alt_ref) {
#else
// Update the Golden frame usage counts.
if (cpi->refresh_golden_frame) {
#endif
- // this frame refreshes means next frames don't unless specified by user
- rc->frames_since_golden = 0;
+#if CONFIG_EXT_REFS
+ // We will not use internal overlay frames to replace the golden frame
+ if (!rc->is_src_frame_ext_arf)
+#endif
+ // this frame refreshes means next frames don't unless specified by user
+ rc->frames_since_golden = 0;
// If we are not using alt ref in the up and coming group clear the arf
// active flag. In multi arf group case, if the index is not 0 then
int is_bwd_ref_frame;
int is_last_bipred_frame;
int is_bipred_frame;
+ int is_src_frame_ext_arf;
#endif // CONFIG_EXT_REFS
int avg_frame_bandwidth; // Average frame size target for clip
#if CONFIG_EXT_REFS
// TODO(zoeliu): To adjust further following factor values.
128, 128, 128
+ // TODO(weitinglin): We should investigate if the values should be the same
+ // as the value used by OVERLAY frame
+ , 144
#endif // CONFIG_EXT_REFS
};
int frames_to_blur_forward;
struct scale_factors sf;
YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS] = { NULL };
+#if CONFIG_EXT_REFS
+ const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
+#endif
// Apply context specific adjustments to the arnr filter parameters.
adjust_arnr_filter(cpi, distance, rc->gfu_boost, &frames_to_blur, &strength);
+ // TODO(weitinglin): Currently, we enforce the filtering strength on
+ // extra ARFs' to be zeros. We should investigate in which
+ // case it is more beneficial to use non-zero strength
+ // filtering.
#if CONFIG_EXT_REFS
- if (strength == 0 && frames_to_blur == 1)
- cpi->is_arf_filter_off = 1;
- else
- cpi->is_arf_filter_off = 0;
+ if (gf_group->rf_level[gf_group->index] == GF_ARF_LOW) {
+ strength = 0;
+ frames_to_blur = 1;
+ }
+#endif
+
+#if CONFIG_EXT_REFS
+ if (strength == 0 && frames_to_blur == 1) {
+ cpi->is_arf_filter_off[gf_group->arf_update_idx[gf_group->index]] = 1;
+ } else {
+ cpi->is_arf_filter_off[gf_group->arf_update_idx[gf_group->index]] = 0;
+ }
#endif
+
frames_to_blur_backward = (frames_to_blur / 2);
frames_to_blur_forward = ((frames_to_blur - 1) / 2);
start_frame = distance + frames_to_blur_forward;