From fc1c5d1c9cba8829995c68d07e827bc9bcccd9e8 Mon Sep 17 00:00:00 2001 From: Marco Paniconi Date: Thu, 24 May 2018 11:13:36 -0700 Subject: [PATCH] vp9-svc: Add max_consec_drop to SVC frame drop. For any spatial, limits the amount of consecutive frame drop. Change-Id: I692d90363f329f571f2b59e12cc680ad2e76065d --- test/svc_datarate_test.cc | 1 + vp9/encoder/vp9_encoder.c | 26 ++++++++++++++------------ vp9/encoder/vp9_ratectrl.c | 23 +++++++++++++++-------- vp9/encoder/vp9_svc_layercontext.c | 2 ++ vp9/encoder/vp9_svc_layercontext.h | 2 ++ vp9/vp9_cx_iface.c | 1 + vpx/vp8cx.h | 3 ++- 7 files changed, 37 insertions(+), 21 deletions(-) diff --git a/test/svc_datarate_test.cc b/test/svc_datarate_test.cc index cf26feb..b9fbd8f 100644 --- a/test/svc_datarate_test.cc +++ b/test/svc_datarate_test.cc @@ -205,6 +205,7 @@ class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest { svc_drop_frame.framedrop_mode = LAYER_DROP; for (i = 0; i < number_spatial_layers_; i++) svc_drop_frame.framedrop_thresh[i] = 30; + svc_drop_frame.max_consec_drop = 30; encoder->Control(VP9E_SET_SVC_FRAME_DROP_LAYER, &svc_drop_frame); } } diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index f5b7b12..97e6321 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -4594,24 +4594,26 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size, cm->frame_type != KEY_FRAME && (!cpi->use_svc || !cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame)) { + SVC *svc = &cpi->svc; int svc_prev_layer_dropped = 0; // 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]) + if (cpi->use_svc && svc->spatial_layer_id > 0 && + svc->drop_spatial_layer[svc->spatial_layer_id - 1]) svc_prev_layer_dropped = 1; - if ((svc_prev_layer_dropped && cpi->svc.framedrop_mode != LAYER_DROP) || + if ((svc_prev_layer_dropped && svc->framedrop_mode != LAYER_DROP) || vp9_rc_drop_frame(cpi)) { vp9_rc_postencode_update_drop_frame(cpi); cpi->ext_refresh_frame_flags_pending = 0; cpi->last_frame_dropped = 1; if (cpi->use_svc) { - 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 == LAYER_DROP || - cpi->svc.drop_spatial_layer[0] == 0) { + svc->last_layer_dropped[svc->spatial_layer_id] = 1; + svc->drop_spatial_layer[svc->spatial_layer_id] = 1; + svc->drop_count[svc->spatial_layer_id]++; + svc->skip_enhancement_layer = 1; + if (svc->framedrop_mode == LAYER_DROP || + svc->drop_spatial_layer[0] == 0) { // 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 @@ -4621,16 +4623,16 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, size_t *size, // issue with temporal alignement with full superframe dropping. vp9_inc_frame_in_layer(cpi); } - if (cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1) { + if (svc->spatial_layer_id == svc->number_spatial_layers - 1) { int i; int all_layers_drop = 1; - for (i = 0; i < cpi->svc.spatial_layer_id; i++) { - if (cpi->svc.drop_spatial_layer[i] == 0) { + for (i = 0; i < svc->spatial_layer_id; i++) { + if (svc->drop_spatial_layer[i] == 0) { all_layers_drop = 0; break; } } - if (all_layers_drop == 1) cpi->svc.skip_enhancement_layer = 0; + if (all_layers_drop == 1) svc->skip_enhancement_layer = 0; } } return; diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 94d8900..f243be8 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -457,19 +457,26 @@ static int check_buffer_below_thresh(VP9_COMP *cpi, int drop_mark) { int vp9_rc_drop_frame(VP9_COMP *cpi) { const VP9EncoderConfig *oxcf = &cpi->oxcf; RATE_CONTROL *const rc = &cpi->rc; + SVC *svc = &cpi->svc; int drop_frames_water_mark = oxcf->drop_frames_water_mark; - if (cpi->use_svc) - drop_frames_water_mark = - cpi->svc.framedrop_thresh[cpi->svc.spatial_layer_id]; + if (cpi->use_svc) { + // If we have dropped max_consec_drop frames, then we don't + // drop this spatial layer, and reset counter to 0. + if (svc->drop_count[svc->spatial_layer_id] == svc->max_consec_drop) { + svc->drop_count[svc->spatial_layer_id] = 0; + return 0; + } else { + drop_frames_water_mark = svc->framedrop_thresh[svc->spatial_layer_id]; + } + } if (!drop_frames_water_mark || - (cpi->svc.spatial_layer_id > 0 && - cpi->svc.framedrop_mode == FULL_SUPERFRAME_DROP)) { + (svc->spatial_layer_id > 0 && + svc->framedrop_mode == FULL_SUPERFRAME_DROP)) { return 0; } else { - if ((rc->buffer_level < 0 && - cpi->svc.framedrop_mode != FULL_SUPERFRAME_DROP) || + if ((rc->buffer_level < 0 && svc->framedrop_mode != FULL_SUPERFRAME_DROP) || (check_buffer_below_thresh(cpi, -1) && - cpi->svc.framedrop_mode == FULL_SUPERFRAME_DROP)) { + svc->framedrop_mode == FULL_SUPERFRAME_DROP)) { // Always drop if buffer is below 0. return 1; } else { diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c index ce31507..d745ae0 100644 --- a/vp9/encoder/vp9_svc_layercontext.c +++ b/vp9/encoder/vp9_svc_layercontext.c @@ -56,7 +56,9 @@ void vp9_init_layer_context(VP9_COMP *const cpi) { svc->downsample_filter_phase[sl] = 8; // Set to 8 for averaging filter. svc->framedrop_thresh[sl] = oxcf->drop_frames_water_mark; svc->fb_idx_upd_tl0[sl] = -1; + svc->drop_count[sl] = 0; } + svc->max_consec_drop = INT_MAX; if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) { if (vpx_realloc_frame_buffer(&cpi->svc.empty_frame.img, SMALL_FRAME_WIDTH, diff --git a/vp9/encoder/vp9_svc_layercontext.h b/vp9/encoder/vp9_svc_layercontext.h index 367c93a..9be5bb7 100644 --- a/vp9/encoder/vp9_svc_layercontext.h +++ b/vp9/encoder/vp9_svc_layercontext.h @@ -121,6 +121,8 @@ typedef struct SVC { int last_layer_dropped[VPX_MAX_LAYERS]; int drop_spatial_layer[VPX_MAX_LAYERS]; int framedrop_thresh[VPX_MAX_LAYERS]; + int drop_count[VPX_MAX_LAYERS]; + int max_consec_drop; SVC_LAYER_DROP_MODE framedrop_mode; INTER_LAYER_PRED disable_inter_layer_pred; diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index d6c6ece..443d896 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -1536,6 +1536,7 @@ static vpx_codec_err_t ctrl_set_svc_frame_drop_layer(vpx_codec_alg_priv_t *ctx, cpi->svc.framedrop_mode = data->framedrop_mode; for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) cpi->svc.framedrop_thresh[sl] = data->framedrop_thresh[sl]; + cpi->svc.max_consec_drop = data->max_consec_drop; return VPX_CODEC_OK; } diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h index 97b8ba7..44519e0 100644 --- a/vpx/vp8cx.h +++ b/vpx/vp8cx.h @@ -800,7 +800,8 @@ typedef enum { typedef struct vpx_svc_frame_drop { int framedrop_thresh[VPX_SS_MAX_LAYERS]; /**< Frame drop thresholds */ SVC_LAYER_DROP_MODE - framedrop_mode; /**< Layer-based or constrained dropping. */ + framedrop_mode; /**< Layer-based or constrained dropping. */ + int max_consec_drop; /**< Maximum consecutive drops, for any layer. */ } vpx_svc_frame_drop_t; /*!\cond */ -- 2.7.4