1 /* 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 12 /*!\file 13 * \brief Provides the high level interface to wrap decoder algorithms. 14 * 15 */ 16 #include <string.h> 17 #include "vpx/internal/vpx_codec_internal.h" 18 19 #define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var) 20 21 vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t *ctx, 22 vpx_codec_iface_t *iface, 23 vpx_codec_dec_cfg_t *cfg, 24 vpx_codec_flags_t flags, 25 int ver) { 26 vpx_codec_err_t res; 27 28 if (ver != VPX_DECODER_ABI_VERSION) 29 res = VPX_CODEC_ABI_MISMATCH; 30 else if (!ctx || !iface) 31 res = VPX_CODEC_INVALID_PARAM; 32 else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION) 33 res = VPX_CODEC_ABI_MISMATCH; 34 else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA)) 35 res = VPX_CODEC_INCAPABLE; 36 else if ((flags & VPX_CODEC_USE_POSTPROC) && !(iface->caps & VPX_CODEC_CAP_POSTPROC)) 37 res = VPX_CODEC_INCAPABLE; 38 else if ((flags & VPX_CODEC_USE_ERROR_CONCEALMENT) && 39 !(iface->caps & VPX_CODEC_CAP_ERROR_CONCEALMENT)) 40 res = VPX_CODEC_INCAPABLE; 41 else if ((flags & VPX_CODEC_USE_INPUT_FRAGMENTS) && 42 !(iface->caps & VPX_CODEC_CAP_INPUT_FRAGMENTS)) 43 res = VPX_CODEC_INCAPABLE; 44 else if (!(iface->caps & VPX_CODEC_CAP_DECODER)) 45 res = VPX_CODEC_INCAPABLE; 46 else { 47 memset(ctx, 0, sizeof(*ctx)); 48 ctx->iface = iface; 49 ctx->name = iface->name; 50 ctx->priv = NULL; 51 ctx->init_flags = flags; 52 ctx->config.dec = cfg; 53 res = VPX_CODEC_OK; 54 55 if (!(flags & VPX_CODEC_USE_XMA)) { 56 res = ctx->iface->init(ctx, NULL); 57 58 if (res) { 59 ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL; 60 vpx_codec_destroy(ctx); 61 } 62 63 if (ctx->priv) 64 ctx->priv->iface = ctx->iface; 65 } 66 } 67 68 return SAVE_STATUS(ctx, res); 69 } 70 71 72 vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface, 73 const uint8_t *data, 74 unsigned int data_sz, 75 vpx_codec_stream_info_t *si) { 76 vpx_codec_err_t res; 77 78 if (!iface || !data || !data_sz || !si 79 || si->sz < sizeof(vpx_codec_stream_info_t)) 80 res = VPX_CODEC_INVALID_PARAM; 81 else { 82 /* Set default/unknown values */ 83 si->w = 0; 84 si->h = 0; 85 86 res = iface->dec.peek_si(data, data_sz, si); 87 } 88 89 return res; 90 } 91 92 93 vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t *ctx, 94 vpx_codec_stream_info_t *si) { 95 vpx_codec_err_t res; 96 97 if (!ctx || !si || si->sz < sizeof(vpx_codec_stream_info_t)) 98 res = VPX_CODEC_INVALID_PARAM; 99 else if (!ctx->iface || !ctx->priv) 100 res = VPX_CODEC_ERROR; 101 else { 102 /* Set default/unknown values */ 103 si->w = 0; 104 si->h = 0; 105 106 res = ctx->iface->dec.get_si(ctx->priv->alg_priv, si); 107 } 108 109 return SAVE_STATUS(ctx, res); 110 } 111 112 113 vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx, 114 const uint8_t *data, 115 unsigned int data_sz, 116 void *user_priv, 117 long deadline) { 118 vpx_codec_err_t res; 119 120 /* Sanity checks */ 121 /* NULL data ptr allowed if data_sz is 0 too */ 122 if (!ctx || (!data && data_sz)) 123 res = VPX_CODEC_INVALID_PARAM; 124 else if (!ctx->iface || !ctx->priv) 125 res = VPX_CODEC_ERROR; 126 else { 127 res = ctx->iface->dec.decode(ctx->priv->alg_priv, data, data_sz, 128 user_priv, deadline); 129 } 130 131 return SAVE_STATUS(ctx, res); 132 } 133 134 vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx, 135 vpx_codec_iter_t *iter) { 136 vpx_image_t *img; 137 138 if (!ctx || !iter || !ctx->iface || !ctx->priv) 139 img = NULL; 140 else 141 img = ctx->iface->dec.get_frame(ctx->priv->alg_priv, iter); 142 143 return img; 144 } 145 146 147 vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx, 148 vpx_codec_put_frame_cb_fn_t cb, 149 void *user_priv) { 150 vpx_codec_err_t res; 151 152 if (!ctx || !cb) 153 res = VPX_CODEC_INVALID_PARAM; 154 else if (!ctx->iface || !ctx->priv 155 || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME)) 156 res = VPX_CODEC_ERROR; 157 else { 158 ctx->priv->dec.put_frame_cb.u.put_frame = cb; 159 ctx->priv->dec.put_frame_cb.user_priv = user_priv; 160 res = VPX_CODEC_OK; 161 } 162 163 return SAVE_STATUS(ctx, res); 164 } 165 166 167 vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx, 168 vpx_codec_put_slice_cb_fn_t cb, 169 void *user_priv) { 170 vpx_codec_err_t res; 171 172 if (!ctx || !cb) 173 res = VPX_CODEC_INVALID_PARAM; 174 else if (!ctx->iface || !ctx->priv 175 || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME)) 176 res = VPX_CODEC_ERROR; 177 else { 178 ctx->priv->dec.put_slice_cb.u.put_slice = cb; 179 ctx->priv->dec.put_slice_cb.user_priv = user_priv; 180 res = VPX_CODEC_OK; 181 } 182 183 return SAVE_STATUS(ctx, res); 184 } 185 186 187 vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t *ctx, 188 vpx_codec_mmap_t *mmap, 189 vpx_codec_iter_t *iter) { 190 vpx_codec_err_t res = VPX_CODEC_OK; 191 192 if (!ctx || !mmap || !iter || !ctx->iface) 193 res = VPX_CODEC_INVALID_PARAM; 194 else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA)) 195 res = VPX_CODEC_ERROR; 196 else 197 res = ctx->iface->get_mmap(ctx, mmap, iter); 198 199 return SAVE_STATUS(ctx, res); 200 } 201 202 203 vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t *ctx, 204 vpx_codec_mmap_t *mmap, 205 unsigned int num_maps) { 206 vpx_codec_err_t res = VPX_CODEC_MEM_ERROR; 207 208 if (!ctx || !mmap || !ctx->iface) 209 res = VPX_CODEC_INVALID_PARAM; 210 else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA)) 211 res = VPX_CODEC_ERROR; 212 else { 213 unsigned int i; 214 215 for (i = 0; i < num_maps; i++, mmap++) { 216 if (!mmap->base) 217 break; 218 219 /* Everything look ok, set the mmap in the decoder */ 220 res = ctx->iface->set_mmap(ctx, mmap); 221 222 if (res) 223 break; 224 } 225 } 226 227 return SAVE_STATUS(ctx, res); 228 } 229