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 <stdarg.h>
17 #include <stdlib.h>
18 #include "vpx/vpx_integer.h"
19 #include "vpx/internal/vpx_codec_internal.h"
20 #include "vpx_version.h"
21 
22 #define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
23 
vpx_codec_version(void)24 int vpx_codec_version(void) {
25   return VERSION_PACKED;
26 }
27 
28 
vpx_codec_version_str(void)29 const char *vpx_codec_version_str(void) {
30   return VERSION_STRING_NOSP;
31 }
32 
33 
vpx_codec_version_extra_str(void)34 const char *vpx_codec_version_extra_str(void) {
35   return VERSION_EXTRA;
36 }
37 
38 
vpx_codec_iface_name(vpx_codec_iface_t * iface)39 const char *vpx_codec_iface_name(vpx_codec_iface_t *iface) {
40   return iface ? iface->name : "<invalid interface>";
41 }
42 
vpx_codec_err_to_string(vpx_codec_err_t err)43 const char *vpx_codec_err_to_string(vpx_codec_err_t  err) {
44   switch (err) {
45     case VPX_CODEC_OK:
46       return "Success";
47     case VPX_CODEC_ERROR:
48       return "Unspecified internal error";
49     case VPX_CODEC_MEM_ERROR:
50       return "Memory allocation error";
51     case VPX_CODEC_ABI_MISMATCH:
52       return "ABI version mismatch";
53     case VPX_CODEC_INCAPABLE:
54       return "Codec does not implement requested capability";
55     case VPX_CODEC_UNSUP_BITSTREAM:
56       return "Bitstream not supported by this decoder";
57     case VPX_CODEC_UNSUP_FEATURE:
58       return "Bitstream required feature not supported by this decoder";
59     case VPX_CODEC_CORRUPT_FRAME:
60       return "Corrupt frame detected";
61     case  VPX_CODEC_INVALID_PARAM:
62       return "Invalid parameter";
63     case VPX_CODEC_LIST_END:
64       return "End of iterated list";
65   }
66 
67   return "Unrecognized error code";
68 }
69 
vpx_codec_error(vpx_codec_ctx_t * ctx)70 const char *vpx_codec_error(vpx_codec_ctx_t  *ctx) {
71   return (ctx) ? vpx_codec_err_to_string(ctx->err)
72          : vpx_codec_err_to_string(VPX_CODEC_INVALID_PARAM);
73 }
74 
vpx_codec_error_detail(vpx_codec_ctx_t * ctx)75 const char *vpx_codec_error_detail(vpx_codec_ctx_t  *ctx) {
76   if (ctx && ctx->err)
77     return ctx->priv ? ctx->priv->err_detail : ctx->err_detail;
78 
79   return NULL;
80 }
81 
82 
vpx_codec_destroy(vpx_codec_ctx_t * ctx)83 vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx) {
84   vpx_codec_err_t res;
85 
86   if (!ctx)
87     res = VPX_CODEC_INVALID_PARAM;
88   else if (!ctx->iface || !ctx->priv)
89     res = VPX_CODEC_ERROR;
90   else {
91     if (ctx->priv->alg_priv)
92       ctx->iface->destroy(ctx->priv->alg_priv);
93 
94     ctx->iface = NULL;
95     ctx->name = NULL;
96     ctx->priv = NULL;
97     res = VPX_CODEC_OK;
98   }
99 
100   return SAVE_STATUS(ctx, res);
101 }
102 
103 
vpx_codec_get_caps(vpx_codec_iface_t * iface)104 vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface) {
105   return (iface) ? iface->caps : 0;
106 }
107 
108 
vpx_codec_control_(vpx_codec_ctx_t * ctx,int ctrl_id,...)109 vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t  *ctx,
110                                    int               ctrl_id,
111                                    ...) {
112   vpx_codec_err_t res;
113 
114   if (!ctx || !ctrl_id)
115     res = VPX_CODEC_INVALID_PARAM;
116   else if (!ctx->iface || !ctx->priv || !ctx->iface->ctrl_maps)
117     res = VPX_CODEC_ERROR;
118   else {
119     vpx_codec_ctrl_fn_map_t *entry;
120 
121     res = VPX_CODEC_ERROR;
122 
123     for (entry = ctx->iface->ctrl_maps; entry && entry->fn; entry++) {
124       if (!entry->ctrl_id || entry->ctrl_id == ctrl_id) {
125         va_list  ap;
126 
127         va_start(ap, ctrl_id);
128         res = entry->fn(ctx->priv->alg_priv, ctrl_id, ap);
129         va_end(ap);
130         break;
131       }
132     }
133   }
134 
135   return SAVE_STATUS(ctx, res);
136 }
137 
138 //------------------------------------------------------------------------------
139 // mmap interface
140 
vpx_mmap_alloc(vpx_codec_mmap_t * mmap)141 vpx_codec_err_t vpx_mmap_alloc(vpx_codec_mmap_t *mmap) {
142   unsigned int align = mmap->align ? mmap->align - 1 : 0;
143 
144   if (mmap->flags & VPX_CODEC_MEM_ZERO)
145     mmap->priv = calloc(1, mmap->sz + align);
146   else
147     mmap->priv = malloc(mmap->sz + align);
148 
149   if (mmap->priv == NULL) return VPX_CODEC_MEM_ERROR;
150   mmap->base = (void *)((((uintptr_t)mmap->priv) + align) & ~(uintptr_t)align);
151   mmap->dtor = vpx_mmap_dtor;
152   return VPX_CODEC_OK;
153 }
154 
vpx_mmap_dtor(vpx_codec_mmap_t * mmap)155 void vpx_mmap_dtor(vpx_codec_mmap_t *mmap) {
156   free(mmap->priv);
157 }
158 
vpx_validate_mmaps(const vpx_codec_stream_info_t * si,const vpx_codec_mmap_t * mmaps,const mem_req_t * mem_reqs,int nreqs,vpx_codec_flags_t init_flags)159 vpx_codec_err_t vpx_validate_mmaps(const vpx_codec_stream_info_t *si,
160                                    const vpx_codec_mmap_t *mmaps,
161                                    const mem_req_t *mem_reqs, int nreqs,
162                                    vpx_codec_flags_t init_flags) {
163   int i;
164 
165   for (i = 0; i < nreqs - 1; ++i) {
166     /* Ensure the segment has been allocated */
167     if (mmaps[i].base == NULL) {
168       return VPX_CODEC_MEM_ERROR;
169     }
170 
171     /* Verify variable size segment is big enough for the current si. */
172     if (mem_reqs[i].calc_sz != NULL) {
173       vpx_codec_dec_cfg_t cfg;
174 
175       cfg.w = si->w;
176       cfg.h = si->h;
177 
178       if (mmaps[i].sz < mem_reqs[i].calc_sz(&cfg, init_flags)) {
179         return VPX_CODEC_MEM_ERROR;
180       }
181     }
182   }
183   return VPX_CODEC_OK;
184 }
185