michael@0: /* michael@0: * Copyright (c) 2010 The WebM project authors. All Rights Reserved. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license michael@0: * that can be found in the LICENSE file in the root of the source michael@0: * tree. An additional intellectual property rights grant can be found michael@0: * in the file PATENTS. All contributing project authors may michael@0: * be found in the AUTHORS file in the root of the source tree. michael@0: */ michael@0: michael@0: michael@0: /*!\file michael@0: * \brief Provides the high level interface to wrap decoder algorithms. michael@0: * michael@0: */ michael@0: #include michael@0: #include "vpx/internal/vpx_codec_internal.h" michael@0: michael@0: #define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var) michael@0: michael@0: vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t *ctx, michael@0: vpx_codec_iface_t *iface, michael@0: vpx_codec_dec_cfg_t *cfg, michael@0: vpx_codec_flags_t flags, michael@0: int ver) { michael@0: vpx_codec_err_t res; michael@0: michael@0: if (ver != VPX_DECODER_ABI_VERSION) michael@0: res = VPX_CODEC_ABI_MISMATCH; michael@0: else if (!ctx || !iface) michael@0: res = VPX_CODEC_INVALID_PARAM; michael@0: else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION) michael@0: res = VPX_CODEC_ABI_MISMATCH; michael@0: else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA)) michael@0: res = VPX_CODEC_INCAPABLE; michael@0: else if ((flags & VPX_CODEC_USE_POSTPROC) && !(iface->caps & VPX_CODEC_CAP_POSTPROC)) michael@0: res = VPX_CODEC_INCAPABLE; michael@0: else if ((flags & VPX_CODEC_USE_ERROR_CONCEALMENT) && michael@0: !(iface->caps & VPX_CODEC_CAP_ERROR_CONCEALMENT)) michael@0: res = VPX_CODEC_INCAPABLE; michael@0: else if ((flags & VPX_CODEC_USE_INPUT_FRAGMENTS) && michael@0: !(iface->caps & VPX_CODEC_CAP_INPUT_FRAGMENTS)) michael@0: res = VPX_CODEC_INCAPABLE; michael@0: else if (!(iface->caps & VPX_CODEC_CAP_DECODER)) michael@0: res = VPX_CODEC_INCAPABLE; michael@0: else { michael@0: memset(ctx, 0, sizeof(*ctx)); michael@0: ctx->iface = iface; michael@0: ctx->name = iface->name; michael@0: ctx->priv = NULL; michael@0: ctx->init_flags = flags; michael@0: ctx->config.dec = cfg; michael@0: res = VPX_CODEC_OK; michael@0: michael@0: if (!(flags & VPX_CODEC_USE_XMA)) { michael@0: res = ctx->iface->init(ctx, NULL); michael@0: michael@0: if (res) { michael@0: ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL; michael@0: vpx_codec_destroy(ctx); michael@0: } michael@0: michael@0: if (ctx->priv) michael@0: ctx->priv->iface = ctx->iface; michael@0: } michael@0: } michael@0: michael@0: return SAVE_STATUS(ctx, res); michael@0: } michael@0: michael@0: michael@0: vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface, michael@0: const uint8_t *data, michael@0: unsigned int data_sz, michael@0: vpx_codec_stream_info_t *si) { michael@0: vpx_codec_err_t res; michael@0: michael@0: if (!iface || !data || !data_sz || !si michael@0: || si->sz < sizeof(vpx_codec_stream_info_t)) michael@0: res = VPX_CODEC_INVALID_PARAM; michael@0: else { michael@0: /* Set default/unknown values */ michael@0: si->w = 0; michael@0: si->h = 0; michael@0: michael@0: res = iface->dec.peek_si(data, data_sz, si); michael@0: } michael@0: michael@0: return res; michael@0: } michael@0: michael@0: michael@0: vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t *ctx, michael@0: vpx_codec_stream_info_t *si) { michael@0: vpx_codec_err_t res; michael@0: michael@0: if (!ctx || !si || si->sz < sizeof(vpx_codec_stream_info_t)) michael@0: res = VPX_CODEC_INVALID_PARAM; michael@0: else if (!ctx->iface || !ctx->priv) michael@0: res = VPX_CODEC_ERROR; michael@0: else { michael@0: /* Set default/unknown values */ michael@0: si->w = 0; michael@0: si->h = 0; michael@0: michael@0: res = ctx->iface->dec.get_si(ctx->priv->alg_priv, si); michael@0: } michael@0: michael@0: return SAVE_STATUS(ctx, res); michael@0: } michael@0: michael@0: michael@0: vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx, michael@0: const uint8_t *data, michael@0: unsigned int data_sz, michael@0: void *user_priv, michael@0: long deadline) { michael@0: vpx_codec_err_t res; michael@0: michael@0: /* Sanity checks */ michael@0: /* NULL data ptr allowed if data_sz is 0 too */ michael@0: if (!ctx || (!data && data_sz)) michael@0: res = VPX_CODEC_INVALID_PARAM; michael@0: else if (!ctx->iface || !ctx->priv) michael@0: res = VPX_CODEC_ERROR; michael@0: else { michael@0: res = ctx->iface->dec.decode(ctx->priv->alg_priv, data, data_sz, michael@0: user_priv, deadline); michael@0: } michael@0: michael@0: return SAVE_STATUS(ctx, res); michael@0: } michael@0: michael@0: vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx, michael@0: vpx_codec_iter_t *iter) { michael@0: vpx_image_t *img; michael@0: michael@0: if (!ctx || !iter || !ctx->iface || !ctx->priv) michael@0: img = NULL; michael@0: else michael@0: img = ctx->iface->dec.get_frame(ctx->priv->alg_priv, iter); michael@0: michael@0: return img; michael@0: } michael@0: michael@0: michael@0: vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx, michael@0: vpx_codec_put_frame_cb_fn_t cb, michael@0: void *user_priv) { michael@0: vpx_codec_err_t res; michael@0: michael@0: if (!ctx || !cb) michael@0: res = VPX_CODEC_INVALID_PARAM; michael@0: else if (!ctx->iface || !ctx->priv michael@0: || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME)) michael@0: res = VPX_CODEC_ERROR; michael@0: else { michael@0: ctx->priv->dec.put_frame_cb.u.put_frame = cb; michael@0: ctx->priv->dec.put_frame_cb.user_priv = user_priv; michael@0: res = VPX_CODEC_OK; michael@0: } michael@0: michael@0: return SAVE_STATUS(ctx, res); michael@0: } michael@0: michael@0: michael@0: vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx, michael@0: vpx_codec_put_slice_cb_fn_t cb, michael@0: void *user_priv) { michael@0: vpx_codec_err_t res; michael@0: michael@0: if (!ctx || !cb) michael@0: res = VPX_CODEC_INVALID_PARAM; michael@0: else if (!ctx->iface || !ctx->priv michael@0: || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME)) michael@0: res = VPX_CODEC_ERROR; michael@0: else { michael@0: ctx->priv->dec.put_slice_cb.u.put_slice = cb; michael@0: ctx->priv->dec.put_slice_cb.user_priv = user_priv; michael@0: res = VPX_CODEC_OK; michael@0: } michael@0: michael@0: return SAVE_STATUS(ctx, res); michael@0: } michael@0: michael@0: michael@0: vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t *ctx, michael@0: vpx_codec_mmap_t *mmap, michael@0: vpx_codec_iter_t *iter) { michael@0: vpx_codec_err_t res = VPX_CODEC_OK; michael@0: michael@0: if (!ctx || !mmap || !iter || !ctx->iface) michael@0: res = VPX_CODEC_INVALID_PARAM; michael@0: else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA)) michael@0: res = VPX_CODEC_ERROR; michael@0: else michael@0: res = ctx->iface->get_mmap(ctx, mmap, iter); michael@0: michael@0: return SAVE_STATUS(ctx, res); michael@0: } michael@0: michael@0: michael@0: vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t *ctx, michael@0: vpx_codec_mmap_t *mmap, michael@0: unsigned int num_maps) { michael@0: vpx_codec_err_t res = VPX_CODEC_MEM_ERROR; michael@0: michael@0: if (!ctx || !mmap || !ctx->iface) michael@0: res = VPX_CODEC_INVALID_PARAM; michael@0: else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA)) michael@0: res = VPX_CODEC_ERROR; michael@0: else { michael@0: unsigned int i; michael@0: michael@0: for (i = 0; i < num_maps; i++, mmap++) { michael@0: if (!mmap->base) michael@0: break; michael@0: michael@0: /* Everything look ok, set the mmap in the decoder */ michael@0: res = ctx->iface->set_mmap(ctx, mmap); michael@0: michael@0: if (res) michael@0: break; michael@0: } michael@0: } michael@0: michael@0: return SAVE_STATUS(ctx, res); michael@0: }