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 
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)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_POSTPROC) && !(iface->caps & VPX_CODEC_CAP_POSTPROC))
35     res = VPX_CODEC_INCAPABLE;
36   else if ((flags & VPX_CODEC_USE_ERROR_CONCEALMENT) &&
37            !(iface->caps & VPX_CODEC_CAP_ERROR_CONCEALMENT))
38     res = VPX_CODEC_INCAPABLE;
39   else if ((flags & VPX_CODEC_USE_INPUT_FRAGMENTS) &&
40            !(iface->caps & VPX_CODEC_CAP_INPUT_FRAGMENTS))
41     res = VPX_CODEC_INCAPABLE;
42   else if (!(iface->caps & VPX_CODEC_CAP_DECODER))
43     res = VPX_CODEC_INCAPABLE;
44   else {
45     memset(ctx, 0, sizeof(*ctx));
46     ctx->iface = iface;
47     ctx->name = iface->name;
48     ctx->priv = NULL;
49     ctx->init_flags = flags;
50     ctx->config.dec = cfg;
51 
52     res = ctx->iface->init(ctx, NULL);
53     if (res) {
54       ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL;
55       vpx_codec_destroy(ctx);
56     }
57 
58     if (ctx->priv)
59       ctx->priv->iface = ctx->iface;
60   }
61 
62   return SAVE_STATUS(ctx, res);
63 }
64 
65 
vpx_codec_peek_stream_info(vpx_codec_iface_t * iface,const uint8_t * data,unsigned int data_sz,vpx_codec_stream_info_t * si)66 vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t       *iface,
67                                            const uint8_t         *data,
68                                            unsigned int           data_sz,
69                                            vpx_codec_stream_info_t *si) {
70   vpx_codec_err_t res;
71 
72   if (!iface || !data || !data_sz || !si
73       || si->sz < sizeof(vpx_codec_stream_info_t))
74     res = VPX_CODEC_INVALID_PARAM;
75   else {
76     /* Set default/unknown values */
77     si->w = 0;
78     si->h = 0;
79 
80     res = iface->dec.peek_si(data, data_sz, si);
81   }
82 
83   return res;
84 }
85 
86 
vpx_codec_get_stream_info(vpx_codec_ctx_t * ctx,vpx_codec_stream_info_t * si)87 vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t         *ctx,
88                                           vpx_codec_stream_info_t *si) {
89   vpx_codec_err_t res;
90 
91   if (!ctx || !si || si->sz < sizeof(vpx_codec_stream_info_t))
92     res = VPX_CODEC_INVALID_PARAM;
93   else if (!ctx->iface || !ctx->priv)
94     res = VPX_CODEC_ERROR;
95   else {
96     /* Set default/unknown values */
97     si->w = 0;
98     si->h = 0;
99 
100     res = ctx->iface->dec.get_si(ctx->priv->alg_priv, si);
101   }
102 
103   return SAVE_STATUS(ctx, res);
104 }
105 
106 
vpx_codec_decode(vpx_codec_ctx_t * ctx,const uint8_t * data,unsigned int data_sz,void * user_priv,long deadline)107 vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t    *ctx,
108                                  const uint8_t        *data,
109                                  unsigned int    data_sz,
110                                  void       *user_priv,
111                                  long        deadline) {
112   vpx_codec_err_t res;
113 
114   /* Sanity checks */
115   /* NULL data ptr allowed if data_sz is 0 too */
116   if (!ctx || (!data && data_sz) || (data && !data_sz))
117     res = VPX_CODEC_INVALID_PARAM;
118   else if (!ctx->iface || !ctx->priv)
119     res = VPX_CODEC_ERROR;
120   else {
121     res = ctx->iface->dec.decode(ctx->priv->alg_priv, data, data_sz,
122                                  user_priv, deadline);
123   }
124 
125   return SAVE_STATUS(ctx, res);
126 }
127 
vpx_codec_get_frame(vpx_codec_ctx_t * ctx,vpx_codec_iter_t * iter)128 vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t  *ctx,
129                                  vpx_codec_iter_t *iter) {
130   vpx_image_t *img;
131 
132   if (!ctx || !iter || !ctx->iface || !ctx->priv)
133     img = NULL;
134   else
135     img = ctx->iface->dec.get_frame(ctx->priv->alg_priv, iter);
136 
137   return img;
138 }
139 
140 
vpx_codec_register_put_frame_cb(vpx_codec_ctx_t * ctx,vpx_codec_put_frame_cb_fn_t cb,void * user_priv)141 vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t             *ctx,
142                                                 vpx_codec_put_frame_cb_fn_t  cb,
143                                                 void                      *user_priv) {
144   vpx_codec_err_t res;
145 
146   if (!ctx || !cb)
147     res = VPX_CODEC_INVALID_PARAM;
148   else if (!ctx->iface || !ctx->priv
149            || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME))
150     res = VPX_CODEC_ERROR;
151   else {
152     ctx->priv->dec.put_frame_cb.u.put_frame = cb;
153     ctx->priv->dec.put_frame_cb.user_priv = user_priv;
154     res = VPX_CODEC_OK;
155   }
156 
157   return SAVE_STATUS(ctx, res);
158 }
159 
160 
vpx_codec_register_put_slice_cb(vpx_codec_ctx_t * ctx,vpx_codec_put_slice_cb_fn_t cb,void * user_priv)161 vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t             *ctx,
162                                                 vpx_codec_put_slice_cb_fn_t  cb,
163                                                 void                      *user_priv) {
164   vpx_codec_err_t res;
165 
166   if (!ctx || !cb)
167     res = VPX_CODEC_INVALID_PARAM;
168   else if (!ctx->iface || !ctx->priv
169            || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_SLICE))
170     res = VPX_CODEC_ERROR;
171   else {
172     ctx->priv->dec.put_slice_cb.u.put_slice = cb;
173     ctx->priv->dec.put_slice_cb.user_priv = user_priv;
174     res = VPX_CODEC_OK;
175   }
176 
177   return SAVE_STATUS(ctx, res);
178 }
179 
vpx_codec_set_frame_buffer_functions(vpx_codec_ctx_t * ctx,vpx_get_frame_buffer_cb_fn_t cb_get,vpx_release_frame_buffer_cb_fn_t cb_release,void * cb_priv)180 vpx_codec_err_t vpx_codec_set_frame_buffer_functions(
181     vpx_codec_ctx_t *ctx, vpx_get_frame_buffer_cb_fn_t cb_get,
182     vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) {
183   vpx_codec_err_t res;
184 
185   if (!ctx || !cb_get || !cb_release) {
186     res = VPX_CODEC_INVALID_PARAM;
187   } else if (!ctx->iface || !ctx->priv ||
188              !(ctx->iface->caps & VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER)) {
189     res = VPX_CODEC_ERROR;
190   } else {
191     res = ctx->iface->dec.set_fb_fn(ctx->priv->alg_priv, cb_get, cb_release,
192                                     cb_priv);
193   }
194 
195   return SAVE_STATUS(ctx, res);
196 }
197