shithub: libvpx

Download patch

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.