vpx_codec_err_t vpx_svc_get_layer_resolution(const SvcContext *svc_ctx, int layer, unsigned int *width, unsigned int *height) { int w, h, index, num, den; const SvcInternal *const si = get_const_svc_internal(svc_ctx); if (svc_ctx == NULL || si == NULL || width == NULL || height == NULL) { return VPX_CODEC_INVALID_PARAM; } if (layer < 0 || layer >= si->layers) return VPX_CODEC_INVALID_PARAM; index = layer + VPX_SS_MAX_LAYERS - si->layers; num = si->scaling_factor_num[index]; den = si->scaling_factor_den[index]; if (num == 0 || den == 0) return VPX_CODEC_INVALID_PARAM; w = si->width * num / den; h = si->height * num / den; // make height and width even to make chrome player happy w += w % 2; h += h % 2; *width = w; *height = h; return VPX_CODEC_OK; }
void assign_layer_bitrates(const SvcContext *svc_ctx, vpx_codec_enc_cfg_t *const enc_cfg) { int i; const SvcInternal *const si = get_const_svc_internal(svc_ctx); if (si->bitrates[0] != 0) { enc_cfg->rc_target_bitrate = 0; for (i = 0; i < svc_ctx->spatial_layers; ++i) { enc_cfg->ss_target_bitrate[i] = (unsigned int)si->bitrates[i]; enc_cfg->rc_target_bitrate += si->bitrates[i]; } } else { float total = 0; float alloc_ratio[VPX_SS_MAX_LAYERS] = {0}; for (i = 0; i < svc_ctx->spatial_layers; ++i) { if (si->scaling_factor_den[i] > 0) { alloc_ratio[i] = (float)(si->scaling_factor_num[i] * 1.0 / si->scaling_factor_den[i]); alloc_ratio[i] *= alloc_ratio[i]; total += alloc_ratio[i]; } } for (i = 0; i < svc_ctx->spatial_layers; ++i) { if (total > 0) { enc_cfg->ss_target_bitrate[i] = (unsigned int) (enc_cfg->rc_target_bitrate * alloc_ratio[i] / total); } } } }
const char *vpx_svc_get_message(const SvcContext *svc_ctx) { const SvcInternal_t *const si = get_const_svc_internal(svc_ctx); if (svc_ctx == NULL || si == NULL) return NULL; return si->message_buffer; }
vpx_codec_err_t assign_layer_bitrates(const SvcContext *svc_ctx, vpx_codec_enc_cfg_t *const enc_cfg) { int i; const SvcInternal_t *const si = get_const_svc_internal(svc_ctx); int sl, tl, spatial_layer_target; if (svc_ctx->temporal_layering_mode != 0) { if (si->bitrates[0] != 0) { unsigned int total_bitrate = 0; for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) { total_bitrate += si->bitrates[sl * svc_ctx->temporal_layers + svc_ctx->temporal_layers - 1]; for (tl = 0; tl < svc_ctx->temporal_layers; ++tl) { enc_cfg->ss_target_bitrate[sl * svc_ctx->temporal_layers] += (unsigned int)si->bitrates[sl * svc_ctx->temporal_layers + tl]; enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + tl] = si->bitrates[sl * svc_ctx->temporal_layers + tl]; if (tl > 0 && (si->bitrates[sl * svc_ctx->temporal_layers + tl] <= si->bitrates[sl * svc_ctx->temporal_layers + tl - 1])) return VPX_CODEC_INVALID_PARAM; } } if (total_bitrate != enc_cfg->rc_target_bitrate) return VPX_CODEC_INVALID_PARAM; } else { float total = 0; float alloc_ratio[VPX_MAX_LAYERS] = { 0 }; for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) { if (si->svc_params.scaling_factor_den[sl] > 0) { alloc_ratio[sl] = (float)(pow(2, sl)); total += alloc_ratio[sl]; } } for (sl = 0; sl < svc_ctx->spatial_layers; ++sl) { enc_cfg->ss_target_bitrate[sl] = spatial_layer_target = (unsigned int)(enc_cfg->rc_target_bitrate * alloc_ratio[sl] / total); if (svc_ctx->temporal_layering_mode == 3) { enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers] = (spatial_layer_target * 6) / 10; // 60% enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 1] = (spatial_layer_target * 8) / 10; // 80% enc_cfg->layer_target_bitrate[sl * svc_ctx->temporal_layers + 2] = spatial_layer_target; } 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] = spatial_layer_target; } else { // User should explicitly assign bitrates in this case. assert(0); } } } } else { if (si->bitrates[0] != 0) { unsigned int total_bitrate = 0; for (i = 0; i < svc_ctx->spatial_layers; ++i) { enc_cfg->ss_target_bitrate[i] = (unsigned int)si->bitrates[i]; enc_cfg->layer_target_bitrate[i] = (unsigned int)si->bitrates[i]; total_bitrate += si->bitrates[i]; } if (total_bitrate != enc_cfg->rc_target_bitrate) return VPX_CODEC_INVALID_PARAM; } else { float total = 0; float alloc_ratio[VPX_MAX_LAYERS] = { 0 }; for (i = 0; i < svc_ctx->spatial_layers; ++i) { if (si->svc_params.scaling_factor_den[i] > 0) { alloc_ratio[i] = (float)(si->svc_params.scaling_factor_num[i] * 1.0 / si->svc_params.scaling_factor_den[i]); alloc_ratio[i] *= alloc_ratio[i]; total += alloc_ratio[i]; } } for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) { if (total > 0) { enc_cfg->layer_target_bitrate[i] = (unsigned int)(enc_cfg->rc_target_bitrate * alloc_ratio[i] / total); } } } } return VPX_CODEC_OK; }
int vpx_svc_is_keyframe(const SvcContext *svc_ctx) { const SvcInternal *const si = get_const_svc_internal(svc_ctx); if (svc_ctx == NULL || si == NULL) return 0; return si->is_keyframe; }
int vpx_svc_get_encode_frame_count(const SvcContext *svc_ctx) { const SvcInternal *const si = get_const_svc_internal(svc_ctx); if (svc_ctx == NULL || si == NULL) return 0; return si->encode_frame_count; }
size_t vpx_svc_get_frame_size(const SvcContext *svc_ctx) { const SvcInternal *const si = get_const_svc_internal(svc_ctx); if (svc_ctx == NULL || si == NULL) return 0; return si->frame_size; }
void *vpx_svc_get_buffer(const SvcContext *svc_ctx) { const SvcInternal *const si = get_const_svc_internal(svc_ctx); if (svc_ctx == NULL || si == NULL) return NULL; return si->buffer; }