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) {
// 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) {
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) {
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) {
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;
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 =
{ 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 },
* 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
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
*
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 */
#ifdef __cplusplus
* fields to structures
*/
#define VPX_ENCODER_ABI_VERSION \
- (10 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
+ (11 + VPX_CODEC_ABI_VERSION) /**<\hideinitializer*/
/*! \brief Encoder capabilities bitfield
*