/*
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */


/*!\file
 * \brief Provides the high level interface to wrap decoder algorithms.
 *
 */
#include <string.h>
#include "vpx/internal/vpx_codec_internal.h"

#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)

vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t      *ctx,
                                       vpx_codec_iface_t    *iface,
                                       vpx_codec_dec_cfg_t  *cfg,
                                       vpx_codec_flags_t     flags,
                                       int                   ver) {
  vpx_codec_err_t res;

  if (ver != VPX_DECODER_ABI_VERSION)
    res = VPX_CODEC_ABI_MISMATCH;
  else if (!ctx || !iface)
    res = VPX_CODEC_INVALID_PARAM;
  else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION)
    res = VPX_CODEC_ABI_MISMATCH;
  else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA))
    res = VPX_CODEC_INCAPABLE;
  else if ((flags & VPX_CODEC_USE_POSTPROC) && !(iface->caps & VPX_CODEC_CAP_POSTPROC))
    res = VPX_CODEC_INCAPABLE;
  else if ((flags & VPX_CODEC_USE_ERROR_CONCEALMENT) &&
           !(iface->caps & VPX_CODEC_CAP_ERROR_CONCEALMENT))
    res = VPX_CODEC_INCAPABLE;
  else if ((flags & VPX_CODEC_USE_INPUT_FRAGMENTS) &&
           !(iface->caps & VPX_CODEC_CAP_INPUT_FRAGMENTS))
    res = VPX_CODEC_INCAPABLE;
  else if (!(iface->caps & VPX_CODEC_CAP_DECODER))
    res = VPX_CODEC_INCAPABLE;
  else {
    memset(ctx, 0, sizeof(*ctx));
    ctx->iface = iface;
    ctx->name = iface->name;
    ctx->priv = NULL;
    ctx->init_flags = flags;
    ctx->config.dec = cfg;
    res = VPX_CODEC_OK;

    if (!(flags & VPX_CODEC_USE_XMA)) {
      res = ctx->iface->init(ctx, NULL);

      if (res) {
        ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL;
        vpx_codec_destroy(ctx);
      }

      if (ctx->priv)
        ctx->priv->iface = ctx->iface;
    }
  }

  return SAVE_STATUS(ctx, res);
}


vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t       *iface,
                                           const uint8_t         *data,
                                           unsigned int           data_sz,
                                           vpx_codec_stream_info_t *si) {
  vpx_codec_err_t res;

  if (!iface || !data || !data_sz || !si
      || si->sz < sizeof(vpx_codec_stream_info_t))
    res = VPX_CODEC_INVALID_PARAM;
  else {
    /* Set default/unknown values */
    si->w = 0;
    si->h = 0;

    res = iface->dec.peek_si(data, data_sz, si);
  }

  return res;
}


vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t         *ctx,
                                          vpx_codec_stream_info_t *si) {
  vpx_codec_err_t res;

  if (!ctx || !si || si->sz < sizeof(vpx_codec_stream_info_t))
    res = VPX_CODEC_INVALID_PARAM;
  else if (!ctx->iface || !ctx->priv)
    res = VPX_CODEC_ERROR;
  else {
    /* Set default/unknown values */
    si->w = 0;
    si->h = 0;

    res = ctx->iface->dec.get_si(ctx->priv->alg_priv, si);
  }

  return SAVE_STATUS(ctx, res);
}

static int read_frame_length(const uint8_t *data, uint64_t size,
                             uint64_t *frame_length, int *size_length) {
  uint64_t value = 0;
  *size_length = 0;
  do {
    uint64_t index;
    size -= value + *size_length;
    index = size - 1;
    value = 0;
    do {
      if (data + index < data) {
          *frame_length = -1;
          return -1;
      }
      value <<= 7;
      value |= (data[index] & 0x7F);
    } while (!(data[index--] >> 7));
    *size_length = size - 1 - index;
  } while (value + *size_length < size);
  *frame_length = value;
  return 0;
}


vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t    *ctx,
                                 const uint8_t        *data,
                                 unsigned int    data_sz,
                                 void       *user_priv,
                                 long        deadline) {
  vpx_codec_err_t res;
  int offset = 0;
  uint64_t length = 0;
  unsigned char altref_frame;
  unsigned int cx_size = data_sz;
  uint8_t *cx_data = data;

  /* Sanity checks */
  /* NULL data ptr allowed if data_sz is 0 too */
  if (!ctx || (!data && data_sz))
    res = VPX_CODEC_INVALID_PARAM;
  else if (!ctx->iface || !ctx->priv)
    res = VPX_CODEC_ERROR;
  else {
    do {
      altref_frame = !(*cx_data & 0x10);
      res = read_frame_length(cx_data, cx_size, &length, &offset);
      if (res != 0)
        return SAVE_STATUS(ctx, VPX_CODEC_UNSUP_BITSTREAM);
      res = ctx->iface->dec.decode(ctx->priv->alg_priv, cx_data,
                                         length, user_priv, deadline);
      if (res != 0)
        return SAVE_STATUS(ctx, res);
      cx_data += offset + length;
      cx_size -= offset + length;
    } while (cx_data - data <= data_sz && altref_frame);
  }

  return SAVE_STATUS(ctx, res);
}

vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t  *ctx,
                                 vpx_codec_iter_t *iter) {
  vpx_image_t *img;

  if (!ctx || !iter || !ctx->iface || !ctx->priv)
    img = NULL;
  else
    img = ctx->iface->dec.get_frame(ctx->priv->alg_priv, iter);

  return img;
}


vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t             *ctx,
                                                vpx_codec_put_frame_cb_fn_t  cb,
                                                void                      *user_priv) {
  vpx_codec_err_t res;

  if (!ctx || !cb)
    res = VPX_CODEC_INVALID_PARAM;
  else if (!ctx->iface || !ctx->priv
           || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME))
    res = VPX_CODEC_ERROR;
  else {
    ctx->priv->dec.put_frame_cb.u.put_frame = cb;
    ctx->priv->dec.put_frame_cb.user_priv = user_priv;
    res = VPX_CODEC_OK;
  }

  return SAVE_STATUS(ctx, res);
}


vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t             *ctx,
                                                vpx_codec_put_slice_cb_fn_t  cb,
                                                void                      *user_priv) {
  vpx_codec_err_t res;

  if (!ctx || !cb)
    res = VPX_CODEC_INVALID_PARAM;
  else if (!ctx->iface || !ctx->priv
           || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME))
    res = VPX_CODEC_ERROR;
  else {
    ctx->priv->dec.put_slice_cb.u.put_slice = cb;
    ctx->priv->dec.put_slice_cb.user_priv = user_priv;
    res = VPX_CODEC_OK;
  }

  return SAVE_STATUS(ctx, res);
}


vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t                *ctx,
                                      vpx_codec_mmap_t               *mmap,
                                      vpx_codec_iter_t               *iter) {
  vpx_codec_err_t res = VPX_CODEC_OK;

  if (!ctx || !mmap || !iter || !ctx->iface)
    res = VPX_CODEC_INVALID_PARAM;
  else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA))
    res = VPX_CODEC_ERROR;
  else
    res = ctx->iface->get_mmap(ctx, mmap, iter);

  return SAVE_STATUS(ctx, res);
}


vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t   *ctx,
                                      vpx_codec_mmap_t  *mmap,
                                      unsigned int     num_maps) {
  vpx_codec_err_t res = VPX_CODEC_MEM_ERROR;

  if (!ctx || !mmap || !ctx->iface)
    res = VPX_CODEC_INVALID_PARAM;
  else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA))
    res = VPX_CODEC_ERROR;
  else {
    unsigned int i;

    for (i = 0; i < num_maps; i++, mmap++) {
      if (!mmap->base)
        break;

      /* Everything look ok, set the mmap in the decoder */
      res = ctx->iface->set_mmap(ctx, mmap);

      if (res)
        break;
    }
  }

  return SAVE_STATUS(ctx, res);
}
