diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index 81d8991f66e6144acbb7fad91246d67d7cf3da5f..9dc283a2f992a87aeadea2967f5be26fa516d0d1 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -2649,6 +2649,7 @@ static void write_tile_info(const VP10_COMMON *const cm, 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; @@ -2663,8 +2664,12 @@ static int get_refresh_mask(VP10_COMP *cpi) { // 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 @@ -2683,10 +2688,15 @@ static int get_refresh_mask(VP10_COMP *cpi) { 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); } diff --git a/vp10/encoder/bitstream.h b/vp10/encoder/bitstream.h index 615c4e482dcbc9a481a6dfd0cc6447dd3d35337c..5b6d8f0372b0a0b74158a00a74d509702d4d2714 100644 --- a/vp10/encoder/bitstream.h +++ b/vp10/encoder/bitstream.h @@ -23,11 +23,13 @@ void vp10_encode_token_init(void); 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 diff --git a/vp10/encoder/encodeframe.c b/vp10/encoder/encodeframe.c index 25e8ac5168fb1f09450a8f6e349f28c479e20a56..d1f019a7d70bf44629556342527a09ecca42c95a 100644 --- a/vp10/encoder/encodeframe.c +++ b/vp10/encoder/encodeframe.c @@ -4289,7 +4289,13 @@ static void reset_skip_tx_size(VP10_COMMON *cm, TX_SIZE max_tx_size) { 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; diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c index 823c8610aaa0848b5051eaa2d871d412c22f6576..32a6ae37bbe55ecf2cb1527048f51e2399461b10 100644 --- a/vp10/encoder/encoder.c +++ b/vp10/encoder/encoder.c @@ -79,7 +79,6 @@ // now so that HIGH_PRECISION is always // chosen. // #define OUTPUT_YUV_REC - #ifdef OUTPUT_YUV_DENOISED FILE *yuv_denoised_file = NULL; #endif @@ -897,6 +896,8 @@ static void init_buffer_indices(VP10_COMP *cpi) { 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; @@ -2726,7 +2727,7 @@ static void check_show_existing_frame(VP10_COMP *cpi) { 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 @@ -2734,19 +2735,21 @@ static void check_show_existing_frame(VP10_COMP *cpi) { 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) { @@ -3063,6 +3066,27 @@ static void dump_ref_frame_images(VP10_COMP *cpi) { } #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; @@ -3087,10 +3111,10 @@ void vp10_update_reference_frames(VP10_COMP *cpi) { 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) { @@ -3134,23 +3158,21 @@ void vp10_update_reference_frames(VP10_COMP *cpi) { 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], @@ -3159,20 +3181,48 @@ void vp10_update_reference_frames(VP10_COMP *cpi) { } 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])); } @@ -3184,18 +3234,35 @@ void vp10_update_reference_frames(VP10_COMP *cpi) { 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) @@ -3267,16 +3334,10 @@ void vp10_update_reference_frames(VP10_COMP *cpi) { &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) { @@ -4272,7 +4333,8 @@ static int get_ref_frame_flags(const VP10_COMP *cpi) { #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 @@ -4348,7 +4410,13 @@ YV12_BUFFER_CONFIG *vp10_scale_if_required(VP10_COMMON *cm, 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 && @@ -4358,6 +4426,7 @@ static void set_arf_sign_bias(VP10_COMP *cpi) { 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]; @@ -4369,12 +4438,30 @@ static int setup_interp_filter_search_mask(VP10_COMP *cpi) { 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) && @@ -4395,8 +4482,8 @@ static int setup_interp_filter_search_mask(VP10_COMP *cpi) { 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; @@ -4465,7 +4552,6 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi, size_t *size, const VP10EncoderConfig *const oxcf = &cpi->oxcf; struct segmentation *const seg = &cm->seg; TX_SIZE t; - set_ext_overrides(cpi); vpx_clear_system_state(); @@ -4484,11 +4570,14 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi, size_t *size, 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; @@ -4953,10 +5042,16 @@ static void check_src_altref(VP10_COMP *cpi, 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); @@ -5143,7 +5238,6 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags, 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; @@ -5187,7 +5281,6 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags, vpx_clear_system_state(); cm->show_existing_frame = 0; - return 0; } #endif // CONFIG_EXT_REFS @@ -5310,6 +5403,12 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags, 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); @@ -5318,7 +5417,7 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags, cpi->alt_fb_idx = gf_group->arf_ref_idx[gf_group->index]; } } - +#endif // Start with a 0 size frame. *size = 0; diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h index 1c08b492c472bf9b6cdee8244d3c6f617598db12..fca8b6fbecde625cd984b4fe51a7c2b826c35eda 100644 --- a/vp10/encoder/encoder.h +++ b/vp10/encoder/encoder.h @@ -622,7 +622,9 @@ typedef struct VP10_COMP { #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]; diff --git a/vp10/encoder/firstpass.c b/vp10/encoder/firstpass.c index 317b689422cc0a497fa4e8e9a26831541b97b2a7..1d1bf520165c64d0e0baadd7c39b9e4993a5d833 100644 --- a/vp10/encoder/firstpass.c +++ b/vp10/encoder/firstpass.c @@ -1548,6 +1548,7 @@ static int calculate_boost_bits(int frame_count, int boost, 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 @@ -1559,6 +1560,7 @@ static void get_arf_buffer_indices(unsigned char *arf_buffer_indices) { 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) { @@ -1576,9 +1578,10 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_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: @@ -1592,11 +1595,25 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits, (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. @@ -1610,9 +1627,13 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits, 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; } @@ -1641,19 +1662,55 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits, 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; @@ -1664,14 +1721,19 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits, 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); @@ -1686,21 +1748,32 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits, 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 --- @@ -1727,9 +1800,8 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits, // 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 @@ -1765,19 +1837,54 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits, #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] = @@ -1785,6 +1892,7 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits, 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; @@ -1797,7 +1905,6 @@ static void allocate_gf_group_bits(VP10_COMP *cpi, int64_t gf_group_bits, // 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; @@ -2000,6 +2107,15 @@ static void define_gf_group(VP10_COMP *cpi, FIRSTPASS_STATS *this_frame) { // 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 @@ -2445,24 +2561,31 @@ static void configure_buffer_updates(VP10_COMP *cpi) { 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 @@ -2479,9 +2602,11 @@ static void configure_buffer_updates(VP10_COMP *cpi) { 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; @@ -2493,8 +2618,16 @@ static void configure_buffer_updates(VP10_COMP *cpi) { 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; @@ -2510,6 +2643,15 @@ static void configure_buffer_updates(VP10_COMP *cpi) { 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; diff --git a/vp10/encoder/firstpass.h b/vp10/encoder/firstpass.h index 3642cfda68110ff5029ff778b370981d126b85fe..156fa2cc579d4ee48b222ccd1bddfe86ea90b6f9 100644 --- a/vp10/encoder/firstpass.h +++ b/vp10/encoder/firstpass.h @@ -43,7 +43,12 @@ typedef struct { // 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 @@ -80,10 +85,11 @@ typedef enum { 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 @@ -176,6 +182,16 @@ void vp10_init_subsampling(struct VP10_COMP *cpi); 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 diff --git a/vp10/encoder/ratectrl.c b/vp10/encoder/ratectrl.c index 6b077c7884684873ab567931a3afd90267713311..c7e4348727a8e31c3376faf909f155756b80381c 100644 --- a/vp10/encoder/ratectrl.c +++ b/vp10/encoder/ratectrl.c @@ -42,7 +42,6 @@ #define MAX_BPB_FACTOR 50 #define FRAME_OVERHEAD_BITS 200 - #if CONFIG_VP9_HIGHBITDEPTH #define ASSIGN_MINQ_TABLE(bit_depth, name) \ do { \ @@ -917,10 +916,11 @@ int vp10_frame_type_qdelta(const VP10_COMP *cpi, int rf_level, int q) { #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 }; @@ -1185,16 +1185,20 @@ static void update_golden_frame_stats(VP10_COMP *cpi) { #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 diff --git a/vp10/encoder/ratectrl.h b/vp10/encoder/ratectrl.h index ed9d6fbf98f9acea11351388267104d4344d946b..18965833676008ae1bed9db48599ee3dce71b6ad 100644 --- a/vp10/encoder/ratectrl.h +++ b/vp10/encoder/ratectrl.h @@ -110,6 +110,7 @@ typedef struct { 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 diff --git a/vp10/encoder/rd.c b/vp10/encoder/rd.c index 54089480551c60b339a3476670d54939901d035b..12a1fbf8c25b2b3ad44f40434f733f41c4ffd99b 100644 --- a/vp10/encoder/rd.c +++ b/vp10/encoder/rd.c @@ -223,6 +223,9 @@ static const int rd_frame_type_factor[FRAME_UPDATE_TYPES] = { #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 }; diff --git a/vp10/encoder/temporal_filter.c b/vp10/encoder/temporal_filter.c index cc484a8ea6a6115ffa74917f2d0fab3824f5e589..691e1572d7bb06171c71f2757ccaa67b65d90649 100644 --- a/vp10/encoder/temporal_filter.c +++ b/vp10/encoder/temporal_filter.c @@ -625,15 +625,31 @@ void vp10_temporal_filter(VP10_COMP *cpi, int distance) { 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;