ref: b2004fdda6423fc6e8f3afb2afc7df03d0a19f53
parent: fe8c07172f4a8acc48386cec0d14aa09cb2495c1
author: Marco Paniconi <marpan@google.com>
date: Tue May 22 11:02:45 EDT 2018
vp9-svc: Add full superframe drop mode. This will check for dropping full superframe if any spatial layer is overshooting. Change-Id: Ic656807028ebef5552301b6d10399fbe3a6c890c
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -4529,9 +4529,9 @@
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 @@
(!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 @@
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())
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -390,8 +390,32 @@
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;
return (rc->buffer_level <= drop_mark);
@@ -398,8 +422,10 @@
} 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 @@
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 @@
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 @@
// (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) {
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -948,12 +948,11 @@
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.
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -786,7 +786,8 @@
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.