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 { 27 vpx_codec_err_t res; 28 29 if (ver != VPX_DECODER_ABI_VERSION) 30 res = VPX_CODEC_ABI_MISMATCH; 31 else if (!ctx || !iface) 32 res = VPX_CODEC_INVALID_PARAM; 33 else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION) 34 res = VPX_CODEC_ABI_MISMATCH; 35 else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA)) 36 res = VPX_CODEC_INCAPABLE; 37 else if ((flags & VPX_CODEC_USE_POSTPROC) && !(iface->caps & VPX_CODEC_CAP_POSTPROC)) 38 res = VPX_CODEC_INCAPABLE; 39 else if (!(iface->caps & VPX_CODEC_CAP_DECODER)) 40 res = VPX_CODEC_INCAPABLE; 41 else 42 { 43 memset(ctx, 0, sizeof(*ctx)); 44 ctx->iface = iface; 45 ctx->name = iface->name; 46 ctx->priv = NULL; 47 ctx->init_flags = flags; 48 ctx->config.dec = cfg; 49 res = VPX_CODEC_OK; 50 51 if (!(flags & VPX_CODEC_USE_XMA)) 52 { 53 res = ctx->iface->init(ctx); 54 55 if (res) 56 { 57 ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL; 58 vpx_codec_destroy(ctx); 59 } 60 61 if (ctx->priv) 62 ctx->priv->iface = ctx->iface; 63 } 64 } 65 66 return SAVE_STATUS(ctx, res); 67 } 68 69 70 vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface, 71 const uint8_t *data, 72 unsigned int data_sz, 73 vpx_codec_stream_info_t *si) 74 { 75 vpx_codec_err_t res; 76 77 if (!iface || !data || !data_sz || !si 78 || si->sz < sizeof(vpx_codec_stream_info_t)) 79 res = VPX_CODEC_INVALID_PARAM; 80 else 81 { 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 { 96 vpx_codec_err_t res; 97 98 if (!ctx || !si || si->sz < sizeof(vpx_codec_stream_info_t)) 99 res = VPX_CODEC_INVALID_PARAM; 100 else if (!ctx->iface || !ctx->priv) 101 res = VPX_CODEC_ERROR; 102 else 103 { 104 /* Set default/unknown values */ 105 si->w = 0; 106 si->h = 0; 107 108 res = ctx->iface->dec.get_si(ctx->priv->alg_priv, si); 109 } 110 111 return SAVE_STATUS(ctx, res); 112 } 113 114 115 vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx, 116 const uint8_t *data, 117 unsigned int data_sz, 118 void *user_priv, 119 long deadline) 120 { 121 vpx_codec_err_t res; 122 123 /* Sanity checks */ 124 /* NULL data ptr allowed if data_sz is 0 too */ 125 if (!ctx || (!data && data_sz)) 126 res = VPX_CODEC_INVALID_PARAM; 127 else if (!ctx->iface || !ctx->priv) 128 res = VPX_CODEC_ERROR; 129 else 130 { 131 res = ctx->iface->dec.decode(ctx->priv->alg_priv, data, data_sz, 132 user_priv, deadline); 133 } 134 135 return SAVE_STATUS(ctx, res); 136 } 137 138 vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx, 139 vpx_codec_iter_t *iter) 140 { 141 vpx_image_t *img; 142 143 if (!ctx || !iter || !ctx->iface || !ctx->priv) 144 img = NULL; 145 else 146 img = ctx->iface->dec.get_frame(ctx->priv->alg_priv, iter); 147 148 return img; 149 } 150 151 152 vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx, 153 vpx_codec_put_frame_cb_fn_t cb, 154 void *user_priv) 155 { 156 vpx_codec_err_t res; 157 158 if (!ctx || !cb) 159 res = VPX_CODEC_INVALID_PARAM; 160 else if (!ctx->iface || !ctx->priv 161 || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME)) 162 res = VPX_CODEC_ERROR; 163 else 164 { 165 ctx->priv->dec.put_frame_cb.u.put_frame = cb; 166 ctx->priv->dec.put_frame_cb.user_priv = user_priv; 167 res = VPX_CODEC_OK; 168 } 169 170 return SAVE_STATUS(ctx, res); 171 } 172 173 174 vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx, 175 vpx_codec_put_slice_cb_fn_t cb, 176 void *user_priv) 177 { 178 vpx_codec_err_t res; 179 180 if (!ctx || !cb) 181 res = VPX_CODEC_INVALID_PARAM; 182 else if (!ctx->iface || !ctx->priv 183 || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME)) 184 res = VPX_CODEC_ERROR; 185 else 186 { 187 ctx->priv->dec.put_slice_cb.u.put_slice = cb; 188 ctx->priv->dec.put_slice_cb.user_priv = user_priv; 189 res = VPX_CODEC_OK; 190 } 191 192 return SAVE_STATUS(ctx, res); 193 } 194 195 196 vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t *ctx, 197 vpx_codec_mmap_t *mmap, 198 vpx_codec_iter_t *iter) 199 { 200 vpx_codec_err_t res = VPX_CODEC_OK; 201 202 if (!ctx || !mmap || !iter || !ctx->iface) 203 res = VPX_CODEC_INVALID_PARAM; 204 else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA)) 205 res = VPX_CODEC_ERROR; 206 else 207 res = ctx->iface->get_mmap(ctx, mmap, iter); 208 209 return SAVE_STATUS(ctx, res); 210 } 211 212 213 vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t *ctx, 214 vpx_codec_mmap_t *mmap, 215 unsigned int num_maps) 216 { 217 vpx_codec_err_t res = VPX_CODEC_MEM_ERROR; 218 219 if (!ctx || !mmap || !ctx->iface) 220 res = VPX_CODEC_INVALID_PARAM; 221 else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA)) 222 res = VPX_CODEC_ERROR; 223 else 224 { 225 unsigned int i; 226 227 for (i = 0; i < num_maps; i++, mmap++) 228 { 229 if (!mmap->base) 230 break; 231 232 /* Everything look ok, set the mmap in the decoder */ 233 res = ctx->iface->set_mmap(ctx, mmap); 234 235 if (res) 236 break; 237 } 238 } 239 240 return SAVE_STATUS(ctx, res); 241 } 242