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 vpx_decoder.c 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 40 { 41 memset(ctx, 0, sizeof(*ctx)); 42 ctx->iface = iface; 43 ctx->name = iface->name; 44 ctx->priv = NULL; 45 ctx->init_flags = flags; 46 ctx->config.dec = cfg; 47 res = VPX_CODEC_OK; 48 49 if (!(flags & VPX_CODEC_USE_XMA)) 50 { 51 res = ctx->iface->init(ctx); 52 53 if (res) 54 { 55 ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL; 56 vpx_codec_destroy(ctx); 57 } 58 59 if (ctx->priv) 60 ctx->priv->iface = ctx->iface; 61 } 62 } 63 64 return SAVE_STATUS(ctx, res); 65 } 66 67 68 vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface, 69 const uint8_t *data, 70 unsigned int data_sz, 71 vpx_codec_stream_info_t *si) 72 { 73 vpx_codec_err_t res; 74 75 if (!iface || !data || !data_sz || !si 76 || si->sz < sizeof(vpx_codec_stream_info_t)) 77 res = VPX_CODEC_INVALID_PARAM; 78 else 79 { 80 /* Set default/unknown values */ 81 si->w = 0; 82 si->h = 0; 83 84 res = iface->dec.peek_si(data, data_sz, si); 85 } 86 87 return res; 88 } 89 90 91 vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t *ctx, 92 vpx_codec_stream_info_t *si) 93 { 94 vpx_codec_err_t res; 95 96 if (!ctx || !si || si->sz < sizeof(vpx_codec_stream_info_t)) 97 res = VPX_CODEC_INVALID_PARAM; 98 else if (!ctx->iface || !ctx->priv) 99 res = VPX_CODEC_ERROR; 100 else 101 { 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 { 119 vpx_codec_err_t res; 120 121 if (!ctx || !data || !data_sz) 122 res = VPX_CODEC_INVALID_PARAM; 123 else if (!ctx->iface || !ctx->priv) 124 res = VPX_CODEC_ERROR; 125 else 126 { 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 { 137 vpx_image_t *img; 138 139 if (!ctx || !iter || !ctx->iface || !ctx->priv) 140 img = NULL; 141 else 142 img = ctx->iface->dec.get_frame(ctx->priv->alg_priv, iter); 143 144 return img; 145 } 146 147 148 vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx, 149 vpx_codec_put_frame_cb_fn_t cb, 150 void *user_priv) 151 { 152 vpx_codec_err_t res; 153 154 if (!ctx || !cb) 155 res = VPX_CODEC_INVALID_PARAM; 156 else if (!ctx->iface || !ctx->priv 157 || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME)) 158 res = VPX_CODEC_ERROR; 159 else 160 { 161 ctx->priv->dec.put_frame_cb.put_frame = cb; 162 ctx->priv->dec.put_frame_cb.user_priv = user_priv; 163 res = VPX_CODEC_OK; 164 } 165 166 return SAVE_STATUS(ctx, res); 167 } 168 169 170 vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx, 171 vpx_codec_put_slice_cb_fn_t cb, 172 void *user_priv) 173 { 174 vpx_codec_err_t res; 175 176 if (!ctx || !cb) 177 res = VPX_CODEC_INVALID_PARAM; 178 else if (!ctx->iface || !ctx->priv 179 || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME)) 180 res = VPX_CODEC_ERROR; 181 else 182 { 183 ctx->priv->dec.put_slice_cb.put_slice = cb; 184 ctx->priv->dec.put_slice_cb.user_priv = user_priv; 185 res = VPX_CODEC_OK; 186 } 187 188 return SAVE_STATUS(ctx, res); 189 } 190 191 192 vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t *ctx, 193 vpx_codec_mmap_t *mmap, 194 vpx_codec_iter_t *iter) 195 { 196 vpx_codec_err_t res = VPX_CODEC_OK; 197 198 if (!ctx || !mmap || !iter || !ctx->iface) 199 res = VPX_CODEC_INVALID_PARAM; 200 else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA)) 201 res = VPX_CODEC_ERROR; 202 else 203 res = ctx->iface->get_mmap(ctx, mmap, iter); 204 205 return SAVE_STATUS(ctx, res); 206 } 207 208 209 vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t *ctx, 210 vpx_codec_mmap_t *mmap, 211 unsigned int num_maps) 212 { 213 vpx_codec_err_t res = VPX_CODEC_MEM_ERROR; 214 215 if (!ctx || !mmap || !ctx->iface) 216 res = VPX_CODEC_INVALID_PARAM; 217 else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA)) 218 res = VPX_CODEC_ERROR; 219 else 220 { 221 unsigned int i; 222 223 for (i = 0; i < num_maps; i++, mmap++) 224 { 225 if (!mmap->base) 226 break; 227 228 /* Everything look ok, set the mmap in the decoder */ 229 res = ctx->iface->set_mmap(ctx, mmap); 230 231 if (res) 232 break; 233 } 234 } 235 236 return SAVE_STATUS(ctx, res); 237 } 238