From a66da313805f41076fd05358a65c1084f646f348 Mon Sep 17 00:00:00 2001 From: Jerome Jiang Date: Mon, 6 Aug 2018 11:37:43 -0700 Subject: [PATCH] vp9-svc: Update to SET/GET_SVC_REF_FRAME_CONFIG api Add update_buffer_slot to SVC API to allow for refreshing any of the 8 reference buffers. Remove frame_flags from the struct. Remove svc tests from vp8 build. BUG=b/112292577 Change-Id: I0551c349d2b311227245a8ed1639cdbbaf5bc5db --- examples/vp9_spatial_svc_encoder.c | 83 +++++++++++++------- test/svc_datarate_test.cc | 74 +++++++++++------- test/test.mk | 8 +- vp9/encoder/vp9_bitstream.c | 3 + vp9/encoder/vp9_encoder.c | 12 ++- vp9/encoder/vp9_svc_layercontext.c | 120 ++++++++++++++++++++--------- vp9/encoder/vp9_svc_layercontext.h | 10 ++- vp9/vp9_cx_iface.c | 13 +++- vpx/vp8cx.h | 11 ++- 9 files changed, 217 insertions(+), 117 deletions(-) diff --git a/examples/vp9_spatial_svc_encoder.c b/examples/vp9_spatial_svc_encoder.c index f22eb4e6f..266ba2656 100644 --- a/examples/vp9_spatial_svc_encoder.c +++ b/examples/vp9_spatial_svc_encoder.c @@ -596,36 +596,11 @@ void set_frame_flags_bypass_mode(int tl, int num_spatial_layers, int is_key_frame, vpx_svc_ref_frame_config_t *ref_frame_config) { int sl; + for (sl = 0; sl < num_spatial_layers; ++sl) + ref_frame_config->update_buffer_slot[sl] = 0; + for (sl = 0; sl < num_spatial_layers; ++sl) { - if (!tl) { - if (!sl) { - ref_frame_config->frame_flags[sl] = - VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | - VP8_EFLAG_NO_UPD_ARF; - } else { - if (is_key_frame) { - ref_frame_config->frame_flags[sl] = - VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | - VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; - } else { - ref_frame_config->frame_flags[sl] = - VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF; - } - } - } else if (tl == 1) { - if (!sl) { - ref_frame_config->frame_flags[sl] = - VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | - VP8_EFLAG_NO_UPD_GF; - } else { - ref_frame_config->frame_flags[sl] = - VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; - if (sl == num_spatial_layers - 1) - ref_frame_config->frame_flags[sl] = - VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_ARF | - VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; - } - } + // Set the buffer idx. if (tl == 0) { ref_frame_config->lst_fb_idx[sl] = sl; if (sl) { @@ -644,6 +619,56 @@ void set_frame_flags_bypass_mode(int tl, int num_spatial_layers, ref_frame_config->gld_fb_idx[sl] = num_spatial_layers + sl - 1; ref_frame_config->alt_fb_idx[sl] = num_spatial_layers + sl; } + // Set the reference and update flags. + if (!tl) { + if (!sl) { + // Base spatial and base temporal (sl = 0, tl = 0) + ref_frame_config->reference_last[sl] = 1; + ref_frame_config->reference_golden[sl] = 0; + ref_frame_config->reference_alt_ref[sl] = 0; + ref_frame_config->update_buffer_slot[sl] |= + 1 << ref_frame_config->lst_fb_idx[sl]; + } else { + if (is_key_frame) { + ref_frame_config->reference_last[sl] = 1; + ref_frame_config->reference_golden[sl] = 0; + ref_frame_config->reference_alt_ref[sl] = 0; + ref_frame_config->update_buffer_slot[sl] |= + 1 << ref_frame_config->gld_fb_idx[sl]; + } else { + // Non-zero spatiall layer. + ref_frame_config->reference_last[sl] = 1; + ref_frame_config->reference_golden[sl] = 1; + ref_frame_config->reference_alt_ref[sl] = 1; + ref_frame_config->update_buffer_slot[sl] |= + 1 << ref_frame_config->lst_fb_idx[sl]; + } + } + } else if (tl == 1) { + if (!sl) { + // Base spatial and top temporal (tl = 1) + ref_frame_config->reference_last[sl] = 1; + ref_frame_config->reference_golden[sl] = 0; + ref_frame_config->reference_alt_ref[sl] = 0; + ref_frame_config->update_buffer_slot[sl] |= + 1 << ref_frame_config->alt_fb_idx[sl]; + } else { + // Non-zero spatial. + if (sl < num_spatial_layers - 1) { + ref_frame_config->reference_last[sl] = 1; + ref_frame_config->reference_golden[sl] = 1; + ref_frame_config->reference_alt_ref[sl] = 0; + ref_frame_config->update_buffer_slot[sl] |= + 1 << ref_frame_config->alt_fb_idx[sl]; + } else if (sl == num_spatial_layers - 1) { + // Top spatial and top temporal (non-reference -- doesn't update any + // reference buffers) + ref_frame_config->reference_last[sl] = 1; + ref_frame_config->reference_golden[sl] = 1; + ref_frame_config->reference_alt_ref[sl] = 0; + } + } + } } } diff --git a/test/svc_datarate_test.cc b/test/svc_datarate_test.cc index c72df5093..661858070 100644 --- a/test/svc_datarate_test.cc +++ b/test/svc_datarate_test.cc @@ -15,6 +15,7 @@ #include "test/svc_test.h" #include "test/util.h" #include "test/y4m_video_source.h" +#include "vp9/common/vp9_onyxc_int.h" #include "vpx/vpx_codec.h" #include "vpx_ports/bitops.h" @@ -69,34 +70,10 @@ class DatarateOnePassCbrSvc : public ::svc_test::OnePassCbrSvc { void set_frame_flags_bypass_mode( int tl, int num_spatial_layers, int is_key_frame, vpx_svc_ref_frame_config_t *ref_frame_config) { + for (int sl = 0; sl < num_spatial_layers; ++sl) + ref_frame_config->update_buffer_slot[sl] = 0; + for (int sl = 0; sl < num_spatial_layers; ++sl) { - if (!tl) { - if (!sl) { - ref_frame_config->frame_flags[sl] = - VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | - VP8_EFLAG_NO_UPD_ARF; - } else { - if (is_key_frame) { - ref_frame_config->frame_flags[sl] = - VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | - VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF; - } else { - ref_frame_config->frame_flags[sl] = - VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | - VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF; - } - } - } else if (tl == 1) { - if (!sl) { - ref_frame_config->frame_flags[sl] = - VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | - VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF; - } else { - ref_frame_config->frame_flags[sl] = - VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST | - VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_REF_GF; - } - } if (tl == 0) { ref_frame_config->lst_fb_idx[sl] = sl; if (sl) { @@ -112,8 +89,47 @@ class DatarateOnePassCbrSvc : public ::svc_test::OnePassCbrSvc { ref_frame_config->alt_fb_idx[sl] = 0; } else if (tl == 1) { ref_frame_config->lst_fb_idx[sl] = sl; - ref_frame_config->gld_fb_idx[sl] = num_spatial_layers + sl - 1; - ref_frame_config->alt_fb_idx[sl] = num_spatial_layers + sl; + ref_frame_config->gld_fb_idx[sl] = + VPXMIN(REF_FRAMES - 1, num_spatial_layers + sl - 1); + ref_frame_config->alt_fb_idx[sl] = + VPXMIN(REF_FRAMES - 1, num_spatial_layers + sl); + } + if (!tl) { + if (!sl) { + ref_frame_config->reference_last[sl] = 1; + ref_frame_config->reference_golden[sl] = 0; + ref_frame_config->reference_alt_ref[sl] = 0; + ref_frame_config->update_buffer_slot[sl] |= + 1 << ref_frame_config->lst_fb_idx[sl]; + } else { + if (is_key_frame) { + ref_frame_config->reference_last[sl] = 1; + ref_frame_config->reference_golden[sl] = 0; + ref_frame_config->reference_alt_ref[sl] = 0; + ref_frame_config->update_buffer_slot[sl] |= + 1 << ref_frame_config->gld_fb_idx[sl]; + } else { + ref_frame_config->reference_last[sl] = 1; + ref_frame_config->reference_golden[sl] = 0; + ref_frame_config->reference_alt_ref[sl] = 0; + ref_frame_config->update_buffer_slot[sl] |= + 1 << ref_frame_config->lst_fb_idx[sl]; + } + } + } else if (tl == 1) { + if (!sl) { + ref_frame_config->reference_last[sl] = 1; + ref_frame_config->reference_golden[sl] = 0; + ref_frame_config->reference_alt_ref[sl] = 0; + ref_frame_config->update_buffer_slot[sl] |= + 1 << ref_frame_config->alt_fb_idx[sl]; + } else { + ref_frame_config->reference_last[sl] = 1; + ref_frame_config->reference_golden[sl] = 0; + ref_frame_config->reference_alt_ref[sl] = 0; + ref_frame_config->update_buffer_slot[sl] |= + 1 << ref_frame_config->alt_fb_idx[sl]; + } } } } diff --git a/test/test.mk b/test/test.mk index 0166a8065..11a0acf81 100644 --- a/test/test.mk +++ b/test/test.mk @@ -26,10 +26,6 @@ LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += aq_segment_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += alt_ref_aq_segment_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += vp8_datarate_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += vp9_datarate_test.cc -LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += svc_datarate_test.cc -LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += svc_test.cc -LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += svc_test.h -LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += svc_end_to_end_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += encode_api_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += error_resilience_test.cc LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += i420_video_source.h @@ -57,6 +53,10 @@ LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += decode_corrupted.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_ethread_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_motion_vector_test.cc LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += level_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += svc_datarate_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += svc_test.cc +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += svc_test.h +LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += svc_end_to_end_test.cc LIBVPX_TEST_SRCS-yes += decode_test_driver.cc LIBVPX_TEST_SRCS-yes += decode_test_driver.h diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 4e7d99f50..8830bfc11 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -913,6 +913,9 @@ int vp9_get_refresh_mask(VP9_COMP *cpi) { const GF_GROUP *const gf_group = &cpi->twopass.gf_group; arf_idx = gf_group->arf_update_idx[gf_group->index]; } + if (cpi->use_svc && + cpi->svc.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) + return cpi->svc.update_buffer_slot[cpi->svc.spatial_layer_id]; return (cpi->refresh_last_frame << cpi->lst_fb_idx) | (cpi->refresh_golden_frame << cpi->gld_fb_idx) | (cpi->refresh_alt_ref_frame << arf_idx); diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 3db11fcb0..dddae32c8 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -3277,8 +3277,10 @@ void vp9_update_reference_frames(VP9_COMP *cpi) { #endif if (is_one_pass_cbr_svc(cpi)) { - // Keep track of frame index for each reference frame. - if (cm->frame_type == KEY_FRAME) { + if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { + vp9_svc_update_ref_frame_bypass_mode(cpi); + } else if (cm->frame_type == KEY_FRAME) { + // Keep track of frame index for each reference frame. int i; // On key frame update all reference frame slots. for (i = 0; i < REF_FRAMES; i++) { @@ -3312,10 +3314,12 @@ void vp9_update_reference_frames(VP9_COMP *cpi) { static void loopfilter_frame(VP9_COMP *cpi, VP9_COMMON *cm) { MACROBLOCKD *xd = &cpi->td.mb.e_mbd; struct loopfilter *lf = &cm->lf; - - const int is_reference_frame = + int is_reference_frame = (cm->frame_type == KEY_FRAME || cpi->refresh_last_frame || cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame); + if (cpi->use_svc && + cpi->svc.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) + is_reference_frame = !cpi->svc.non_reference_frame; if (xd->lossless) { lf->filter_level = 0; diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index 0b7e7fe80..2154d144a 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -660,6 +660,23 @@ static void set_flags_and_fb_idx_for_temporal_mode_noLayering( reset_fb_idx_unused(cpi); } +static void set_flags_and_fb_idx_bypass_via_set_ref_frame_config( + VP9_COMP *const cpi) { + SVC *const svc = &cpi->svc; + int sl = svc->spatial_layer_id = svc->spatial_layer_to_encode; + cpi->ext_refresh_frame_flags_pending = 1; + cpi->lst_fb_idx = svc->lst_fb_idx[sl]; + cpi->gld_fb_idx = svc->gld_fb_idx[sl]; + cpi->alt_fb_idx = svc->alt_fb_idx[sl]; + cpi->ext_refresh_last_frame = 0; + cpi->ext_refresh_golden_frame = 0; + cpi->ext_refresh_alt_ref_frame = 0; + cpi->ref_frame_flags = 0; + if (svc->reference_last[sl]) cpi->ref_frame_flags |= VP9_LAST_FLAG; + if (svc->reference_golden[sl]) cpi->ref_frame_flags |= VP9_GOLD_FLAG; + if (svc->reference_altref[sl]) cpi->ref_frame_flags |= VP9_ALT_FLAG; +} + void vp9_copy_flags_ref_update_idx(VP9_COMP *const cpi) { SVC *const svc = &cpi->svc; static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG, @@ -668,10 +685,23 @@ void vp9_copy_flags_ref_update_idx(VP9_COMP *const cpi) { svc->lst_fb_idx[sl] = cpi->lst_fb_idx; svc->gld_fb_idx[sl] = cpi->gld_fb_idx; svc->alt_fb_idx[sl] = cpi->alt_fb_idx; - + // For the fixed SVC mode: pass the refresh_lst/gld/alt_frame flags to the + // update_buffer_slot, this is needed for the GET_SVC_REF_FRAME_CONFIG api. + if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { + int ref; + for (ref = 0; ref < REF_FRAMES; ++ref) { + svc->update_buffer_slot[sl] &= ~(1 << ref); + if ((ref == svc->lst_fb_idx[sl] && cpi->refresh_last_frame) || + (ref == svc->gld_fb_idx[sl] && cpi->refresh_golden_frame) || + (ref == svc->alt_fb_idx[sl] && cpi->refresh_alt_ref_frame)) + svc->update_buffer_slot[sl] |= (1 << ref); + } + } + // TODO(jianj): Remove these 3, deprecated. svc->update_last[sl] = (uint8_t)cpi->refresh_last_frame; svc->update_golden[sl] = (uint8_t)cpi->refresh_golden_frame; svc->update_altref[sl] = (uint8_t)cpi->refresh_alt_ref_frame; + svc->reference_last[sl] = (uint8_t)(cpi->ref_frame_flags & flag_list[LAST_FRAME]); svc->reference_golden[sl] = @@ -701,23 +731,8 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) { set_flags_and_fb_idx_for_temporal_mode2(cpi); } else if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { - // In the BYPASS/flexible mode, the encoder is relying on the application - // to specify, for each spatial layer, the flags and buffer indices for the - // layering. - // Note that the check (cpi->ext_refresh_frame_flags_pending == 0) is - // needed to support the case where the frame flags may be passed in via - // vpx_codec_encode(), which can be used for the temporal-only svc case. - // TODO(marpan): Consider adding an enc_config parameter to better handle - // this case. - if (cpi->ext_refresh_frame_flags_pending == 0) { - int sl; - svc->spatial_layer_id = svc->spatial_layer_to_encode; - sl = svc->spatial_layer_id; - vp9_apply_encoding_flags(cpi, svc->ext_frame_flags[sl]); - cpi->lst_fb_idx = svc->lst_fb_idx[sl]; - cpi->gld_fb_idx = svc->gld_fb_idx[sl]; - cpi->alt_fb_idx = svc->alt_fb_idx[sl]; - } + if (cpi->ext_refresh_frame_flags_pending == 0) + set_flags_and_fb_idx_bypass_via_set_ref_frame_config(cpi); } if (cpi->lst_fb_idx == svc->buffer_gf_temporal_ref[0].idx || @@ -772,13 +787,18 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) { memset(&svc->lst_fb_idx, -1, sizeof(svc->lst_fb_idx)); memset(&svc->gld_fb_idx, -1, sizeof(svc->lst_fb_idx)); memset(&svc->alt_fb_idx, -1, sizeof(svc->lst_fb_idx)); + // These are set by API before the superframe is encoded and they are + // passed to encoder layer by layer. Don't reset them on layer 0 in bypass + // mode. + vp9_zero(svc->update_buffer_slot); + vp9_zero(svc->reference_last); + vp9_zero(svc->reference_golden); + vp9_zero(svc->reference_altref); + // TODO(jianj): Remove these 3, deprecated. + vp9_zero(svc->update_last); + vp9_zero(svc->update_golden); + vp9_zero(svc->update_altref); } - vp9_zero(svc->update_last); - vp9_zero(svc->update_golden); - vp9_zero(svc->update_altref); - vp9_zero(svc->reference_last); - vp9_zero(svc->reference_golden); - vp9_zero(svc->reference_altref); } lc = &svc->layer_context[svc->spatial_layer_id * svc->number_temporal_layers + @@ -835,8 +855,13 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) { svc->non_reference_frame = 0; if (cpi->common.frame_type != KEY_FRAME && !cpi->ext_refresh_last_frame && - !cpi->ext_refresh_golden_frame && !cpi->ext_refresh_alt_ref_frame) { + !cpi->ext_refresh_golden_frame && !cpi->ext_refresh_alt_ref_frame) svc->non_reference_frame = 1; + // For non-flexible mode, where update_buffer_slot is used, need to check if + // all buffer slots are not refreshed. + if (svc->temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { + if (svc->update_buffer_slot[svc->spatial_layer_id] != 0) + svc->non_reference_frame = 0; } if (svc->spatial_layer_id == 0) svc->high_source_sad_superframe = 0; @@ -940,16 +965,17 @@ void vp9_svc_check_reset_layer_rc_flag(VP9_COMP *const cpi) { void vp9_svc_constrain_inter_layer_pred(VP9_COMP *const cpi) { VP9_COMMON *const cm = &cpi->common; + SVC *const svc = &cpi->svc; // Check for disabling inter-layer (spatial) prediction, if // svc.disable_inter_layer_pred is set. If the previous spatial layer was // dropped then disable the prediction from this (scaled) reference. // For INTER_LAYER_PRED_OFF_NONKEY: inter-layer prediction is disabled // on key frames or if any spatial layer is a sync layer. - if ((cpi->svc.disable_inter_layer_pred == INTER_LAYER_PRED_OFF_NONKEY && - !cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame && - !cpi->svc.superframe_has_layer_sync) || - cpi->svc.disable_inter_layer_pred == INTER_LAYER_PRED_OFF || - cpi->svc.drop_spatial_layer[cpi->svc.spatial_layer_id - 1]) { + if ((svc->disable_inter_layer_pred == INTER_LAYER_PRED_OFF_NONKEY && + !svc->layer_context[svc->temporal_layer_id].is_key_frame && + !svc->superframe_has_layer_sync) || + svc->disable_inter_layer_pred == INTER_LAYER_PRED_OFF || + svc->drop_spatial_layer[svc->spatial_layer_id - 1]) { MV_REFERENCE_FRAME ref_frame; static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG, VP9_ALT_FLAG }; @@ -967,7 +993,7 @@ void vp9_svc_constrain_inter_layer_pred(VP9_COMP *const cpi) { // prediction (the reference that is scaled) is not the previous spatial layer // from the same superframe, then we disable inter-layer prediction. // Only need to check when inter_layer prediction is not set to OFF mode. - if (cpi->svc.disable_inter_layer_pred != INTER_LAYER_PRED_OFF) { + if (svc->disable_inter_layer_pred != INTER_LAYER_PRED_OFF) { // We only use LAST and GOLDEN for prediction in real-time mode, so we // check both here. MV_REFERENCE_FRAME ref_frame; @@ -985,14 +1011,15 @@ void vp9_svc_constrain_inter_layer_pred(VP9_COMP *const cpi) { int fb_idx = ref_frame == LAST_FRAME ? cpi->lst_fb_idx : cpi->gld_fb_idx; int ref_flag = ref_frame == LAST_FRAME ? VP9_LAST_FLAG : VP9_GOLD_FLAG; - int sl = cpi->svc.spatial_layer_id; + int sl = svc->spatial_layer_id; int disable = 1; - if ((fb_idx == cpi->svc.lst_fb_idx[sl - 1] && - cpi->svc.update_last[sl - 1]) || - (fb_idx == cpi->svc.gld_fb_idx[sl - 1] && - cpi->svc.update_golden[sl - 1]) || - (fb_idx == cpi->svc.alt_fb_idx[sl - 1] && - cpi->svc.update_altref[sl - 1])) + if (fb_idx < 0) continue; + if ((fb_idx == svc->lst_fb_idx[sl - 1] && + (svc->update_buffer_slot[sl - 1] & (1 << fb_idx))) || + (fb_idx == svc->gld_fb_idx[sl - 1] && + (svc->update_buffer_slot[sl - 1] & (1 << fb_idx))) || + (fb_idx == svc->alt_fb_idx[sl - 1] && + (svc->update_buffer_slot[sl - 1] & (1 << fb_idx)))) disable = 0; if (disable) cpi->ref_frame_flags &= (~ref_flag); } @@ -1098,3 +1125,20 @@ void vp9_svc_update_ref_frame_buffer_idx(VP9_COMP *const cpi) { svc->fb_idx_base[cpi->alt_fb_idx] = 1; } } + +void vp9_svc_update_ref_frame_bypass_mode(VP9_COMP *const cpi) { + // For non-flexible/bypass SVC mode: check for refreshing other buffer + // slots. + SVC *const svc = &cpi->svc; + VP9_COMMON *const cm = &cpi->common; + BufferPool *const pool = cm->buffer_pool; + int i; + for (i = 0; i < REF_FRAMES; i++) { + if (cm->frame_type == KEY_FRAME || + svc->update_buffer_slot[svc->spatial_layer_id] & (1 << i)) { + ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[i], cm->new_fb_idx); + svc->fb_idx_spatial_layer_id[i] = svc->spatial_layer_id; + svc->fb_idx_temporal_layer_id[i] = svc->temporal_layer_id; + } + } +} diff --git a/vp9/encoder/vp9_svc_layercontext.h b/vp9/encoder/vp9_svc_layercontext.h index 0ac1a7315..6eba7c8c2 100644 --- a/vp9/encoder/vp9_svc_layercontext.h +++ b/vp9/encoder/vp9_svc_layercontext.h @@ -143,12 +143,14 @@ typedef struct SVC { int high_source_sad_superframe; // Flags used to get SVC pattern info. - uint8_t update_last[VPX_SS_MAX_LAYERS]; - uint8_t update_golden[VPX_SS_MAX_LAYERS]; - uint8_t update_altref[VPX_SS_MAX_LAYERS]; + int update_buffer_slot[VPX_SS_MAX_LAYERS]; uint8_t reference_last[VPX_SS_MAX_LAYERS]; uint8_t reference_golden[VPX_SS_MAX_LAYERS]; uint8_t reference_altref[VPX_SS_MAX_LAYERS]; + // TODO(jianj): Remove these last 3, deprecated. + uint8_t update_last[VPX_SS_MAX_LAYERS]; + uint8_t update_golden[VPX_SS_MAX_LAYERS]; + uint8_t update_altref[VPX_SS_MAX_LAYERS]; // Keep track of the frame buffer index updated/refreshed on the base // temporal superframe. @@ -230,6 +232,8 @@ void vp9_svc_check_spatial_layer_sync(struct VP9_COMP *const cpi); void vp9_svc_update_ref_frame_buffer_idx(struct VP9_COMP *const cpi); +void vp9_svc_update_ref_frame_bypass_mode(struct VP9_COMP *const cpi); + #ifdef __cplusplus } // extern "C" #endif diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 13c42c75f..d202e09c3 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -1489,15 +1489,17 @@ static vpx_codec_err_t ctrl_get_svc_ref_frame_config(vpx_codec_alg_priv_t *ctx, vpx_svc_ref_frame_config_t *data = va_arg(args, vpx_svc_ref_frame_config_t *); int sl; for (sl = 0; sl <= cpi->svc.spatial_layer_id; sl++) { - data->update_last[sl] = cpi->svc.update_last[sl]; - data->update_golden[sl] = cpi->svc.update_golden[sl]; - data->update_alt_ref[sl] = cpi->svc.update_altref[sl]; + data->update_buffer_slot[sl] = cpi->svc.update_buffer_slot[sl]; data->reference_last[sl] = cpi->svc.reference_last[sl]; data->reference_golden[sl] = cpi->svc.reference_golden[sl]; data->reference_alt_ref[sl] = cpi->svc.reference_altref[sl]; data->lst_fb_idx[sl] = cpi->svc.lst_fb_idx[sl]; data->gld_fb_idx[sl] = cpi->svc.gld_fb_idx[sl]; data->alt_fb_idx[sl] = cpi->svc.alt_fb_idx[sl]; + // TODO(jianj): Remove these 3, deprecated. + data->update_last[sl] = cpi->svc.update_last[sl]; + data->update_golden[sl] = cpi->svc.update_golden[sl]; + data->update_alt_ref[sl] = cpi->svc.update_altref[sl]; } return VPX_CODEC_OK; } @@ -1508,7 +1510,10 @@ static vpx_codec_err_t ctrl_set_svc_ref_frame_config(vpx_codec_alg_priv_t *ctx, vpx_svc_ref_frame_config_t *data = va_arg(args, vpx_svc_ref_frame_config_t *); int sl; for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) { - cpi->svc.ext_frame_flags[sl] = data->frame_flags[sl]; + cpi->svc.update_buffer_slot[sl] = data->update_buffer_slot[sl]; + cpi->svc.reference_last[sl] = data->reference_last[sl]; + cpi->svc.reference_golden[sl] = data->reference_golden[sl]; + cpi->svc.reference_altref[sl] = data->reference_alt_ref[sl]; cpi->svc.lst_fb_idx[sl] = data->lst_fb_idx[sl]; cpi->svc.gld_fb_idx[sl] = data->gld_fb_idx[sl]; cpi->svc.alt_fb_idx[sl] = data->alt_fb_idx[sl]; diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h index d63365e41..ea720cfb3 100644 --- a/vpx/vp8cx.h +++ b/vpx/vp8cx.h @@ -789,12 +789,11 @@ typedef struct vpx_svc_layer_id { * */ typedef struct vpx_svc_ref_frame_config { - // TODO(jianj/marpan): Remove the usage of frame_flags, instead use the - // update and reference flags. - int frame_flags[VPX_SS_MAX_LAYERS]; /**< Frame flags. */ - int lst_fb_idx[VPX_SS_MAX_LAYERS]; /**< Last buffer index. */ - int gld_fb_idx[VPX_SS_MAX_LAYERS]; /**< Golden buffer index. */ - int alt_fb_idx[VPX_SS_MAX_LAYERS]; /**< Altref buffer index. */ + int lst_fb_idx[VPX_SS_MAX_LAYERS]; /**< Last buffer index. */ + int gld_fb_idx[VPX_SS_MAX_LAYERS]; /**< Golden buffer index. */ + int alt_fb_idx[VPX_SS_MAX_LAYERS]; /**< Altref buffer index. */ + int update_buffer_slot[VPX_SS_MAX_LAYERS]; /**< Update reference frames. */ + // TODO(jianj): Remove update_last/golden/alt_ref, these are deprecated. int update_last[VPX_SS_MAX_LAYERS]; /**< Update last. */ int update_golden[VPX_SS_MAX_LAYERS]; /**< Update golden. */ int update_alt_ref[VPX_SS_MAX_LAYERS]; /**< Update altref. */ -- 2.50.1