From: Marco Paniconi Date: Mon, 14 May 2018 05:17:17 +0000 (-0700) Subject: vp9-svc: Update layer_id of frame buffer idx last refreshed. X-Git-Tag: v1.8.0~688 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c85c5337bfe2f64503b8e8f4584db63d6cd64d61;p=libvpx vp9-svc: Update layer_id of frame buffer idx last refreshed. Remove some unused code and add parameter to keep track of the layer_id of the frame buffer indices last refreshed. This is useful for verifying constaints on spatial-temporal pattern, for fixed/non-flexible mode. Change-Id: I6957bb43157eb31df49dac1b8245facc043e4a49 --- diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 0b72b2489..997fae2ba 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -3024,23 +3024,28 @@ void vp9_update_reference_frames(VP9_COMP *cpi) { SVC *const svc = &cpi->svc; if (cm->frame_type == KEY_FRAME) { int i; - svc->ref_frame_index[cpi->lst_fb_idx] = svc->current_superframe; - svc->ref_frame_index[cpi->gld_fb_idx] = svc->current_superframe; - svc->ref_frame_index[cpi->alt_fb_idx] = svc->current_superframe; // On key frame update all reference frame slots. for (i = 0; i < REF_FRAMES; i++) { + svc->fb_idx_spatial_layer_id[i] = svc->spatial_layer_id; + svc->fb_idx_temporal_layer_id[i] = svc->temporal_layer_id; // LAST/GOLDEN/ALTREF is already updated above. if (i != cpi->lst_fb_idx && i != cpi->gld_fb_idx && i != cpi->alt_fb_idx) ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[i], cm->new_fb_idx); } } else { - if (cpi->refresh_last_frame) - svc->ref_frame_index[cpi->lst_fb_idx] = svc->current_superframe; - if (cpi->refresh_golden_frame) - svc->ref_frame_index[cpi->gld_fb_idx] = svc->current_superframe; - if (cpi->refresh_alt_ref_frame) - svc->ref_frame_index[cpi->alt_fb_idx] = svc->current_superframe; + if (cpi->refresh_last_frame) { + svc->fb_idx_spatial_layer_id[cpi->lst_fb_idx] = svc->spatial_layer_id; + svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] = svc->temporal_layer_id; + } + if (cpi->refresh_golden_frame) { + svc->fb_idx_spatial_layer_id[cpi->gld_fb_idx] = svc->spatial_layer_id; + svc->fb_idx_temporal_layer_id[cpi->gld_fb_idx] = svc->temporal_layer_id; + } + if (cpi->refresh_alt_ref_frame) { + svc->fb_idx_spatial_layer_id[cpi->alt_fb_idx] = svc->spatial_layer_id; + svc->fb_idx_temporal_layer_id[cpi->alt_fb_idx] = svc->temporal_layer_id; + } } // Copy flags from encoder to SVC struct. vp9_copy_flags_ref_update_idx(cpi); @@ -3729,10 +3734,12 @@ static void encode_without_recode_loop(VP9_COMP *cpi, size_t *size, suppress_active_map(cpi); - // For SVC on non-zero spatial layer: check for disabling inter-layer - // prediction. - if (cpi->use_svc && cpi->svc.spatial_layer_id > 0) - vp9_svc_constrain_inter_layer_pred(cpi); + if (cpi->use_svc) { + // On non-zero spatial layer, check for disabling inter-layer + // prediction. + if (cpi->svc.spatial_layer_id > 0) vp9_svc_constrain_inter_layer_pred(cpi); + vp9_svc_assert_constraints_pattern(cpi); + } // Variance adaptive and in frame q adjustment experiments are mutually // exclusive. diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index 07d1995a8..aec877ac8 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -41,7 +41,10 @@ void vp9_init_layer_context(VP9_COMP *const cpi) { svc->disable_inter_layer_pred = INTER_LAYER_PRED_ON; svc->framedrop_mode = CONSTRAINED_LAYER_DROP; - for (i = 0; i < REF_FRAMES; ++i) svc->ref_frame_index[i] = -1; + for (i = 0; i < REF_FRAMES; ++i) { + svc->fb_idx_spatial_layer_id[i] = -1; + svc->fb_idx_temporal_layer_id[i] = -1; + } for (sl = 0; sl < oxcf->ss_number_layers; ++sl) { svc->last_layer_dropped[sl] = 0; svc->drop_spatial_layer[sl] = 0; @@ -940,3 +943,45 @@ void vp9_svc_constrain_inter_layer_pred(VP9_COMP *const cpi) { } } } + +void vp9_svc_assert_constraints_pattern(VP9_COMP *const cpi) { + SVC *const svc = &cpi->svc; + // For fixed/non-flexible mode, and with CONSTRAINED frame drop + // mode (default), the folllowing constraint are expected. + if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS && + svc->framedrop_mode == CONSTRAINED_LAYER_DROP) { + if (!cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame) { + // On non-key frames: LAST is always temporal reference, GOLDEN is + // spatial reference. + if (svc->temporal_layer_id == 0) + // Base temporal only predicts from base temporal. + assert(svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] == 0); + else + // Non-base temporal only predicts from lower temporal layer. + assert(svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] < + svc->temporal_layer_id); + if (svc->spatial_layer_id > 0) { + // Non-base spatial only predicts from lower spatial layer with same + // temporal_id. + assert(svc->fb_idx_spatial_layer_id[cpi->gld_fb_idx] == + svc->spatial_layer_id - 1); + assert(svc->fb_idx_temporal_layer_id[cpi->gld_fb_idx] == + svc->temporal_layer_id); + } + } else if (svc->spatial_layer_id > 0) { + // Only 1 reference for frame whose base is key; reference may be LAST + // or GOLDEN, so we check both. + if (cpi->ref_frame_flags & VP9_LAST_FLAG) { + assert(svc->fb_idx_spatial_layer_id[cpi->lst_fb_idx] == + svc->spatial_layer_id - 1); + assert(svc->fb_idx_temporal_layer_id[cpi->lst_fb_idx] == + svc->temporal_layer_id); + } else if (cpi->ref_frame_flags & VP9_GOLD_FLAG) { + assert(svc->fb_idx_spatial_layer_id[cpi->gld_fb_idx] == + svc->spatial_layer_id - 1); + assert(svc->fb_idx_temporal_layer_id[cpi->gld_fb_idx] == + svc->temporal_layer_id); + } + } + } +} diff --git a/vp9/encoder/vp9_svc_layercontext.h b/vp9/encoder/vp9_svc_layercontext.h index 617717049..99ec9e97b 100644 --- a/vp9/encoder/vp9_svc_layercontext.h +++ b/vp9/encoder/vp9_svc_layercontext.h @@ -96,7 +96,6 @@ typedef struct SVC { int lst_fb_idx[VPX_MAX_LAYERS]; int gld_fb_idx[VPX_MAX_LAYERS]; int alt_fb_idx[VPX_MAX_LAYERS]; - int ref_frame_index[REF_FRAMES]; int force_zero_mode_spatial_ref; int current_superframe; int non_reference_frame; @@ -142,6 +141,11 @@ typedef struct SVC { // Keep track of the frame buffer index updated/refreshed on the base // temporal superframe. uint8_t fb_idx_upd_tl0[VPX_SS_MAX_LAYERS]; + + // Keep track of the spatial and temporal layer id of the frame that last + // updated the frame buffer index. + uint8_t fb_idx_spatial_layer_id[REF_FRAMES]; + uint8_t fb_idx_temporal_layer_id[REF_FRAMES]; } SVC; struct VP9_COMP; @@ -201,6 +205,8 @@ void vp9_svc_check_reset_layer_rc_flag(struct VP9_COMP *const cpi); void vp9_svc_constrain_inter_layer_pred(struct VP9_COMP *const cpi); +void vp9_svc_assert_constraints_pattern(struct VP9_COMP *const cpi); + #ifdef __cplusplus } // extern "C" #endif