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 |
} |