| Index: source/libvpx/vp9/vp9_cx_iface.c
|
| ===================================================================
|
| --- source/libvpx/vp9/vp9_cx_iface.c (revision 251189)
|
| +++ source/libvpx/vp9/vp9_cx_iface.c (working copy)
|
| @@ -175,6 +175,23 @@
|
|
|
| RANGE_CHECK(cfg, ss_number_layers, 1,
|
| VPX_SS_MAX_LAYERS); /*Spatial layers max */
|
| +
|
| + RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
|
| + if (cfg->ts_number_layers > 1) {
|
| + unsigned int i;
|
| + for (i = 1; i < cfg->ts_number_layers; ++i) {
|
| + if (cfg->ts_target_bitrate[i] < cfg->ts_target_bitrate[i-1]) {
|
| + ERROR("ts_target_bitrate entries are not increasing");
|
| + }
|
| + }
|
| + RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers-1], 1, 1);
|
| + for (i = cfg->ts_number_layers-2; i > 0; --i) {
|
| + if (cfg->ts_rate_decimator[i-1] != 2*cfg->ts_rate_decimator[i]) {
|
| + ERROR("ts_rate_decimator factors are not powers of 2");
|
| + }
|
| + }
|
| + }
|
| +
|
| /* VP8 does not support a lower bound on the keyframe interval in
|
| * automatic keyframe placement mode.
|
| */
|
| @@ -205,7 +222,7 @@
|
| int n_packets = (int)(cfg->rc_twopass_stats_in.sz / packet_sz);
|
| FIRSTPASS_STATS *stats;
|
|
|
| - if (!cfg->rc_twopass_stats_in.buf)
|
| + if (cfg->rc_twopass_stats_in.buf == NULL)
|
| ERROR("rc_twopass_stats_in.buf not set.");
|
|
|
| if (cfg->rc_twopass_stats_in.sz % packet_sz)
|
| @@ -279,14 +296,11 @@
|
| oxcf->lag_in_frames = cfg.g_lag_in_frames;
|
| }
|
|
|
| - // VBR only supported for now.
|
| - // CBR code has been deprectated for experimental phase.
|
| - // CQ mode not yet tested
|
| - oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
|
| + oxcf->end_usage = USAGE_LOCAL_FILE_PLAYBACK;
|
| if (cfg.rc_end_usage == VPX_CQ)
|
| - oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
|
| + oxcf->end_usage = USAGE_CONSTRAINED_QUALITY;
|
| else if (cfg.rc_end_usage == VPX_Q)
|
| - oxcf->end_usage = USAGE_CONSTANT_QUALITY;
|
| + oxcf->end_usage = USAGE_CONSTANT_QUALITY;
|
| else if (cfg.rc_end_usage == VPX_CBR)
|
| oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
|
|
|
| @@ -316,9 +330,6 @@
|
| // oxcf->kf_min_dist = cfg.kf_min_dis;
|
| oxcf->key_freq = cfg.kf_max_dist;
|
|
|
| - // oxcf->delete_first_pass_file = cfg.g_delete_firstpassfile;
|
| - // strcpy(oxcf->first_pass_file, cfg.g_firstpass_file);
|
| -
|
| oxcf->cpu_used = vp8_cfg.cpu_used;
|
| oxcf->encode_breakout = vp8_cfg.static_thresh;
|
| oxcf->play_alternate = vp8_cfg.enable_auto_alt_ref;
|
| @@ -345,6 +356,19 @@
|
| oxcf->aq_mode = vp8_cfg.aq_mode;
|
|
|
| oxcf->ss_number_layers = cfg.ss_number_layers;
|
| +
|
| + oxcf->ts_number_layers = cfg.ts_number_layers;
|
| +
|
| + if (oxcf->ts_number_layers > 1) {
|
| + memcpy(oxcf->ts_target_bitrate, cfg.ts_target_bitrate,
|
| + sizeof(cfg.ts_target_bitrate));
|
| + memcpy(oxcf->ts_rate_decimator, cfg.ts_rate_decimator,
|
| + sizeof(cfg.ts_rate_decimator));
|
| + } else if (oxcf->ts_number_layers == 1) {
|
| + oxcf->ts_target_bitrate[0] = oxcf->target_bandwidth;
|
| + oxcf->ts_rate_decimator[0] = 1;
|
| + }
|
| +
|
| /*
|
| printf("Current VP9 Settings: \n");
|
| printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
|
| @@ -352,7 +376,6 @@
|
| printf("sharpness: %d\n", oxcf->sharpness);
|
| printf("cpu_used: %d\n", oxcf->cpu_used);
|
| printf("Mode: %d\n", oxcf->mode);
|
| - // printf("delete_first_pass_file: %d\n", oxcf->delete_first_pass_file);
|
| printf("auto_key: %d\n", oxcf->auto_key);
|
| printf("key_freq: %d\n", oxcf->key_freq);
|
| printf("end_usage: %d\n", oxcf->end_usage);
|
| @@ -396,7 +419,7 @@
|
|
|
| res = validate_config(ctx, cfg, &ctx->vp8_cfg);
|
|
|
| - if (!res) {
|
| + if (res == VPX_CODEC_OK) {
|
| ctx->cfg = *cfg;
|
| set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
|
| vp9_change_config(ctx->cpi, &ctx->oxcf);
|
| @@ -416,8 +439,7 @@
|
|
|
| #define MAP(id, var) case id: *(RECAST(id, arg)) = var; break
|
|
|
| - if (!arg)
|
| - return VPX_CODEC_INVALID_PARAM;
|
| + if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
|
|
|
| switch (ctrl_id) {
|
| MAP(VP8E_GET_LAST_QUANTIZER, vp9_get_quantizer(ctx->cpi));
|
| @@ -459,7 +481,7 @@
|
|
|
| res = validate_config(ctx, &ctx->cfg, &xcfg);
|
|
|
| - if (!res) {
|
| + if (res == VPX_CODEC_OK) {
|
| ctx->vp8_cfg = xcfg;
|
| set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
|
| vp9_change_config(ctx->cpi, &ctx->oxcf);
|
| @@ -478,12 +500,10 @@
|
|
|
| VP9_PTR optr;
|
|
|
| - if (!ctx->priv) {
|
| + if (ctx->priv == NULL) {
|
| priv = calloc(1, sizeof(struct vpx_codec_alg_priv));
|
|
|
| - if (!priv) {
|
| - return VPX_CODEC_MEM_ERROR;
|
| - }
|
| + if (priv == NULL) return VPX_CODEC_MEM_ERROR;
|
|
|
| ctx->priv = &priv->base;
|
| ctx->priv->sz = sizeof(*ctx->priv);
|
| @@ -520,21 +540,19 @@
|
|
|
| priv->cx_data = malloc(priv->cx_data_sz);
|
|
|
| - if (!priv->cx_data) {
|
| - return VPX_CODEC_MEM_ERROR;
|
| - }
|
| + if (priv->cx_data == NULL) return VPX_CODEC_MEM_ERROR;
|
|
|
| vp9_initialize_enc();
|
|
|
| res = validate_config(priv, &priv->cfg, &priv->vp8_cfg);
|
|
|
| - if (!res) {
|
| + if (res == VPX_CODEC_OK) {
|
| set_vp9e_config(&ctx->priv->alg_priv->oxcf,
|
| ctx->priv->alg_priv->cfg,
|
| ctx->priv->alg_priv->vp8_cfg);
|
| optr = vp9_create_compressor(&ctx->priv->alg_priv->oxcf);
|
|
|
| - if (!optr)
|
| + if (optr == NULL)
|
| res = VPX_CODEC_MEM_ERROR;
|
| else
|
| ctx->priv->alg_priv->cpi = optr;
|
| @@ -563,11 +581,22 @@
|
| unsigned int new_qc;
|
|
|
| /* Use best quality mode if no deadline is given. */
|
| - if (deadline)
|
| - new_qc = MODE_GOODQUALITY;
|
| - else
|
| - new_qc = MODE_BESTQUALITY;
|
| + new_qc = MODE_BESTQUALITY;
|
|
|
| + if (deadline) {
|
| + uint64_t duration_us;
|
| +
|
| + /* Convert duration parameter from stream timebase to microseconds */
|
| + duration_us = (uint64_t)duration * 1000000
|
| + * (uint64_t)ctx->cfg.g_timebase.num
|
| + / (uint64_t)ctx->cfg.g_timebase.den;
|
| +
|
| + /* If the deadline is more that the duration this frame is to be shown,
|
| + * use good quality mode. Otherwise use realtime mode.
|
| + */
|
| + new_qc = (deadline > duration_us) ? MODE_GOODQUALITY : MODE_REALTIME;
|
| + }
|
| +
|
| if (ctx->cfg.g_pass == VPX_RC_FIRST_PASS)
|
| new_qc = MODE_FIRSTPASS;
|
| else if (ctx->cfg.g_pass == VPX_RC_LAST_PASS)
|
| @@ -691,7 +720,7 @@
|
| }
|
|
|
| /* Initialize the encoder instance on the first frame. */
|
| - if (!res && ctx->cpi) {
|
| + if (res == VPX_CODEC_OK && ctx->cpi != NULL) {
|
| unsigned int lib_flags;
|
| YV12_BUFFER_CONFIG sd;
|
| int64_t dst_time_stamp, dst_end_time_stamp;
|
| @@ -751,8 +780,8 @@
|
| VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
|
|
|
| /* Pack invisible frames with the next visible frame */
|
| - if (!cpi->common.show_frame) {
|
| - if (!ctx->pending_cx_data)
|
| + if (cpi->common.show_frame == 0) {
|
| + if (ctx->pending_cx_data == 0)
|
| ctx->pending_cx_data = cx_data;
|
| ctx->pending_cx_data_sz += size;
|
| ctx->pending_frame_sizes[ctx->pending_frame_count++] = size;
|
| @@ -777,7 +806,7 @@
|
| if (lib_flags & FRAMEFLAGS_KEY)
|
| pkt.data.frame.flags |= VPX_FRAME_IS_KEY;
|
|
|
| - if (!cpi->common.show_frame) {
|
| + if (cpi->common.show_frame == 0) {
|
| pkt.data.frame.flags |= VPX_FRAME_IS_INVISIBLE;
|
|
|
| // This timestamp should be as close as possible to the
|
| @@ -851,10 +880,9 @@
|
| static vpx_codec_err_t vp9e_set_reference(vpx_codec_alg_priv_t *ctx,
|
| int ctr_id,
|
| va_list args) {
|
| - vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
|
| + vpx_ref_frame_t *frame = va_arg(args, vpx_ref_frame_t *);
|
|
|
| - if (data) {
|
| - vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
|
| + if (frame != NULL) {
|
| YV12_BUFFER_CONFIG sd;
|
|
|
| image2yuvconfig(&frame->img, &sd);
|
| @@ -869,10 +897,9 @@
|
| static vpx_codec_err_t vp9e_copy_reference(vpx_codec_alg_priv_t *ctx,
|
| int ctr_id,
|
| va_list args) {
|
| - vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
|
| + vpx_ref_frame_t *frame = va_arg(args, vpx_ref_frame_t *);
|
|
|
| - if (data) {
|
| - vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
|
| + if (frame != NULL) {
|
| YV12_BUFFER_CONFIG sd;
|
|
|
| image2yuvconfig(&frame->img, &sd);
|
| @@ -887,13 +914,13 @@
|
| static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx,
|
| int ctr_id,
|
| va_list args) {
|
| - vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);
|
| + vp9_ref_frame_t *frame = va_arg(args, vp9_ref_frame_t *);
|
|
|
| - if (data) {
|
| + if (frame != NULL) {
|
| YV12_BUFFER_CONFIG* fb;
|
|
|
| - vp9_get_reference_enc(ctx->cpi, data->idx, &fb);
|
| - yuvconfig2image(&data->img, fb, NULL);
|
| + vp9_get_reference_enc(ctx->cpi, frame->idx, &fb);
|
| + yuvconfig2image(&frame->img, fb, NULL);
|
| return VPX_CODEC_OK;
|
| } else {
|
| return VPX_CODEC_INVALID_PARAM;
|
| @@ -904,11 +931,11 @@
|
| int ctr_id,
|
| va_list args) {
|
| #if CONFIG_VP9_POSTPROC
|
| - vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
|
| + vp8_postproc_cfg_t *config = va_arg(args, vp8_postproc_cfg_t *);
|
| (void)ctr_id;
|
|
|
| - if (data) {
|
| - ctx->preview_ppcfg = *((vp8_postproc_cfg_t *)data);
|
| + if (config != NULL) {
|
| + ctx->preview_ppcfg = *config;
|
| return VPX_CODEC_OK;
|
| } else {
|
| return VPX_CODEC_INVALID_PARAM;
|
| @@ -982,20 +1009,14 @@
|
| static vpx_codec_err_t vp9e_set_scalemode(vpx_codec_alg_priv_t *ctx,
|
| int ctr_id,
|
| va_list args) {
|
| - vpx_scaling_mode_t *data = va_arg(args, vpx_scaling_mode_t *);
|
| + vpx_scaling_mode_t *scalemode = va_arg(args, vpx_scaling_mode_t *);
|
|
|
| - if (data) {
|
| + if (scalemode != NULL) {
|
| int res;
|
| - vpx_scaling_mode_t scalemode = *(vpx_scaling_mode_t *)data;
|
| res = vp9_set_internal_size(ctx->cpi,
|
| - (VPX_SCALING)scalemode.h_scaling_mode,
|
| - (VPX_SCALING)scalemode.v_scaling_mode);
|
| -
|
| - if (!res) {
|
| - return VPX_CODEC_OK;
|
| - } else {
|
| - return VPX_CODEC_INVALID_PARAM;
|
| - }
|
| + (VPX_SCALING)scalemode->h_scaling_mode,
|
| + (VPX_SCALING)scalemode->v_scaling_mode);
|
| + return (res == 0) ? VPX_CODEC_OK : VPX_CODEC_INVALID_PARAM;
|
| } else {
|
| return VPX_CODEC_INVALID_PARAM;
|
| }
|
| @@ -1005,32 +1026,54 @@
|
| va_list args) {
|
| int data = va_arg(args, int);
|
| vp9_set_svc(ctx->cpi, data);
|
| + // CBR mode for SVC with both temporal and spatial layers not yet supported.
|
| + if (data == 1 &&
|
| + ctx->cfg.rc_end_usage == VPX_CBR &&
|
| + ctx->cfg.ss_number_layers > 1 &&
|
| + ctx->cfg.ts_number_layers > 1) {
|
| + return VPX_CODEC_INVALID_PARAM;
|
| + }
|
| return VPX_CODEC_OK;
|
| }
|
|
|
| +static vpx_codec_err_t vp9e_set_svc_layer_id(vpx_codec_alg_priv_t *ctx,
|
| + int ctr_id,
|
| + va_list args) {
|
| + vpx_svc_layer_id_t *data = va_arg(args, vpx_svc_layer_id_t *);
|
| + VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
|
| + cpi->svc.spatial_layer_id = data->spatial_layer_id;
|
| + cpi->svc.temporal_layer_id = data->temporal_layer_id;
|
| + // Checks on valid layer_id input.
|
| + if (cpi->svc.temporal_layer_id < 0 ||
|
| + cpi->svc.temporal_layer_id >= (int)ctx->cfg.ts_number_layers) {
|
| + return VPX_CODEC_INVALID_PARAM;
|
| + }
|
| + if (cpi->svc.spatial_layer_id < 0 ||
|
| + cpi->svc.spatial_layer_id >= ctx->cfg.ss_number_layers) {
|
| + return VPX_CODEC_INVALID_PARAM;
|
| + }
|
| + return VPX_CODEC_OK;
|
| +}
|
| +
|
| static vpx_codec_err_t vp9e_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
|
| int ctr_id, va_list args) {
|
| - vpx_svc_parameters_t *data = va_arg(args, vpx_svc_parameters_t *);
|
| VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
|
| - vpx_svc_parameters_t params;
|
| + vpx_svc_parameters_t *params = va_arg(args, vpx_svc_parameters_t *);
|
|
|
| - if (data == NULL) {
|
| - return VPX_CODEC_INVALID_PARAM;
|
| - }
|
| + if (params == NULL) return VPX_CODEC_INVALID_PARAM;
|
|
|
| - params = *(vpx_svc_parameters_t *)data;
|
| + cpi->svc.spatial_layer_id = params->spatial_layer;
|
| + cpi->svc.temporal_layer_id = params->temporal_layer;
|
|
|
| - cpi->current_layer = params.layer;
|
| - cpi->lst_fb_idx = params.lst_fb_idx;
|
| - cpi->gld_fb_idx = params.gld_fb_idx;
|
| - cpi->alt_fb_idx = params.alt_fb_idx;
|
| + cpi->lst_fb_idx = params->lst_fb_idx;
|
| + cpi->gld_fb_idx = params->gld_fb_idx;
|
| + cpi->alt_fb_idx = params->alt_fb_idx;
|
|
|
| - if (vp9_set_size_literal(ctx->cpi, params.width, params.height) != 0) {
|
| + if (vp9_set_size_literal(ctx->cpi, params->width, params->height) != 0)
|
| return VPX_CODEC_INVALID_PARAM;
|
| - }
|
|
|
| - ctx->cfg.rc_max_quantizer = params.max_quantizer;
|
| - ctx->cfg.rc_min_quantizer = params.min_quantizer;
|
| + ctx->cfg.rc_max_quantizer = params->max_quantizer;
|
| + ctx->cfg.rc_min_quantizer = params->min_quantizer;
|
|
|
| set_vp9e_config(&ctx->oxcf, ctx->cfg, ctx->vp8_cfg);
|
| vp9_change_config(ctx->cpi, &ctx->oxcf);
|
| @@ -1069,6 +1112,7 @@
|
| {VP9_GET_REFERENCE, get_reference},
|
| {VP9E_SET_SVC, vp9e_set_svc},
|
| {VP9E_SET_SVC_PARAMETERS, vp9e_set_svc_parameters},
|
| + {VP9E_SET_SVC_LAYER_ID, vp9e_set_svc_layer_id},
|
| { -1, NULL},
|
| };
|
|
|
| @@ -1119,9 +1163,12 @@
|
| 9999, /* kf_max_dist */
|
|
|
| VPX_SS_DEFAULT_LAYERS, /* ss_number_layers */
|
| -
|
| + 1, /* ts_number_layers */
|
| + {0}, /* ts_target_bitrate */
|
| + {0}, /* ts_rate_decimator */
|
| + 0, /* ts_periodicity */
|
| + {0}, /* ts_layer_id */
|
| #if VPX_ENCODER_ABI_VERSION == (1 + VPX_CODEC_ABI_VERSION)
|
| - 1, /* g_delete_first_pass_file */
|
| "vp8.fpf" /* first pass filename */
|
| #endif
|
| }
|
|
|