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

This commit is contained in:
Marco Paniconi 2015-09-17 22:29:07 +00:00 коммит произвёл Gerrit Code Review
Родитель 9d8decc162 730cdefd3e
Коммит e12ec3615c
6 изменённых файлов: 143 добавлений и 9 удалений

Просмотреть файл

@ -544,6 +544,59 @@ vpx_codec_err_t parse_superframe_index(const uint8_t *data,
}
#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) {
AppInput app_input = {0};
VpxVideoWriter *writer = NULL;
@ -564,6 +617,7 @@ int main(int argc, const char **argv) {
VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL};
struct RateControlStats rc;
vpx_svc_layer_id_t layer_id;
vpx_svc_ref_frame_config_t ref_frame_config;
int sl, tl;
double sum_bitrate = 0.0;
double sum_bitrate2 = 0.0;
@ -653,6 +707,30 @@ int main(int argc, const char **argv) {
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);
res = vpx_svc_encode(&svc_ctx, &codec, (end_of_stream ? NULL : &raw),
pts, frame_duration, svc_ctx.speed >= 5 ?

Просмотреть файл

@ -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);
} else if (cpi->svc.temporal_layering_mode ==
VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
// VP9E_TEMPORAL_LAYERING_MODE_BYPASS :
// if the code goes here, it means the encoder will be relying on the
// flags from outside for layering.
// However, since when spatial+temporal layering is used, the buffer indices
// cannot be derived automatically, the bypass mode will only work when the
// number of spatial layers equals 1.
assert(cpi->svc.number_spatial_layers == 1);
// In the BYPASS/flexible mode, the encoder is relying on the application
// to specify, for each spatial layer, the flags and buffer indices for the
// layering.
// Note that the check (cpi->ext_refresh_frame_flags_pending == 0) is
// needed to support the case where the frame flags may be passed in via
// vpx_codec_encode(), which can be used for the temporal-only svc case.
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 *

Просмотреть файл

@ -74,6 +74,12 @@ typedef struct {
// Indicates what sort of temporal layering is used.
// Currently, this only works for CBR 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;
struct VP9_COMP;

Просмотреть файл

@ -1416,6 +1416,20 @@ static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
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,
va_list args) {
vpx_codec_priv_output_cx_pkt_cb_pair_t *cbp =
@ -1487,6 +1501,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity},
{VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_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
{VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer},

Просмотреть файл

@ -339,7 +339,8 @@ void assign_layer_bitrates(const SvcContext *svc_ctx,
(spatial_layer_target >> 1) + (spatial_layer_target >> 2);
enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 2] =
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] =
spatial_layer_target * 2 / 3;
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,
// si->svc_params.temporal_layering_mode = svc_ctx->temporal_layering_mode;
if (svc_ctx->temporal_layering_mode == 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;
}

Просмотреть файл

@ -556,6 +556,14 @@ enum vp8e_enc_control_id {
* Supported in codecs: VP9
*/
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
@ -682,6 +690,21 @@ typedef struct vpx_svc_layer_id {
int temporal_layer_id; /**< Temporal layer id number. */
} 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
*
* 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 *)
*/
#define VPX_CTRL_VP9E_SET_COLOR_RANGE
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 */
#ifdef __cplusplus
} // extern "C"