Merge "Add SVC codec control to set frame flags and buffer indices."
This commit is contained in:
Коммит
e12ec3615c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
25
vpx/vp8cx.h
25
vpx/vp8cx.h
|
@ -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"
|
||||
|
|
Загрузка…
Ссылка в новой задаче