shithub: libvpx

Download patch

ref: 223f9e36718e8c2e33c38f96345dc9877d2e19e6
parent: 9037a05041ec080b9541e846af84241513e37aae
author: Marco Paniconi <marpan@google.com>
date: Mon Mar 26 06:53:38 EDT 2018

vp9-svc: Allow for setting frame drop thresholds per layer.

Add encoder control to set the frame drop thresholds per
spatial layer, and add a frame drop mode: 0 = per-layer drop,
and 1 = constrained drop mode (a drop on a given layer forces
drops to all upper layers).

Default is mode 0 (per-layer dropping).
Implementation for mode 1 will come in subsequent change.

If the control is not used, then the spatial layer frame
drop thresholds (water mark) are all equal and set to the value
given by the encoder config (oxcf->drop_frames_water_mark).

Bump up the ABI version.

Change-Id: Id038d4181b86fa98b3d44d026f96d5f344d81629

--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -396,7 +396,11 @@
 int vp9_rc_drop_frame(VP9_COMP *cpi) {
   const VP9EncoderConfig *oxcf = &cpi->oxcf;
   RATE_CONTROL *const rc = &cpi->rc;
-  if (!oxcf->drop_frames_water_mark) {
+  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 (!drop_frames_water_mark) {
     return 0;
   } else {
     if (rc->buffer_level < 0) {
@@ -406,7 +410,7 @@
       // If buffer is below drop_mark, for now just drop every other frame
       // (starting with the next frame) until it increases back over drop_mark.
       int drop_mark =
-          (int)(oxcf->drop_frames_water_mark * rc->optimal_buffer_level / 100);
+          (int)(drop_frames_water_mark * rc->optimal_buffer_level / 100);
       if ((rc->buffer_level > drop_mark) && (rc->decimation_factor > 0)) {
         --rc->decimation_factor;
       } else if (rc->buffer_level <= drop_mark && rc->decimation_factor == 0) {
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -39,6 +39,7 @@
   svc->non_reference_frame = 0;
   svc->skip_enhancement_layer = 0;
   svc->disable_inter_layer_pred = INTER_LAYER_PRED_ON;
+  svc->framedrop_mode = 0;
 
   for (i = 0; i < REF_FRAMES; ++i) svc->ref_frame_index[i] = -1;
   for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
@@ -50,6 +51,7 @@
     svc->ext_alt_fb_idx[sl] = 2;
     svc->downsample_filter_type[sl] = BILINEAR;
     svc->downsample_filter_phase[sl] = 8;  // Set to 8 for averaging filter.
+    svc->framedrop_thresh[sl] = oxcf->drop_frames_water_mark;
   }
 
   if (cpi->oxcf.error_resilient_mode == 0 && cpi->oxcf.pass == 2) {
--- a/vp9/encoder/vp9_svc_layercontext.h
+++ b/vp9/encoder/vp9_svc_layercontext.h
@@ -114,6 +114,8 @@
 
   int last_layer_dropped[VPX_MAX_LAYERS];
   int drop_spatial_layer[VPX_MAX_LAYERS];
+  int framedrop_thresh[VPX_MAX_LAYERS];
+  int framedrop_mode;
 
   INTER_LAYER_PRED disable_inter_layer_pred;
 } SVC;
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -1524,6 +1524,17 @@
   return VPX_CODEC_OK;
 }
 
+static vpx_codec_err_t ctrl_set_svc_frame_drop_layer(vpx_codec_alg_priv_t *ctx,
+                                                     va_list args) {
+  VP9_COMP *const cpi = ctx->cpi;
+  vpx_svc_frame_drop_t *data = va_arg(args, vpx_svc_frame_drop_t *);
+  int sl;
+  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];
+  return VPX_CODEC_OK;
+}
+
 static vpx_codec_err_t ctrl_register_cx_callback(vpx_codec_alg_priv_t *ctx,
                                                  va_list args) {
   vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp =
@@ -1608,6 +1619,7 @@
   { VP9E_SET_ROW_MT, ctrl_set_row_mt },
   { VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST, ctrl_enable_motion_vector_unit_test },
   { VP9E_SET_SVC_INTER_LAYER_PRED, ctrl_set_svc_inter_layer_pred },
+  { VP9E_SET_SVC_FRAME_DROP_LAYER, ctrl_set_svc_frame_drop_layer },
 
   // Getters
   { VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer },
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -611,6 +611,15 @@
    * Supported in codecs: VP9
    */
   VP9E_SET_SVC_INTER_LAYER_PRED,
+
+  /*!\brief Codec control function to set mode and thresholds for frame
+   *  dropping in SVC. Drop frame thresholds are set per-layer. Mode is set as:
+   * 0 : layer-dependent dropping, 1 : constrained dropping, current layer drop
+   * forces drop on all upper layers. Default mode is 0.
+   *
+   * Supported in codecs: VP9
+   */
+  VP9E_SET_SVC_FRAME_DROP_LAYER,
 };
 
 /*!\brief vpx 1-D scaling mode
@@ -754,6 +763,18 @@
   int alt_fb_idx[VPX_TS_MAX_LAYERS];  /**< Altref buffer index. */
 } vpx_svc_ref_frame_config_t;
 
+/*!\brief  vp9 svc frame dropping parameters.
+ *
+ * This defines the frame drop thresholds for each spatial layer, and the
+ * the frame dropping mode: 0 = layer based frame dropping (default),
+ * 1 = constrained dropping where current layer drop forces all upper
+ * spatial layers to drop.
+ */
+typedef struct vpx_svc_frame_drop {
+  int framedrop_thresh[VPX_SS_MAX_LAYERS]; /**< Frame flags. */
+  int framedrop_mode; /**< Layer-based or constrained dropping. */
+} vpx_svc_frame_drop_t;
+
 /*!\cond */
 /*!\brief VP8 encoder control function parameter type
  *
@@ -890,6 +911,9 @@
 
 VPX_CTRL_USE_TYPE(VP9E_SET_SVC_INTER_LAYER_PRED, unsigned int)
 #define VPX_CTRL_VP9E_SET_SVC_INTER_LAYER_PRED
+
+VPX_CTRL_USE_TYPE(VP9E_SET_SVC_FRAME_DROP_LAYER, vpx_svc_frame_drop_t *)
+#define VPX_CTRL_VP9E_SET_SVC_FRAME_DROP_LAYER
 
 /*!\endcond */
 /*! @} - end defgroup vp8_encoder */
--- a/vpx/vpx_encoder.h
+++ b/vpx/vpx_encoder.h
@@ -63,7 +63,7 @@
  * fields to structures
  */
 #define VPX_ENCODER_ABI_VERSION \
-  (10 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
+  (11 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
 
 /*! \brief Encoder capabilities bitfield
  *