Commit e12ec361 authored by Marco Paniconi's avatar Marco Paniconi Committed by Gerrit Code Review
Browse files

Merge "Add SVC codec control to set frame flags and buffer indices."

parents 9d8decc1 730cdefd
...@@ -544,6 +544,59 @@ vpx_codec_err_t parse_superframe_index(const uint8_t *data, ...@@ -544,6 +544,59 @@ vpx_codec_err_t parse_superframe_index(const uint8_t *data,
} }
#endif #endif
// Example pattern for spatial layers and 2 temporal layers used in the
// bypass/flexible mode. The pattern corresponds to the pattern
// VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in
// non-flexible mode.
void set_frame_flags_bypass_mode(int sl, int tl, int num_spatial_layers,
int is_key_frame,
vpx_svc_ref_frame_config_t *ref_frame_config) {
for (sl = 0; sl < num_spatial_layers; ++sl) {
if (!tl) {
if (!sl) {
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF |
VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_GF |
VP8_EFLAG_NO_UPD_ARF;
} else {
if (is_key_frame) {
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_LAST |
VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_GF |
VP8_EFLAG_NO_UPD_ARF;
} else {
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_GF |
VP8_EFLAG_NO_UPD_ARF;
}
}
} else if (tl == 1) {
if (!sl) {
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF |
VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_LAST |
VP8_EFLAG_NO_UPD_GF;
} else {
ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF |
VP8_EFLAG_NO_UPD_LAST |
VP8_EFLAG_NO_UPD_GF;
}
}
if (tl == 0) {
ref_frame_config->lst_fb_idx[sl] = sl;
if (sl)
ref_frame_config->gld_fb_idx[sl] = sl - 1;
else
ref_frame_config->gld_fb_idx[sl] = 0;
ref_frame_config->alt_fb_idx[sl] = 0;
} else if (tl == 1) {
ref_frame_config->lst_fb_idx[sl] = sl;
ref_frame_config->gld_fb_idx[sl] = num_spatial_layers + sl - 1;
ref_frame_config->alt_fb_idx[sl] = num_spatial_layers + sl;
}
}
}
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
AppInput app_input = {0}; AppInput app_input = {0};
VpxVideoWriter *writer = NULL; VpxVideoWriter *writer = NULL;
...@@ -564,6 +617,7 @@ int main(int argc, const char **argv) { ...@@ -564,6 +617,7 @@ int main(int argc, const char **argv) {
VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL}; VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL};
struct RateControlStats rc; struct RateControlStats rc;
vpx_svc_layer_id_t layer_id; vpx_svc_layer_id_t layer_id;
vpx_svc_ref_frame_config_t ref_frame_config;
int sl, tl; int sl, tl;
double sum_bitrate = 0.0; double sum_bitrate = 0.0;
double sum_bitrate2 = 0.0; double sum_bitrate2 = 0.0;
...@@ -653,6 +707,30 @@ int main(int argc, const char **argv) { ...@@ -653,6 +707,30 @@ int main(int argc, const char **argv) {
end_of_stream = 1; end_of_stream = 1;
} }
// For BYPASS/FLEXIBLE mode, set the frame flags (reference and updates)
// and the buffer indices for each spatial layer of the current
// (super)frame to be encoded. The temporal layer_id for the current frame
// also needs to be set.
// TODO(marpan): Should rename the "VP9E_TEMPORAL_LAYERING_MODE_BYPASS"
// mode to "VP9E_LAYERING_MODE_BYPASS".
if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
// Example for 2 temporal layers.
if (frame_cnt % 2 == 0)
layer_id.temporal_layer_id = 0;
else
layer_id.temporal_layer_id = 1;
// Note that we only set the temporal layer_id, since we are calling
// the encode for the whole superframe. The encoder will internally loop
// over all the spatial layers for the current superframe.
vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id);
set_frame_flags_bypass_mode(sl, layer_id.temporal_layer_id,
svc_ctx.spatial_layers,
frame_cnt == 0,
&ref_frame_config);
vpx_codec_control(&codec, VP9E_SET_SVC_REF_FRAME_CONFIG,
&ref_frame_config);
}
vpx_usec_timer_start(&timer); vpx_usec_timer_start(&timer);
res = vpx_svc_encode(&svc_ctx, &codec, (end_of_stream ? NULL : &raw), res = vpx_svc_encode(&svc_ctx, &codec, (end_of_stream ? NULL : &raw),
pts, frame_duration, svc_ctx.speed >= 5 ? pts, frame_duration, svc_ctx.speed >= 5 ?
......
...@@ -541,13 +541,21 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) { ...@@ -541,13 +541,21 @@ int vp9_one_pass_cbr_svc_start_layer(VP9_COMP *const cpi) {
set_flags_and_fb_idx_for_temporal_mode2(cpi); set_flags_and_fb_idx_for_temporal_mode2(cpi);
} else if (cpi->svc.temporal_layering_mode == } else if (cpi->svc.temporal_layering_mode ==
VP9E_TEMPORAL_LAYERING_MODE_BYPASS) { VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
// VP9E_TEMPORAL_LAYERING_MODE_BYPASS : // In the BYPASS/flexible mode, the encoder is relying on the application
// if the code goes here, it means the encoder will be relying on the // to specify, for each spatial layer, the flags and buffer indices for the
// flags from outside for layering. // layering.
// However, since when spatial+temporal layering is used, the buffer indices // Note that the check (cpi->ext_refresh_frame_flags_pending == 0) is
// cannot be derived automatically, the bypass mode will only work when the // needed to support the case where the frame flags may be passed in via
// number of spatial layers equals 1. // vpx_codec_encode(), which can be used for the temporal-only svc case.
assert(cpi->svc.number_spatial_layers == 1); if (cpi->ext_refresh_frame_flags_pending == 0) {
int sl;
cpi->svc.spatial_layer_id = cpi->svc.spatial_layer_to_encode;
sl = cpi->svc.spatial_layer_id;
vp9_apply_encoding_flags(cpi, cpi->svc.ext_frame_flags[sl]);
cpi->lst_fb_idx = cpi->svc.ext_lst_fb_idx[sl];
cpi->gld_fb_idx = cpi->svc.ext_gld_fb_idx[sl];
cpi->alt_fb_idx = cpi->svc.ext_alt_fb_idx[sl];
}
} }
lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id * lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id *
......
...@@ -74,6 +74,12 @@ typedef struct { ...@@ -74,6 +74,12 @@ typedef struct {
// Indicates what sort of temporal layering is used. // Indicates what sort of temporal layering is used.
// Currently, this only works for CBR mode. // Currently, this only works for CBR mode.
VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode; VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode;
// Frame flags and buffer indexes for each spatial layer, set by the
// application (external settings).
int ext_frame_flags[VPX_MAX_LAYERS];
int ext_lst_fb_idx[VPX_MAX_LAYERS];
int ext_gld_fb_idx[VPX_MAX_LAYERS];
int ext_alt_fb_idx[VPX_MAX_LAYERS];
} SVC; } SVC;
struct VP9_COMP; struct VP9_COMP;
......
...@@ -1416,6 +1416,20 @@ static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx, ...@@ -1416,6 +1416,20 @@ static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
return VPX_CODEC_OK; return VPX_CODEC_OK;
} }
static vpx_codec_err_t ctrl_set_svc_ref_frame_config(vpx_codec_alg_priv_t *ctx,
va_list args) {
VP9_COMP *const cpi = ctx->cpi;
vpx_svc_ref_frame_config_t *data = va_arg(args, vpx_svc_ref_frame_config_t *);
int sl;
for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
cpi->svc.ext_frame_flags[sl] = data->frame_flags[sl];
cpi->svc.ext_lst_fb_idx[sl] = data->lst_fb_idx[sl];
cpi->svc.ext_gld_fb_idx[sl] = data->gld_fb_idx[sl];
cpi->svc.ext_alt_fb_idx[sl] = data->alt_fb_idx[sl];
}
return VPX_CODEC_OK;
}
static vpx_codec_err_t ctrl_register_cx_callback(vpx_codec_alg_priv_t *ctx, static vpx_codec_err_t ctrl_register_cx_callback(vpx_codec_alg_priv_t *ctx,
va_list args) { va_list args) {
vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp = vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp =
...@@ -1487,6 +1501,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { ...@@ -1487,6 +1501,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity}, {VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity},
{VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval}, {VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval},
{VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval}, {VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval},
{VP9E_SET_SVC_REF_FRAME_CONFIG, ctrl_set_svc_ref_frame_config},
// Getters // Getters
{VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer}, {VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer},
......
...@@ -339,7 +339,8 @@ void assign_layer_bitrates(const SvcContext *svc_ctx, ...@@ -339,7 +339,8 @@ void assign_layer_bitrates(const SvcContext *svc_ctx,
(spatial_layer_target >> 1) + (spatial_layer_target >> 2); (spatial_layer_target >> 1) + (spatial_layer_target >> 2);
enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 2] = enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 2] =
spatial_layer_target; spatial_layer_target;
} else if (svc_ctx->temporal_layering_mode == 2) { } else if (svc_ctx->temporal_layering_mode == 2 ||
svc_ctx->temporal_layering_mode == 1) {
enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers] = enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers] =
spatial_layer_target * 2 / 3; spatial_layer_target * 2 / 3;
enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 1] = enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 1] =
...@@ -417,7 +418,8 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx, ...@@ -417,7 +418,8 @@ vpx_codec_err_t vpx_svc_init(SvcContext *svc_ctx, vpx_codec_ctx_t *codec_ctx,
// si->svc_params.temporal_layering_mode = svc_ctx->temporal_layering_mode; // si->svc_params.temporal_layering_mode = svc_ctx->temporal_layering_mode;
if (svc_ctx->temporal_layering_mode == 3) { if (svc_ctx->temporal_layering_mode == 3) {
svc_ctx->temporal_layers = 3; svc_ctx->temporal_layers = 3;
} else if (svc_ctx->temporal_layering_mode == 2) { } else if (svc_ctx->temporal_layering_mode == 2 ||
svc_ctx->temporal_layering_mode == 1) {
svc_ctx->temporal_layers = 2; svc_ctx->temporal_layers = 2;
} }
......
...@@ -556,6 +556,14 @@ enum vp8e_enc_control_id { ...@@ -556,6 +556,14 @@ enum vp8e_enc_control_id {
* Supported in codecs: VP9 * Supported in codecs: VP9
*/ */
VP9E_SET_COLOR_RANGE, VP9E_SET_COLOR_RANGE,
/*!\brief Codec control function to set the frame flags and buffer indices
* for spatial layers. The frame flags and buffer indices are set using the
* struct #vpx_svc_ref_frame_config defined below.
*
* Supported in codecs: VP9
*/
VP9E_SET_SVC_REF_FRAME_CONFIG,
}; };
/*!\brief vpx 1-D scaling mode /*!\brief vpx 1-D scaling mode
...@@ -682,6 +690,21 @@ typedef struct vpx_svc_layer_id { ...@@ -682,6 +690,21 @@ typedef struct vpx_svc_layer_id {
int temporal_layer_id; /**< Temporal layer id number. */ int temporal_layer_id; /**< Temporal layer id number. */
} vpx_svc_layer_id_t; } vpx_svc_layer_id_t;
/*!\brief vp9 svc frame flag parameters.
*
* This defines the frame flags and buffer indices for each spatial layer for
* svc encoding.
* This is used with the #VP9E_SET_SVC_REF_FRAME_CONFIG control to set frame
* flags and buffer indices for each spatial layer for the current (super)frame.
*
*/
typedef struct vpx_svc_ref_frame_config {
int frame_flags[VPX_TS_MAX_LAYERS]; /**< Frame flags. */
int lst_fb_idx[VPX_TS_MAX_LAYERS]; /**< Last buffer index. */
int gld_fb_idx[VPX_TS_MAX_LAYERS]; /**< Golden buffer index. */
int alt_fb_idx[VPX_TS_MAX_LAYERS]; /**< Altref buffer index. */
} vpx_svc_ref_frame_config_t;
/*!\brief VP8 encoder control function parameter type /*!\brief VP8 encoder control function parameter type
* *
* Defines the data types that VP8E control functions take. Note that * Defines the data types that VP8E control functions take. Note that
...@@ -773,6 +796,8 @@ VPX_CTRL_USE_TYPE(VP9E_GET_ACTIVEMAP, vpx_active_map_t *) ...@@ -773,6 +796,8 @@ VPX_CTRL_USE_TYPE(VP9E_GET_ACTIVEMAP, vpx_active_map_t *)
*/ */
#define VPX_CTRL_VP9E_SET_COLOR_RANGE #define VPX_CTRL_VP9E_SET_COLOR_RANGE
VPX_CTRL_USE_TYPE(VP9E_SET_COLOR_RANGE, int) VPX_CTRL_USE_TYPE(VP9E_SET_COLOR_RANGE, int)
VPX_CTRL_USE_TYPE(VP9E_SET_SVC_REF_FRAME_CONFIG, vpx_svc_ref_frame_config_t *)
/*! @} - end defgroup vp8_encoder */ /*! @} - end defgroup vp8_encoder */
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment