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 encoder algorithms.
14 : *
15 : */
16 : #include <limits.h>
17 : #include <string.h>
18 : #include "vpx/internal/vpx_codec_internal.h"
19 : #include "vpx_config.h"
20 :
21 : #define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
22 :
23 0 : vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t *ctx,
24 : vpx_codec_iface_t *iface,
25 : vpx_codec_enc_cfg_t *cfg,
26 : vpx_codec_flags_t flags,
27 : int ver)
28 : {
29 : vpx_codec_err_t res;
30 :
31 0 : if (ver != VPX_ENCODER_ABI_VERSION)
32 0 : res = VPX_CODEC_ABI_MISMATCH;
33 0 : else if (!ctx || !iface || !cfg)
34 0 : res = VPX_CODEC_INVALID_PARAM;
35 0 : else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION)
36 0 : res = VPX_CODEC_ABI_MISMATCH;
37 0 : else if (!(iface->caps & VPX_CODEC_CAP_ENCODER))
38 0 : res = VPX_CODEC_INCAPABLE;
39 0 : else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA))
40 0 : res = VPX_CODEC_INCAPABLE;
41 0 : else if ((flags & VPX_CODEC_USE_PSNR)
42 0 : && !(iface->caps & VPX_CODEC_CAP_PSNR))
43 0 : res = VPX_CODEC_INCAPABLE;
44 0 : else if ((flags & VPX_CODEC_USE_OUTPUT_PARTITION)
45 0 : && !(iface->caps & VPX_CODEC_CAP_OUTPUT_PARTITION))
46 0 : res = VPX_CODEC_INCAPABLE;
47 : else
48 : {
49 0 : ctx->iface = iface;
50 0 : ctx->name = iface->name;
51 0 : ctx->priv = NULL;
52 0 : ctx->init_flags = flags;
53 0 : ctx->config.enc = cfg;
54 0 : res = ctx->iface->init(ctx);
55 :
56 0 : if (res)
57 : {
58 0 : ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL;
59 0 : vpx_codec_destroy(ctx);
60 : }
61 :
62 0 : if (ctx->priv)
63 0 : ctx->priv->iface = ctx->iface;
64 : }
65 :
66 0 : return SAVE_STATUS(ctx, res);
67 : }
68 :
69 :
70 :
71 0 : vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface,
72 : vpx_codec_enc_cfg_t *cfg,
73 : unsigned int usage)
74 : {
75 : vpx_codec_err_t res;
76 : vpx_codec_enc_cfg_map_t *map;
77 :
78 0 : if (!iface || !cfg || usage > INT_MAX)
79 0 : res = VPX_CODEC_INVALID_PARAM;
80 0 : else if (!(iface->caps & VPX_CODEC_CAP_ENCODER))
81 0 : res = VPX_CODEC_INCAPABLE;
82 : else
83 : {
84 0 : res = VPX_CODEC_INVALID_PARAM;
85 :
86 0 : for (map = iface->enc.cfg_maps; map->usage >= 0; map++)
87 : {
88 0 : if (map->usage == (int)usage)
89 : {
90 0 : *cfg = map->cfg;
91 0 : cfg->g_usage = usage;
92 0 : res = VPX_CODEC_OK;
93 0 : break;
94 : }
95 : }
96 : }
97 :
98 0 : return res;
99 : }
100 :
101 :
102 : #if ARCH_X86 || ARCH_X86_64
103 : /* On X86, disable the x87 unit's internal 80 bit precision for better
104 : * consistency with the SSE unit's 64 bit precision.
105 : */
106 : #include "vpx_ports/x86.h"
107 : #define FLOATING_POINT_INIT() do {\
108 : unsigned short x87_orig_mode = x87_set_double_precision();
109 : #define FLOATING_POINT_RESTORE() \
110 : x87_set_control_word(x87_orig_mode); }while(0)
111 :
112 :
113 : #else
114 : static void FLOATING_POINT_INIT() {}
115 : static void FLOATING_POINT_RESTORE() {}
116 : #endif
117 :
118 :
119 0 : vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx,
120 : const vpx_image_t *img,
121 : vpx_codec_pts_t pts,
122 : unsigned long duration,
123 : vpx_enc_frame_flags_t flags,
124 : unsigned long deadline)
125 : {
126 : vpx_codec_err_t res;
127 :
128 0 : if (!ctx || (img && !duration))
129 0 : res = VPX_CODEC_INVALID_PARAM;
130 0 : else if (!ctx->iface || !ctx->priv)
131 0 : res = VPX_CODEC_ERROR;
132 0 : else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
133 0 : res = VPX_CODEC_INCAPABLE;
134 : else
135 : {
136 : /* Execute in a normalized floating point environment, if the platform
137 : * requires it.
138 : */
139 0 : FLOATING_POINT_INIT();
140 0 : res = ctx->iface->enc.encode(ctx->priv->alg_priv, img, pts,
141 : duration, flags, deadline);
142 0 : FLOATING_POINT_RESTORE();
143 : }
144 :
145 0 : return SAVE_STATUS(ctx, res);
146 : }
147 :
148 :
149 0 : const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx,
150 : vpx_codec_iter_t *iter)
151 : {
152 0 : const vpx_codec_cx_pkt_t *pkt = NULL;
153 :
154 0 : if (ctx)
155 : {
156 0 : if (!iter)
157 0 : ctx->err = VPX_CODEC_INVALID_PARAM;
158 0 : else if (!ctx->iface || !ctx->priv)
159 0 : ctx->err = VPX_CODEC_ERROR;
160 0 : else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
161 0 : ctx->err = VPX_CODEC_INCAPABLE;
162 : else
163 0 : pkt = ctx->iface->enc.get_cx_data(ctx->priv->alg_priv, iter);
164 : }
165 :
166 0 : if (pkt && pkt->kind == VPX_CODEC_CX_FRAME_PKT)
167 : {
168 : /* If the application has specified a destination area for the
169 : * compressed data, and the codec has not placed the data there,
170 : * and it fits, copy it.
171 : */
172 0 : char *dst_buf = ctx->priv->enc.cx_data_dst_buf.buf;
173 :
174 0 : if (dst_buf
175 0 : && pkt->data.raw.buf != dst_buf
176 0 : && pkt->data.raw.sz
177 0 : + ctx->priv->enc.cx_data_pad_before
178 0 : + ctx->priv->enc.cx_data_pad_after
179 0 : <= ctx->priv->enc.cx_data_dst_buf.sz)
180 : {
181 0 : vpx_codec_cx_pkt_t *modified_pkt = &ctx->priv->enc.cx_data_pkt;
182 :
183 0 : memcpy(dst_buf + ctx->priv->enc.cx_data_pad_before,
184 0 : pkt->data.raw.buf, pkt->data.raw.sz);
185 0 : *modified_pkt = *pkt;
186 0 : modified_pkt->data.raw.buf = dst_buf;
187 0 : modified_pkt->data.raw.sz += ctx->priv->enc.cx_data_pad_before
188 0 : + ctx->priv->enc.cx_data_pad_after;
189 0 : pkt = modified_pkt;
190 : }
191 :
192 0 : if (dst_buf == pkt->data.raw.buf)
193 : {
194 0 : ctx->priv->enc.cx_data_dst_buf.buf = dst_buf + pkt->data.raw.sz;
195 0 : ctx->priv->enc.cx_data_dst_buf.sz -= pkt->data.raw.sz;
196 : }
197 : }
198 :
199 0 : return pkt;
200 : }
201 :
202 :
203 0 : vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t *ctx,
204 : const vpx_fixed_buf_t *buf,
205 : unsigned int pad_before,
206 : unsigned int pad_after)
207 : {
208 0 : if (!ctx || !ctx->priv)
209 0 : return VPX_CODEC_INVALID_PARAM;
210 :
211 0 : if (buf)
212 : {
213 0 : ctx->priv->enc.cx_data_dst_buf = *buf;
214 0 : ctx->priv->enc.cx_data_pad_before = pad_before;
215 0 : ctx->priv->enc.cx_data_pad_after = pad_after;
216 : }
217 : else
218 : {
219 0 : ctx->priv->enc.cx_data_dst_buf.buf = NULL;
220 0 : ctx->priv->enc.cx_data_dst_buf.sz = 0;
221 0 : ctx->priv->enc.cx_data_pad_before = 0;
222 0 : ctx->priv->enc.cx_data_pad_after = 0;
223 : }
224 :
225 0 : return VPX_CODEC_OK;
226 : }
227 :
228 :
229 0 : const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t *ctx)
230 : {
231 0 : vpx_image_t *img = NULL;
232 :
233 0 : if (ctx)
234 : {
235 0 : if (!ctx->iface || !ctx->priv)
236 0 : ctx->err = VPX_CODEC_ERROR;
237 0 : else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
238 0 : ctx->err = VPX_CODEC_INCAPABLE;
239 0 : else if (!ctx->iface->enc.get_preview)
240 0 : ctx->err = VPX_CODEC_INCAPABLE;
241 : else
242 0 : img = ctx->iface->enc.get_preview(ctx->priv->alg_priv);
243 : }
244 :
245 0 : return img;
246 : }
247 :
248 :
249 0 : vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t *ctx)
250 : {
251 0 : vpx_fixed_buf_t *buf = NULL;
252 :
253 0 : if (ctx)
254 : {
255 0 : if (!ctx->iface || !ctx->priv)
256 0 : ctx->err = VPX_CODEC_ERROR;
257 0 : else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
258 0 : ctx->err = VPX_CODEC_INCAPABLE;
259 0 : else if (!ctx->iface->enc.get_glob_hdrs)
260 0 : ctx->err = VPX_CODEC_INCAPABLE;
261 : else
262 0 : buf = ctx->iface->enc.get_glob_hdrs(ctx->priv->alg_priv);
263 : }
264 :
265 0 : return buf;
266 : }
267 :
268 :
269 0 : vpx_codec_err_t vpx_codec_enc_config_set(vpx_codec_ctx_t *ctx,
270 : const vpx_codec_enc_cfg_t *cfg)
271 : {
272 : vpx_codec_err_t res;
273 :
274 0 : if (!ctx || !ctx->iface || !ctx->priv || !cfg)
275 0 : res = VPX_CODEC_INVALID_PARAM;
276 0 : else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
277 0 : res = VPX_CODEC_INCAPABLE;
278 : else
279 0 : res = ctx->iface->enc.cfg_set(ctx->priv->alg_priv, cfg);
280 :
281 0 : return SAVE_STATUS(ctx, res);
282 : }
283 :
284 :
285 0 : int vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *list,
286 : const struct vpx_codec_cx_pkt *pkt)
287 : {
288 0 : if (list->cnt < list->max)
289 : {
290 0 : list->pkts[list->cnt++] = *pkt;
291 0 : return 0;
292 : }
293 :
294 0 : return 1;
295 : }
296 :
297 :
298 0 : const vpx_codec_cx_pkt_t *vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list,
299 : vpx_codec_iter_t *iter)
300 : {
301 : const vpx_codec_cx_pkt_t *pkt;
302 :
303 0 : if (!(*iter))
304 : {
305 0 : *iter = list->pkts;
306 : }
307 :
308 0 : pkt = (const void *) * iter;
309 :
310 0 : if ((size_t)(pkt - list->pkts) < list->cnt)
311 0 : *iter = pkt + 1;
312 : else
313 0 : pkt = NULL;
314 :
315 0 : return pkt;
316 : }
|