|
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 |
|
24 int vpx_codec_version(void) { |
|
25 return VERSION_PACKED; |
|
26 } |
|
27 |
|
28 |
|
29 const char *vpx_codec_version_str(void) { |
|
30 return VERSION_STRING_NOSP; |
|
31 } |
|
32 |
|
33 |
|
34 const char *vpx_codec_version_extra_str(void) { |
|
35 return VERSION_EXTRA; |
|
36 } |
|
37 |
|
38 |
|
39 const char *vpx_codec_iface_name(vpx_codec_iface_t *iface) { |
|
40 return iface ? iface->name : "<invalid interface>"; |
|
41 } |
|
42 |
|
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 |
|
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 |
|
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 |
|
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 |
|
104 vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface) { |
|
105 return (iface) ? iface->caps : 0; |
|
106 } |
|
107 |
|
108 |
|
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 |
|
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 |
|
155 void vpx_mmap_dtor(vpx_codec_mmap_t *mmap) { |
|
156 free(mmap->priv); |
|
157 } |
|
158 |
|
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 } |