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