From b2004fdda6423fc6e8f3afb2afc7df03d0a19f53 Mon Sep 17 00:00:00 2001 From: Marco Paniconi Date: Tue, 22 May 2018 15:02:45 -0700 Subject: [PATCH] vp9-svc: Add full superframe drop mode. This will check for dropping full superframe if any spatial layer is overshooting. Change-Id: Ic656807028ebef5552301b6d10399fbe3a6c890c --- vp9/encoder/vp9_encoder.c | 17 +++++---- vp9/encoder/vp9_ratectrl.c | 58 +++++++++++++++++++++++++----- vp9/encoder/vp9_svc_layercontext.c | 7 ++-- vpx/vp8cx.h | 3 +- 4 files changed, 62 insertions(+), 23 deletions(-) diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index e41768a8f..f5b7b1264 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -4529,9 +4529,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size, cpi->last_frame_dropped = 1; cpi->svc.last_layer_dropped[cpi->svc.spatial_layer_id] = 1; cpi->svc.drop_spatial_layer[cpi->svc.spatial_layer_id] = 1; - if (cpi->svc.framedrop_mode != CONSTRAINED_LAYER_DROP || + if (cpi->svc.framedrop_mode == LAYER_DROP || cpi->svc.drop_spatial_layer[0] == 0) { - // For the case of CONSTRAINED_LAYER_DROP where the base is dropped + // For the case of constrained drop mode where the base is dropped // (drop_spatial_layer[0] == 1), which means full superframe dropped, // we don't increment the svc frame counters. In particular temporal // layer counter (which is incremented in vp9_inc_frame_in_layer()) @@ -4595,14 +4595,13 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size, (!cpi->use_svc || !cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame)) { int svc_prev_layer_dropped = 0; - // In the contrained framedrop mode for svc (framedrop_mode = - // CONSTRAINED_LAYER_DROP), if the previous spatial layer was dropped, drop - // the current spatial layer. + // In the constrained or full_superframe framedrop mode for svc + // (framedrop_mode != LAYER_DROP), if the previous spatial layer was + // dropped, drop the current spatial layer. if (cpi->use_svc && cpi->svc.spatial_layer_id > 0 && cpi->svc.drop_spatial_layer[cpi->svc.spatial_layer_id - 1]) svc_prev_layer_dropped = 1; - if ((svc_prev_layer_dropped && - cpi->svc.framedrop_mode == CONSTRAINED_LAYER_DROP) || + if ((svc_prev_layer_dropped && cpi->svc.framedrop_mode != LAYER_DROP) || vp9_rc_drop_frame(cpi)) { vp9_rc_postencode_update_drop_frame(cpi); cpi->ext_refresh_frame_flags_pending = 0; @@ -4611,9 +4610,9 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size, cpi->svc.last_layer_dropped[cpi->svc.spatial_layer_id] = 1; cpi->svc.drop_spatial_layer[cpi->svc.spatial_layer_id] = 1; cpi->svc.skip_enhancement_layer = 1; - if (cpi->svc.framedrop_mode != CONSTRAINED_LAYER_DROP || + if (cpi->svc.framedrop_mode == LAYER_DROP || cpi->svc.drop_spatial_layer[0] == 0) { - // For the case of CONSTRAINED_LAYER_DROP where the base is dropped + // For the case of constrained drop mode where the base is dropped // (drop_spatial_layer[0] == 1), which means full superframe dropped, // we don't increment the svc frame counters. In particular temporal // layer counter (which is incremented in vp9_inc_frame_in_layer()) diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index c349a807a..ba09025f0 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -390,7 +390,31 @@ void vp9_rc_init(const VP9EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) { rc->baseline_gf_interval = (rc->min_gf_interval + rc->max_gf_interval) / 2; } -static int check_buffer(VP9_COMP *cpi, int drop_mark) { +static int check_buffer_above_thresh(VP9_COMP *cpi, int drop_mark) { + SVC *svc = &cpi->svc; + if (!cpi->use_svc || cpi->svc.framedrop_mode != FULL_SUPERFRAME_DROP) { + RATE_CONTROL *const rc = &cpi->rc; + return (rc->buffer_level > drop_mark); + } else { + int i; + // For SVC in the FULL_SUPERFRAME_DROP): the condition on + // buffer (if its above threshold, so no drop) is checked on current and + // upper spatial layers. If any spatial layer is not above threshold then + // we return 0. + for (i = svc->spatial_layer_id; i < svc->number_spatial_layers; ++i) { + const int layer = LAYER_IDS_TO_IDX(i, svc->temporal_layer_id, + svc->number_temporal_layers); + LAYER_CONTEXT *lc = &svc->layer_context[layer]; + RATE_CONTROL *lrc = &lc->rc; + const int drop_mark_layer = + (int)(cpi->svc.framedrop_thresh[i] * lrc->optimal_buffer_level / 100); + if (!(lrc->buffer_level > drop_mark_layer)) return 0; + } + return 1; + } +} + +static int check_buffer_below_thresh(VP9_COMP *cpi, int drop_mark) { SVC *svc = &cpi->svc; if (!cpi->use_svc || cpi->svc.framedrop_mode == LAYER_DROP) { RATE_CONTROL *const rc = &cpi->rc; @@ -398,8 +422,10 @@ static int check_buffer(VP9_COMP *cpi, int drop_mark) { } else { int i; // For SVC in the constrained framedrop mode (svc->framedrop_mode = - // CONSTRAINED_LAYER_DROP): the condition on buffer (to drop frame) is - // checked on current and upper spatial layers. + // CONSTRAINED_LAYER_DROP or FULL_SUPERFRAME_DROP): the condition on + // buffer (if its below threshold, so drop frame) is checked on current + // and upper spatial layers. For FULL_SUPERFRAME_DROP mode if any + // spatial layer is <= threshold, then we return 1 (drop). for (i = svc->spatial_layer_id; i < svc->number_spatial_layers; ++i) { const int layer = LAYER_IDS_TO_IDX(i, svc->temporal_layer_id, svc->number_temporal_layers); @@ -407,9 +433,16 @@ static int check_buffer(VP9_COMP *cpi, int drop_mark) { RATE_CONTROL *lrc = &lc->rc; const int drop_mark_layer = (int)(cpi->svc.framedrop_thresh[i] * lrc->optimal_buffer_level / 100); - if (!(lrc->buffer_level <= drop_mark_layer)) return 0; + if (cpi->svc.framedrop_mode == FULL_SUPERFRAME_DROP) { + if (lrc->buffer_level <= drop_mark_layer) return 1; + } else { + if (!(lrc->buffer_level <= drop_mark_layer)) return 0; + } } - return 1; + if (cpi->svc.framedrop_mode == FULL_SUPERFRAME_DROP) + return 0; + else + return 1; } } @@ -420,10 +453,15 @@ int vp9_rc_drop_frame(VP9_COMP *cpi) { if (cpi->use_svc) drop_frames_water_mark = cpi->svc.framedrop_thresh[cpi->svc.spatial_layer_id]; - if (!drop_frames_water_mark) { + if (!drop_frames_water_mark || + (cpi->svc.spatial_layer_id > 0 && + cpi->svc.framedrop_mode == FULL_SUPERFRAME_DROP)) { return 0; } else { - if (rc->buffer_level < 0) { + if ((rc->buffer_level < 0 && + cpi->svc.framedrop_mode != FULL_SUPERFRAME_DROP) || + (check_buffer_below_thresh(cpi, -1) && + cpi->svc.framedrop_mode == FULL_SUPERFRAME_DROP)) { // Always drop if buffer is below 0. return 1; } else { @@ -431,9 +469,11 @@ int vp9_rc_drop_frame(VP9_COMP *cpi) { // (starting with the next frame) until it increases back over drop_mark. int drop_mark = (int)(drop_frames_water_mark * rc->optimal_buffer_level / 100); - if ((rc->buffer_level > drop_mark) && (rc->decimation_factor > 0)) { + if (check_buffer_above_thresh(cpi, drop_mark) && + (rc->decimation_factor > 0)) { --rc->decimation_factor; - } else if (check_buffer(cpi, drop_mark) && rc->decimation_factor == 0) { + } else if (check_buffer_below_thresh(cpi, drop_mark) && + rc->decimation_factor == 0) { rc->decimation_factor = 1; } if (rc->decimation_factor > 0) { diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index fec0fa893..ce31507b6 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -948,12 +948,11 @@ 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, when - // inter-layer prediciton is on (default). + // For fixed/non-flexible mode, the folllowing constraint are expected, + // when inter-layer prediciton is on (default). if (svc->temporal_layering_mode != VP9E_TEMPORAL_LAYERING_MODE_BYPASS && svc->disable_inter_layer_pred == INTER_LAYER_PRED_ON && - svc->framedrop_mode == CONSTRAINED_LAYER_DROP) { + svc->framedrop_mode != 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. diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h index b201d96f4..97b8ba71c 100644 --- a/vpx/vp8cx.h +++ b/vpx/vp8cx.h @@ -786,7 +786,8 @@ typedef struct vpx_svc_ref_frame_config { typedef enum { CONSTRAINED_LAYER_DROP, /**< Upper layers are constrained to drop if current layer drops. */ - LAYER_DROP, /**< Any spatial layer can drop. */ + LAYER_DROP, /**< Any spatial layer can drop. */ + FULL_SUPERFRAME_DROP, /**< Only full superframe can drop. */ } SVC_LAYER_DROP_MODE; /*!\brief vp9 svc frame dropping parameters. -- 2.40.0