]> granicus.if.org Git - libvpx/commitdiff
vp9-svc: Add full superframe drop mode.
authorMarco Paniconi <marpan@google.com>
Tue, 22 May 2018 22:02:45 +0000 (15:02 -0700)
committerMarco Paniconi <marpan@google.com>
Wed, 23 May 2018 04:36:08 +0000 (21:36 -0700)
This will check for dropping full superframe if any
spatial layer is overshooting.

Change-Id: Ic656807028ebef5552301b6d10399fbe3a6c890c

vp9/encoder/vp9_encoder.c
vp9/encoder/vp9_ratectrl.c
vp9/encoder/vp9_svc_layercontext.c
vpx/vp8cx.h

index e41768a8f13298a5a965401f64bd6683bee4274f..f5b7b1264bbf17a6839f46ac26b2c6ae371067d4 100644 (file)
@@ -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())
index c349a807aa214c9e050d74543b0a0f4ba68bffbd..ba09025f077c5e51365def90621f61421b1a93f3 100644 (file)
@@ -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) {
index fec0fa8930d47f9c9f36ed9d2aec1abe99e2ddc1..ce31507b6ff05fa75a3e7a2424af621127740de1 100644 (file)
@@ -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.
index b201d96f4fa0c95e3f8d136e6f3e68cf11411f5a..97b8ba71c80aa85e0b7db98e1021135c59ee8773 100644 (file)
@@ -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.