2 * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license and patent
5 * grant that can be found in the LICENSE file in the root of the source
6 * tree. All contributing project authors may be found in the AUTHORS
7 * file in the root of the source tree.
11 /*!\file vpx_encoder.c
12 * \brief Provides the high level interface to wrap encoder algorithms.
17 #include "vpx/internal/vpx_codec_internal.h"
19 #define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var)
21 vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t *ctx,
22 vpx_codec_iface_t *iface,
23 vpx_codec_enc_cfg_t *cfg,
24 vpx_codec_flags_t flags,
29 if (ver != VPX_ENCODER_ABI_VERSION)
30 res = VPX_CODEC_ABI_MISMATCH;
31 else if (!ctx || !iface || !cfg)
32 res = VPX_CODEC_INVALID_PARAM;
33 else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION)
34 res = VPX_CODEC_ABI_MISMATCH;
35 else if (!(iface->caps & VPX_CODEC_CAP_ENCODER))
36 res = VPX_CODEC_INCAPABLE;
37 else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA))
38 res = VPX_CODEC_INCAPABLE;
39 else if ((flags & VPX_CODEC_USE_PSNR)
40 && !(iface->caps & VPX_CODEC_CAP_PSNR))
41 res = VPX_CODEC_INCAPABLE;
45 ctx->name = iface->name;
47 ctx->init_flags = flags;
48 ctx->config.enc = cfg;
49 res = ctx->iface->init(ctx);
53 ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL;
54 vpx_codec_destroy(ctx);
58 ctx->priv->iface = ctx->iface;
61 return SAVE_STATUS(ctx, res);
66 vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface,
67 vpx_codec_enc_cfg_t *cfg,
71 vpx_codec_enc_cfg_map_t *map;
73 if (!iface || !cfg || usage > INT_MAX)
74 res = VPX_CODEC_INVALID_PARAM;
75 else if (!(iface->caps & VPX_CODEC_CAP_ENCODER))
76 res = VPX_CODEC_INCAPABLE;
79 res = VPX_CODEC_INVALID_PARAM;
81 for (map = iface->enc.cfg_maps; map->usage >= 0; map++)
83 if (map->usage == (int)usage)
97 #if ARCH_X86 || ARCH_X86_64
98 /* On X86, disable the x87 unit's internal 80 bit precision for better
99 * consistency with the SSE unit's 64 bit precision.
101 #include "vpx_ports/x86.h"
102 #define FLOATING_POINT_INIT() do {\
103 unsigned short x87_orig_mode = x87_set_double_precision();
104 #define FLOATING_POINT_RESTORE() \
105 x87_set_control_word(x87_orig_mode); }while(0)
109 static void FLOATING_POINT_INIT() {}
110 static void FLOATING_POINT_RESTORE() {}
114 vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx,
115 const vpx_image_t *img,
117 unsigned long duration,
118 vpx_enc_frame_flags_t flags,
119 unsigned long deadline)
123 if (!ctx || (img && !duration))
124 res = VPX_CODEC_INVALID_PARAM;
125 else if (!ctx->iface || !ctx->priv)
126 res = VPX_CODEC_ERROR;
127 else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
128 res = VPX_CODEC_INCAPABLE;
130 #if CONFIG_EVAL_LIMIT
131 else if (ctx->priv->eval_counter >= 500)
133 ctx->priv->err_detail = "Evaluation limit exceeded.";
134 res = VPX_CODEC_ERROR;
140 /* Execute in a normalized floating point environment, if the platform
143 FLOATING_POINT_INIT();
144 res = ctx->iface->enc.encode(ctx->priv->alg_priv, img, pts,
145 duration, flags, deadline);
146 FLOATING_POINT_RESTORE();
148 #if CONFIG_EVAL_LIMIT
149 ctx->priv->eval_counter++;
153 return SAVE_STATUS(ctx, res);
157 const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx,
158 vpx_codec_iter_t *iter)
160 const vpx_codec_cx_pkt_t *pkt = NULL;
165 ctx->err = VPX_CODEC_INVALID_PARAM;
166 else if (!ctx->iface || !ctx->priv)
167 ctx->err = VPX_CODEC_ERROR;
168 else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
169 ctx->err = VPX_CODEC_INCAPABLE;
171 pkt = ctx->iface->enc.get_cx_data(ctx->priv->alg_priv, iter);
174 if (pkt && pkt->kind == VPX_CODEC_CX_FRAME_PKT)
176 /* If the application has specified a destination area for the
177 * compressed data, and the codec has not placed the data there,
178 * and it fits, copy it.
180 char *dst_buf = ctx->priv->enc.cx_data_dst_buf.buf;
183 && pkt->data.raw.buf != dst_buf
185 + ctx->priv->enc.cx_data_pad_before
186 + ctx->priv->enc.cx_data_pad_after
187 <= ctx->priv->enc.cx_data_dst_buf.sz)
189 vpx_codec_cx_pkt_t *modified_pkt = &ctx->priv->enc.cx_data_pkt;
191 memcpy(dst_buf + ctx->priv->enc.cx_data_pad_before,
192 pkt->data.raw.buf, pkt->data.raw.sz);
193 *modified_pkt = *pkt;
194 modified_pkt->data.raw.buf = dst_buf;
195 modified_pkt->data.raw.sz += ctx->priv->enc.cx_data_pad_before
196 + ctx->priv->enc.cx_data_pad_after;
200 if (dst_buf == pkt->data.raw.buf)
202 ctx->priv->enc.cx_data_dst_buf.buf = dst_buf + pkt->data.raw.sz;
203 ctx->priv->enc.cx_data_dst_buf.sz -= pkt->data.raw.sz;
211 vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t *ctx,
212 const vpx_fixed_buf_t *buf,
213 unsigned int pad_before,
214 unsigned int pad_after)
216 if (!ctx || !ctx->priv)
217 return VPX_CODEC_INVALID_PARAM;
221 ctx->priv->enc.cx_data_dst_buf = *buf;
222 ctx->priv->enc.cx_data_pad_before = pad_before;
223 ctx->priv->enc.cx_data_pad_after = pad_after;
227 ctx->priv->enc.cx_data_dst_buf.buf = NULL;
228 ctx->priv->enc.cx_data_dst_buf.sz = 0;
229 ctx->priv->enc.cx_data_pad_before = 0;
230 ctx->priv->enc.cx_data_pad_after = 0;
237 const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t *ctx)
239 vpx_image_t *img = NULL;
243 if (!ctx->iface || !ctx->priv)
244 ctx->err = VPX_CODEC_ERROR;
245 else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
246 ctx->err = VPX_CODEC_INCAPABLE;
247 else if (!ctx->iface->enc.get_preview)
248 ctx->err = VPX_CODEC_INCAPABLE;
250 img = ctx->iface->enc.get_preview(ctx->priv->alg_priv);
257 vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t *ctx)
259 vpx_fixed_buf_t *buf = NULL;
263 if (!ctx->iface || !ctx->priv)
264 ctx->err = VPX_CODEC_ERROR;
265 else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
266 ctx->err = VPX_CODEC_INCAPABLE;
267 else if (!ctx->iface->enc.get_glob_hdrs)
268 ctx->err = VPX_CODEC_INCAPABLE;
270 buf = ctx->iface->enc.get_glob_hdrs(ctx->priv->alg_priv);
277 vpx_codec_err_t vpx_codec_enc_config_set(vpx_codec_ctx_t *ctx,
278 const vpx_codec_enc_cfg_t *cfg)
282 if (!ctx || !ctx->iface || !ctx->priv || !cfg)
283 res = VPX_CODEC_INVALID_PARAM;
284 else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER))
285 res = VPX_CODEC_INCAPABLE;
287 res = ctx->iface->enc.cfg_set(ctx->priv->alg_priv, cfg);
289 return SAVE_STATUS(ctx, res);
293 int vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *list,
294 const struct vpx_codec_cx_pkt *pkt)
296 if (list->cnt < list->max)
298 list->pkts[list->cnt++] = *pkt;
306 const vpx_codec_cx_pkt_t *vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list,
307 vpx_codec_iter_t *iter)
309 const vpx_codec_cx_pkt_t *pkt;
316 pkt = (const void *) * iter;
318 if (pkt - list->pkts < list->cnt)