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