diff options
author | John Koleszar <jkoleszar@google.com> | 2010-05-24 11:39:59 -0400 |
---|---|---|
committer | John Koleszar <jkoleszar@google.com> | 2010-05-24 20:27:42 -0400 |
commit | b7492341ac224b9dda9e618f6a9e9ab37e8afa66 (patch) | |
tree | 5f9d0e4429be663f3d9274bbba4eaeb4b4cbe159 /vpx/src | |
parent | ee8bcb1a7dcecc4dd393129237f234cbb619bab4 (diff) | |
download | libvpx-b7492341ac224b9dda9e618f6a9e9ab37e8afa66.tar libvpx-b7492341ac224b9dda9e618f6a9e9ab37e8afa66.tar.gz libvpx-b7492341ac224b9dda9e618f6a9e9ab37e8afa66.tar.bz2 libvpx-b7492341ac224b9dda9e618f6a9e9ab37e8afa66.zip |
install includes in DIST_DIR/include/vpx, move vpx_codec/ to vpx/
This renames the vpx_codec/ directory to vpx/, to allow applications
to more consistently reference these includes with the vpx/ prefix.
This allows the includes to be installed in /usr/local/include/vpx
rather than polluting the system includes directory with an
excessive number of includes.
Change-Id: I7b0652a20543d93f38f421c60b0bbccde4d61b4f
Diffstat (limited to 'vpx/src')
-rw-r--r-- | vpx/src/vpx_codec.c | 197 | ||||
-rw-r--r-- | vpx/src/vpx_decoder.c | 201 | ||||
-rw-r--r-- | vpx/src/vpx_decoder_compat.c | 200 | ||||
-rw-r--r-- | vpx/src/vpx_encoder.c | 324 | ||||
-rw-r--r-- | vpx/src/vpx_image.c | 261 |
5 files changed, 1183 insertions, 0 deletions
diff --git a/vpx/src/vpx_codec.c b/vpx/src/vpx_codec.c new file mode 100644 index 000000000..45dfce0aa --- /dev/null +++ b/vpx/src/vpx_codec.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2010 The VP8 project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license and patent + * grant that can be found in the LICENSE file in the root of the source + * tree. All contributing project authors may be found in the AUTHORS + * file in the root of the source tree. + */ + + +/*!\file vpx_decoder.c + * \brief Provides the high level interface to wrap decoder algorithms. + * + */ +#include <stdlib.h> +#include <string.h> +#include "vpx/vpx_integer.h" +#include "vpx/internal/vpx_codec_internal.h" +#include "vpx_version.h" + +#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var) + +int vpx_codec_version(void) +{ + return VERSION_PACKED; +} + + +const char *vpx_codec_version_str(void) +{ + return VERSION_STRING_NOSP; +} + + +const char *vpx_codec_version_extra_str(void) +{ + return VERSION_EXTRA; +} + + +const char *vpx_codec_iface_name(vpx_codec_iface_t *iface) +{ + return iface ? iface->name : "<invalid interface>"; +} + +const char *vpx_codec_err_to_string(vpx_codec_err_t err) +{ + switch (err) + { + case VPX_CODEC_OK: + return "Success"; + case VPX_CODEC_ERROR: + return "Unspecified internal error"; + case VPX_CODEC_MEM_ERROR: + return "Memory allocation error"; + case VPX_CODEC_ABI_MISMATCH: + return "ABI version mismatch"; + case VPX_CODEC_INCAPABLE: + return "Codec does not implement requested capability"; + case VPX_CODEC_UNSUP_BITSTREAM: + return "Bitstream not supported by this decoder"; + case VPX_CODEC_UNSUP_FEATURE: + return "Bitstream required feature not supported by this decoder"; + case VPX_CODEC_CORRUPT_FRAME: + return "Corrupt frame detected"; + case VPX_CODEC_INVALID_PARAM: + return "Invalid parameter"; + case VPX_CODEC_LIST_END: + return "End of iterated list"; + } + + return "Unrecognized error code"; +} + +const char *vpx_codec_error(vpx_codec_ctx_t *ctx) +{ + return (ctx) ? vpx_codec_err_to_string(ctx->err) + : vpx_codec_err_to_string(VPX_CODEC_INVALID_PARAM); +} + +const char *vpx_codec_error_detail(vpx_codec_ctx_t *ctx) +{ + if (ctx && ctx->err) + return ctx->priv ? ctx->priv->err_detail : ctx->err_detail; + + return NULL; +} + + +vpx_codec_err_t vpx_codec_dec_init_ver(vpx_codec_ctx_t *ctx, + vpx_codec_iface_t *iface, + vpx_codec_dec_cfg_t *cfg, + vpx_codec_flags_t flags, + int ver) +{ + vpx_codec_err_t res; + + if (ver != VPX_DECODER_ABI_VERSION) + res = VPX_CODEC_ABI_MISMATCH; + else if (!ctx || !iface) + res = VPX_CODEC_INVALID_PARAM; + else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION) + res = VPX_CODEC_ABI_MISMATCH; + else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA)) + res = VPX_CODEC_INCAPABLE; + else if ((flags & VPX_CODEC_USE_POSTPROC) && !(iface->caps & VPX_CODEC_CAP_POSTPROC)) + res = VPX_CODEC_INCAPABLE; + else + { + memset(ctx, 0, sizeof(*ctx)); + ctx->iface = iface; + ctx->name = iface->name; + ctx->priv = NULL; + ctx->init_flags = flags; + ctx->config.dec = cfg; + res = VPX_CODEC_OK; + + if (!(flags & VPX_CODEC_USE_XMA)) + { + res = ctx->iface->init(ctx); + + if (res) + { + ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL; + vpx_codec_destroy(ctx); + } + + if (ctx->priv) + ctx->priv->iface = ctx->iface; + } + } + + return SAVE_STATUS(ctx, res); +} + + +vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx) +{ + vpx_codec_err_t res; + + if (!ctx) + res = VPX_CODEC_INVALID_PARAM; + else if (!ctx->iface || !ctx->priv) + res = VPX_CODEC_ERROR; + else + { + if (ctx->priv->alg_priv) + ctx->iface->destroy(ctx->priv->alg_priv); + + ctx->iface = NULL; + ctx->name = NULL; + ctx->priv = NULL; + res = VPX_CODEC_OK; + } + + return SAVE_STATUS(ctx, res); +} + + +vpx_codec_caps_t vpx_codec_get_caps(vpx_codec_iface_t *iface) +{ + return (iface) ? iface->caps : 0; +} + + +vpx_codec_err_t vpx_codec_control_(vpx_codec_ctx_t *ctx, + int ctrl_id, + ...) +{ + vpx_codec_err_t res; + + if (!ctx || !ctrl_id) + res = VPX_CODEC_INVALID_PARAM; + else if (!ctx->iface || !ctx->priv || !ctx->iface->ctrl_maps) + res = VPX_CODEC_ERROR; + else + { + vpx_codec_ctrl_fn_map_t *entry; + + res = VPX_CODEC_ERROR; + + for (entry = ctx->iface->ctrl_maps; entry && entry->fn; entry++) + { + if (!entry->ctrl_id || entry->ctrl_id == ctrl_id) + { + va_list ap; + + va_start(ap, ctrl_id); + res = entry->fn(ctx->priv->alg_priv, ctrl_id, ap); + va_end(ap); + break; + } + } + } + + return SAVE_STATUS(ctx, res); +} diff --git a/vpx/src/vpx_decoder.c b/vpx/src/vpx_decoder.c new file mode 100644 index 000000000..8257f89b2 --- /dev/null +++ b/vpx/src/vpx_decoder.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2010 The VP8 project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license and patent + * grant that can be found in the LICENSE file in the root of the source + * tree. All contributing project authors may be found in the AUTHORS + * file in the root of the source tree. + */ + + +/*!\file vpx_decoder.c + * \brief Provides the high level interface to wrap decoder algorithms. + * + */ +#include <stdlib.h> +#include "vpx/internal/vpx_codec_internal.h" + +#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var) + +vpx_codec_err_t vpx_codec_peek_stream_info(vpx_codec_iface_t *iface, + const uint8_t *data, + unsigned int data_sz, + vpx_codec_stream_info_t *si) +{ + vpx_codec_err_t res; + + if (!iface || !data || !data_sz || !si + || si->sz < sizeof(vpx_codec_stream_info_t)) + res = VPX_CODEC_INVALID_PARAM; + else + { + /* Set default/unknown values */ + si->w = 0; + si->h = 0; + + res = iface->dec.peek_si(data, data_sz, si); + } + + return res; +} + + +vpx_codec_err_t vpx_codec_get_stream_info(vpx_codec_ctx_t *ctx, + vpx_codec_stream_info_t *si) +{ + vpx_codec_err_t res; + + if (!ctx || !si || si->sz < sizeof(vpx_codec_stream_info_t)) + res = VPX_CODEC_INVALID_PARAM; + else if (!ctx->iface || !ctx->priv) + res = VPX_CODEC_ERROR; + else + { + /* Set default/unknown values */ + si->w = 0; + si->h = 0; + + res = ctx->iface->dec.get_si(ctx->priv->alg_priv, si); + } + + return SAVE_STATUS(ctx, res); +} + + +vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx, + const uint8_t *data, + unsigned int data_sz, + void *user_priv, + long deadline) +{ + vpx_codec_err_t res; + + if (!ctx || !data || !data_sz) + res = VPX_CODEC_INVALID_PARAM; + else if (!ctx->iface || !ctx->priv) + res = VPX_CODEC_ERROR; + +#if CONFIG_EVAL_LIMIT + else if (ctx->priv->eval_counter >= 500) + { + ctx->priv->err_detail = "Evaluation limit exceeded."; + res = VPX_CODEC_ERROR; + } + +#endif + else + { + res = ctx->iface->dec.decode(ctx->priv->alg_priv, data, data_sz, + user_priv, deadline); +#if CONFIG_EVAL_LIMIT + ctx->priv->eval_counter++; +#endif + } + + return SAVE_STATUS(ctx, res); +} + +vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx, + vpx_codec_iter_t *iter) +{ + vpx_image_t *img; + + if (!ctx || !iter || !ctx->iface || !ctx->priv) + img = NULL; + else + img = ctx->iface->dec.get_frame(ctx->priv->alg_priv, iter); + + return img; +} + + +vpx_codec_err_t vpx_codec_register_put_frame_cb(vpx_codec_ctx_t *ctx, + vpx_codec_put_frame_cb_fn_t cb, + void *user_priv) +{ + vpx_codec_err_t res; + + if (!ctx || !cb) + res = VPX_CODEC_INVALID_PARAM; + else if (!ctx->iface || !ctx->priv + || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME)) + res = VPX_CODEC_ERROR; + else + { + ctx->priv->dec.put_frame_cb.put_frame = cb; + ctx->priv->dec.put_frame_cb.user_priv = user_priv; + res = VPX_CODEC_OK; + } + + return SAVE_STATUS(ctx, res); +} + + +vpx_codec_err_t vpx_codec_register_put_slice_cb(vpx_codec_ctx_t *ctx, + vpx_codec_put_slice_cb_fn_t cb, + void *user_priv) +{ + vpx_codec_err_t res; + + if (!ctx || !cb) + res = VPX_CODEC_INVALID_PARAM; + else if (!ctx->iface || !ctx->priv + || !(ctx->iface->caps & VPX_CODEC_CAP_PUT_FRAME)) + res = VPX_CODEC_ERROR; + else + { + ctx->priv->dec.put_slice_cb.put_slice = cb; + ctx->priv->dec.put_slice_cb.user_priv = user_priv; + res = VPX_CODEC_OK; + } + + return SAVE_STATUS(ctx, res); +} + + +vpx_codec_err_t vpx_codec_get_mem_map(vpx_codec_ctx_t *ctx, + vpx_codec_mmap_t *mmap, + vpx_codec_iter_t *iter) +{ + vpx_codec_err_t res = VPX_CODEC_OK; + + if (!ctx || !mmap || !iter || !ctx->iface) + res = VPX_CODEC_INVALID_PARAM; + else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA)) + res = VPX_CODEC_ERROR; + else + res = ctx->iface->get_mmap(ctx, mmap, iter); + + return SAVE_STATUS(ctx, res); +} + + +vpx_codec_err_t vpx_codec_set_mem_map(vpx_codec_ctx_t *ctx, + vpx_codec_mmap_t *mmap, + unsigned int num_maps) +{ + vpx_codec_err_t res = VPX_CODEC_MEM_ERROR; + + if (!ctx || !mmap || !ctx->iface) + res = VPX_CODEC_INVALID_PARAM; + else if (!(ctx->iface->caps & VPX_CODEC_CAP_XMA)) + res = VPX_CODEC_ERROR; + else + { + unsigned int i; + + for (i = 0; i < num_maps; i++, mmap++) + { + if (!mmap->base) + break; + + /* Everything look ok, set the mmap in the decoder */ + res = ctx->iface->set_mmap(ctx, mmap); + + if (res) + break; + } + } + + return SAVE_STATUS(ctx, res); +} diff --git a/vpx/src/vpx_decoder_compat.c b/vpx/src/vpx_decoder_compat.c new file mode 100644 index 000000000..96594fe2f --- /dev/null +++ b/vpx/src/vpx_decoder_compat.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2010 The VP8 project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license and patent + * grant that can be found in the LICENSE file in the root of the source + * tree. All contributing project authors may be found in the AUTHORS + * file in the root of the source tree. + */ + + +/*!\file vpx_decoder.c + * \brief Provides the high level interface to wrap decoder algorithms. + * + */ +#include <stdlib.h> +#include <string.h> +#include "vpx/vpx_decoder.h" +#include "vpx/internal/vpx_codec_internal.h" + +#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var) + +const char *vpx_dec_iface_name(vpx_dec_iface_t *iface) +{ + return vpx_codec_iface_name((vpx_codec_iface_t *)iface); +} + +const char *vpx_dec_err_to_string(vpx_dec_err_t err) +{ + return vpx_codec_err_to_string(err); +} + +const char *vpx_dec_error(vpx_dec_ctx_t *ctx) +{ + return vpx_codec_error((vpx_codec_ctx_t *)ctx); +} + +const char *vpx_dec_error_detail(vpx_dec_ctx_t *ctx) +{ + return vpx_codec_error_detail((vpx_codec_ctx_t *)ctx); +} + + +vpx_dec_err_t vpx_dec_init_ver(vpx_dec_ctx_t *ctx, + vpx_dec_iface_t *iface, + int ver) +{ + return vpx_codec_dec_init_ver((vpx_codec_ctx_t *)ctx, + (vpx_codec_iface_t *)iface, + NULL, + 0, + ver); +} + + +vpx_dec_err_t vpx_dec_destroy(vpx_dec_ctx_t *ctx) +{ + return vpx_codec_destroy((vpx_codec_ctx_t *)ctx); +} + + +vpx_dec_caps_t vpx_dec_get_caps(vpx_dec_iface_t *iface) +{ + return vpx_codec_get_caps((vpx_codec_iface_t *)iface); +} + + +vpx_dec_err_t vpx_dec_peek_stream_info(vpx_dec_iface_t *iface, + const uint8_t *data, + unsigned int data_sz, + vpx_dec_stream_info_t *si) +{ + return vpx_codec_peek_stream_info((vpx_codec_iface_t *)iface, data, data_sz, + (vpx_codec_stream_info_t *)si); +} + + +vpx_dec_err_t vpx_dec_get_stream_info(vpx_dec_ctx_t *ctx, + vpx_dec_stream_info_t *si) +{ + return vpx_codec_get_stream_info((vpx_codec_ctx_t *)ctx, + (vpx_codec_stream_info_t *)si); +} + + +vpx_dec_err_t vpx_dec_control(vpx_dec_ctx_t *ctx, + int ctrl_id, + void *data) +{ + return vpx_codec_control_((vpx_codec_ctx_t *)ctx, ctrl_id, data); +} + + +vpx_dec_err_t vpx_dec_decode(vpx_dec_ctx_t *ctx, + uint8_t *data, + unsigned int data_sz, + void *user_priv, + int rel_pts) +{ + (void)rel_pts; + return vpx_codec_decode((vpx_codec_ctx_t *)ctx, data, data_sz, user_priv, + 0); +} + +vpx_image_t *vpx_dec_get_frame(vpx_dec_ctx_t *ctx, + vpx_dec_iter_t *iter) +{ + return vpx_codec_get_frame((vpx_codec_ctx_t *)ctx, iter); +} + + +vpx_dec_err_t vpx_dec_register_put_frame_cb(vpx_dec_ctx_t *ctx, + vpx_dec_put_frame_cb_fn_t cb, + void *user_priv) +{ + return vpx_codec_register_put_frame_cb((vpx_codec_ctx_t *)ctx, cb, + user_priv); +} + + +vpx_dec_err_t vpx_dec_register_put_slice_cb(vpx_dec_ctx_t *ctx, + vpx_dec_put_slice_cb_fn_t cb, + void *user_priv) +{ + return vpx_codec_register_put_slice_cb((vpx_codec_ctx_t *)ctx, cb, + user_priv); +} + + +vpx_dec_err_t vpx_dec_xma_init_ver(vpx_dec_ctx_t *ctx, + vpx_dec_iface_t *iface, + int ver) +{ + return vpx_codec_dec_init_ver((vpx_codec_ctx_t *)ctx, + (vpx_codec_iface_t *)iface, + NULL, + VPX_CODEC_USE_XMA, + ver); +} + +vpx_dec_err_t vpx_dec_get_mem_map(vpx_dec_ctx_t *ctx_, + vpx_dec_mmap_t *mmap, + const vpx_dec_stream_info_t *si, + vpx_dec_iter_t *iter) +{ + vpx_codec_ctx_t *ctx = (vpx_codec_ctx_t *)ctx_; + vpx_dec_err_t res = VPX_DEC_OK; + + if (!ctx || !mmap || !si || !iter || !ctx->iface) + res = VPX_DEC_INVALID_PARAM; + else if (!(ctx->iface->caps & VPX_DEC_CAP_XMA)) + res = VPX_DEC_ERROR; + else + { + if (!ctx->config.dec) + { + ctx->config.dec = malloc(sizeof(vpx_codec_dec_cfg_t)); + ctx->config.dec->w = si->w; + ctx->config.dec->h = si->h; + } + + res = ctx->iface->get_mmap(ctx, mmap, iter); + } + + return SAVE_STATUS(ctx, res); +} + + +vpx_dec_err_t vpx_dec_set_mem_map(vpx_dec_ctx_t *ctx_, + vpx_dec_mmap_t *mmap, + unsigned int num_maps) +{ + vpx_codec_ctx_t *ctx = (vpx_codec_ctx_t *)ctx_; + vpx_dec_err_t res = VPX_DEC_MEM_ERROR; + + if (!ctx || !mmap || !ctx->iface) + res = VPX_DEC_INVALID_PARAM; + else if (!(ctx->iface->caps & VPX_DEC_CAP_XMA)) + res = VPX_DEC_ERROR; + else + { + void *save = (ctx->priv) ? NULL : ctx->config.dec; + unsigned int i; + + for (i = 0; i < num_maps; i++, mmap++) + { + if (!mmap->base) + break; + + /* Everything look ok, set the mmap in the decoder */ + res = ctx->iface->set_mmap(ctx, mmap); + + if (res) + break; + } + + if (save) free(save); + } + + return SAVE_STATUS(ctx, res); +} diff --git a/vpx/src/vpx_encoder.c b/vpx/src/vpx_encoder.c new file mode 100644 index 000000000..a9a40de71 --- /dev/null +++ b/vpx/src/vpx_encoder.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2010 The VP8 project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license and patent + * grant that can be found in the LICENSE file in the root of the source + * tree. All contributing project authors may be found in the AUTHORS + * file in the root of the source tree. + */ + + +/*!\file vpx_encoder.c + * \brief Provides the high level interface to wrap encoder algorithms. + * + */ +#include <limits.h> +#include <string.h> +#include "vpx/internal/vpx_codec_internal.h" + +#define SAVE_STATUS(ctx,var) (ctx?(ctx->err = var):var) + +vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t *ctx, + vpx_codec_iface_t *iface, + vpx_codec_enc_cfg_t *cfg, + vpx_codec_flags_t flags, + int ver) +{ + vpx_codec_err_t res; + + if (ver != VPX_ENCODER_ABI_VERSION) + res = VPX_CODEC_ABI_MISMATCH; + else if (!ctx || !iface || !cfg) + res = VPX_CODEC_INVALID_PARAM; + else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION) + res = VPX_CODEC_ABI_MISMATCH; + else if (!(iface->caps & VPX_CODEC_CAP_ENCODER)) + res = VPX_CODEC_INCAPABLE; + else if ((flags & VPX_CODEC_USE_XMA) && !(iface->caps & VPX_CODEC_CAP_XMA)) + res = VPX_CODEC_INCAPABLE; + else if ((flags & VPX_CODEC_USE_PSNR) + && !(iface->caps & VPX_CODEC_CAP_PSNR)) + res = VPX_CODEC_INCAPABLE; + else + { + ctx->iface = iface; + ctx->name = iface->name; + ctx->priv = NULL; + ctx->init_flags = flags; + ctx->config.enc = cfg; + res = ctx->iface->init(ctx); + + if (res) + { + ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL; + vpx_codec_destroy(ctx); + } + + if (ctx->priv) + ctx->priv->iface = ctx->iface; + } + + return SAVE_STATUS(ctx, res); +} + + + +vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface, + vpx_codec_enc_cfg_t *cfg, + unsigned int usage) +{ + vpx_codec_err_t res; + vpx_codec_enc_cfg_map_t *map; + + if (!iface || !cfg || usage > INT_MAX) + res = VPX_CODEC_INVALID_PARAM; + else if (!(iface->caps & VPX_CODEC_CAP_ENCODER)) + res = VPX_CODEC_INCAPABLE; + else + { + res = VPX_CODEC_INVALID_PARAM; + + for (map = iface->enc.cfg_maps; map->usage >= 0; map++) + { + if (map->usage == (int)usage) + { + *cfg = map->cfg; + cfg->g_usage = usage; + res = VPX_CODEC_OK; + break; + } + } + } + + return res; +} + + +#if ARCH_X86 || ARCH_X86_64 +/* On X86, disable the x87 unit's internal 80 bit precision for better + * consistency with the SSE unit's 64 bit precision. + */ +#include "vpx_ports/x86.h" +#define FLOATING_POINT_INIT() do {\ + unsigned short x87_orig_mode = x87_set_double_precision(); +#define FLOATING_POINT_RESTORE() \ + x87_set_control_word(x87_orig_mode); }while(0) + + +#else +static void FLOATING_POINT_INIT() {} +static void FLOATING_POINT_RESTORE() {} +#endif + + +vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx, + const vpx_image_t *img, + vpx_codec_pts_t pts, + unsigned long duration, + vpx_enc_frame_flags_t flags, + unsigned long deadline) +{ + vpx_codec_err_t res; + + if (!ctx || (img && !duration)) + res = VPX_CODEC_INVALID_PARAM; + else if (!ctx->iface || !ctx->priv) + res = VPX_CODEC_ERROR; + else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER)) + res = VPX_CODEC_INCAPABLE; + +#if CONFIG_EVAL_LIMIT + else if (ctx->priv->eval_counter >= 500) + { + ctx->priv->err_detail = "Evaluation limit exceeded."; + res = VPX_CODEC_ERROR; + } + +#endif + else + { + /* Execute in a normalized floating point environment, if the platform + * requires it. + */ + FLOATING_POINT_INIT(); + res = ctx->iface->enc.encode(ctx->priv->alg_priv, img, pts, + duration, flags, deadline); + FLOATING_POINT_RESTORE(); + +#if CONFIG_EVAL_LIMIT + ctx->priv->eval_counter++; +#endif + } + + return SAVE_STATUS(ctx, res); +} + + +const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx, + vpx_codec_iter_t *iter) +{ + const vpx_codec_cx_pkt_t *pkt = NULL; + + if (ctx) + { + if (!iter) + ctx->err = VPX_CODEC_INVALID_PARAM; + else if (!ctx->iface || !ctx->priv) + ctx->err = VPX_CODEC_ERROR; + else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER)) + ctx->err = VPX_CODEC_INCAPABLE; + else + pkt = ctx->iface->enc.get_cx_data(ctx->priv->alg_priv, iter); + } + + if (pkt && pkt->kind == VPX_CODEC_CX_FRAME_PKT) + { + /* If the application has specified a destination area for the + * compressed data, and the codec has not placed the data there, + * and it fits, copy it. + */ + char *dst_buf = ctx->priv->enc.cx_data_dst_buf.buf; + + if (dst_buf + && pkt->data.raw.buf != dst_buf + && pkt->data.raw.sz + + ctx->priv->enc.cx_data_pad_before + + ctx->priv->enc.cx_data_pad_after + <= ctx->priv->enc.cx_data_dst_buf.sz) + { + vpx_codec_cx_pkt_t *modified_pkt = &ctx->priv->enc.cx_data_pkt; + + memcpy(dst_buf + ctx->priv->enc.cx_data_pad_before, + pkt->data.raw.buf, pkt->data.raw.sz); + *modified_pkt = *pkt; + modified_pkt->data.raw.buf = dst_buf; + modified_pkt->data.raw.sz += ctx->priv->enc.cx_data_pad_before + + ctx->priv->enc.cx_data_pad_after; + pkt = modified_pkt; + } + + if (dst_buf == pkt->data.raw.buf) + { + ctx->priv->enc.cx_data_dst_buf.buf = dst_buf + pkt->data.raw.sz; + ctx->priv->enc.cx_data_dst_buf.sz -= pkt->data.raw.sz; + } + } + + return pkt; +} + + +vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t *ctx, + const vpx_fixed_buf_t *buf, + unsigned int pad_before, + unsigned int pad_after) +{ + if (!ctx || !ctx->priv) + return VPX_CODEC_INVALID_PARAM; + + if (buf) + { + ctx->priv->enc.cx_data_dst_buf = *buf; + ctx->priv->enc.cx_data_pad_before = pad_before; + ctx->priv->enc.cx_data_pad_after = pad_after; + } + else + { + ctx->priv->enc.cx_data_dst_buf.buf = NULL; + ctx->priv->enc.cx_data_dst_buf.sz = 0; + ctx->priv->enc.cx_data_pad_before = 0; + ctx->priv->enc.cx_data_pad_after = 0; + } + + return VPX_CODEC_OK; +} + + +const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t *ctx) +{ + vpx_image_t *img = NULL; + + if (ctx) + { + if (!ctx->iface || !ctx->priv) + ctx->err = VPX_CODEC_ERROR; + else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER)) + ctx->err = VPX_CODEC_INCAPABLE; + else if (!ctx->iface->enc.get_preview) + ctx->err = VPX_CODEC_INCAPABLE; + else + img = ctx->iface->enc.get_preview(ctx->priv->alg_priv); + } + + return img; +} + + +vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t *ctx) +{ + vpx_fixed_buf_t *buf = NULL; + + if (ctx) + { + if (!ctx->iface || !ctx->priv) + ctx->err = VPX_CODEC_ERROR; + else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER)) + ctx->err = VPX_CODEC_INCAPABLE; + else if (!ctx->iface->enc.get_glob_hdrs) + ctx->err = VPX_CODEC_INCAPABLE; + else + buf = ctx->iface->enc.get_glob_hdrs(ctx->priv->alg_priv); + } + + return buf; +} + + +vpx_codec_err_t vpx_codec_enc_config_set(vpx_codec_ctx_t *ctx, + const vpx_codec_enc_cfg_t *cfg) +{ + vpx_codec_err_t res; + + if (!ctx || !ctx->iface || !ctx->priv || !cfg) + res = VPX_CODEC_INVALID_PARAM; + else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER)) + res = VPX_CODEC_INCAPABLE; + else + res = ctx->iface->enc.cfg_set(ctx->priv->alg_priv, cfg); + + return SAVE_STATUS(ctx, res); +} + + +int vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *list, + const struct vpx_codec_cx_pkt *pkt) +{ + if (list->cnt < list->max) + { + list->pkts[list->cnt++] = *pkt; + return 0; + } + + return 1; +} + + +const vpx_codec_cx_pkt_t *vpx_codec_pkt_list_get(struct vpx_codec_pkt_list *list, + vpx_codec_iter_t *iter) +{ + const vpx_codec_cx_pkt_t *pkt; + + if (!(*iter)) + { + *iter = list->pkts; + } + + pkt = (const void *) * iter; + + if (pkt - list->pkts < list->cnt) + *iter = pkt + 1; + else + pkt = NULL; + + return pkt; +} diff --git a/vpx/src/vpx_image.c b/vpx/src/vpx_image.c new file mode 100644 index 000000000..881ab1a31 --- /dev/null +++ b/vpx/src/vpx_image.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2010 The VP8 project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license and patent + * grant that can be found in the LICENSE file in the root of the source + * tree. All contributing project authors may be found in the AUTHORS + * file in the root of the source tree. + */ + + +#include <stdlib.h> +#include <string.h> +#include "vpx/vpx_image.h" + +static vpx_image_t *img_alloc_helper(vpx_image_t *img, + vpx_img_fmt_t fmt, + unsigned int d_w, + unsigned int d_h, + unsigned int stride_align, + unsigned char *img_data) +{ + + unsigned int h, w, s, xcs, ycs, bps; + int align; + + /* Treat align==0 like align==1 */ + if (!stride_align) + stride_align = 1; + + /* Validate alignment (must be power of 2) */ + if (stride_align & (stride_align - 1)) + goto fail; + + /* Get sample size for this format */ + switch (fmt) + { + case VPX_IMG_FMT_RGB32: + case VPX_IMG_FMT_RGB32_LE: + case VPX_IMG_FMT_ARGB: + case VPX_IMG_FMT_ARGB_LE: + bps = 32; + break; + case VPX_IMG_FMT_RGB24: + case VPX_IMG_FMT_BGR24: + bps = 24; + break; + case VPX_IMG_FMT_RGB565: + case VPX_IMG_FMT_RGB565_LE: + case VPX_IMG_FMT_RGB555: + case VPX_IMG_FMT_RGB555_LE: + case VPX_IMG_FMT_UYVY: + case VPX_IMG_FMT_YUY2: + case VPX_IMG_FMT_YVYU: + bps = 16; + break; + case VPX_IMG_FMT_I420: + case VPX_IMG_FMT_YV12: + case VPX_IMG_FMT_VPXI420: + case VPX_IMG_FMT_VPXYV12: + bps = 12; + break; + default: + bps = 16; + break; + } + + /* Get chroma shift values for this format */ + switch (fmt) + { + case VPX_IMG_FMT_I420: + case VPX_IMG_FMT_YV12: + case VPX_IMG_FMT_VPXI420: + case VPX_IMG_FMT_VPXYV12: + xcs = 1; + break; + default: + xcs = 0; + break; + } + + switch (fmt) + { + case VPX_IMG_FMT_I420: + case VPX_IMG_FMT_YV12: + case VPX_IMG_FMT_VPXI420: + case VPX_IMG_FMT_VPXYV12: + ycs = 1; + break; + default: + ycs = 0; + break; + } + + /* Calculate storage sizes given the chroma subsampling */ + align = (1 << xcs) - 1; + w = (d_w + align) & ~align; + align = (1 << ycs) - 1; + h = (d_h + align) & ~align; + s = (fmt & VPX_IMG_FMT_PLANAR) ? w : bps * w / 8; + s = (s + stride_align - 1) & ~(stride_align - 1); + + /* Allocate the new image */ + if (!img) + { + img = (vpx_image_t *)calloc(1, sizeof(vpx_image_t)); + + if (!img) + goto fail; + + img->self_allocd = 1; + } + else + { + memset(img, 0, sizeof(vpx_image_t)); + } + + img->img_data = img_data; + + if (!img_data) + { + img->img_data = malloc((fmt & VPX_IMG_FMT_PLANAR) ? h * w * bps / 8 : h * s); + img->img_data_owner = 1; + } + + if (!img->img_data) + goto fail; + + img->fmt = fmt; + img->w = w; + img->h = h; + img->x_chroma_shift = xcs; + img->y_chroma_shift = ycs; + img->bps = bps; + + /* Calculate strides */ + img->stride[PLANE_Y] = img->stride[PLANE_ALPHA] = s; + img->stride[PLANE_U] = img->stride[PLANE_V] = s >> xcs; + + /* Default viewport to entire image */ + if (!vpx_img_set_rect(img, 0, 0, d_w, d_h)) + return img; + +fail: + vpx_img_free(img); + return NULL; +} + +vpx_image_t *vpx_img_alloc(vpx_image_t *img, + vpx_img_fmt_t fmt, + unsigned int d_w, + unsigned int d_h, + unsigned int stride_align) +{ + return img_alloc_helper(img, fmt, d_w, d_h, stride_align, NULL); +} + +vpx_image_t *vpx_img_wrap(vpx_image_t *img, + vpx_img_fmt_t fmt, + unsigned int d_w, + unsigned int d_h, + unsigned int stride_align, + unsigned char *img_data) +{ + return img_alloc_helper(img, fmt, d_w, d_h, stride_align, img_data); +} + +int vpx_img_set_rect(vpx_image_t *img, + unsigned int x, + unsigned int y, + unsigned int w, + unsigned int h) +{ + unsigned char *data; + + if (x + w <= img->w && y + h <= img->h) + { + img->d_w = w; + img->d_h = h; + + /* Calculate plane pointers */ + if (!(img->fmt & VPX_IMG_FMT_PLANAR)) + { + img->planes[PLANE_PACKED] = + img->img_data + x * img->bps / 8 + y * img->stride[PLANE_PACKED]; + } + else + { + data = img->img_data; + + if (img->fmt & VPX_IMG_FMT_HAS_ALPHA) + { + img->planes[PLANE_ALPHA] = + data + x + y * img->stride[PLANE_ALPHA]; + data += img->h * img->stride[PLANE_ALPHA]; + } + + img->planes[PLANE_Y] = data + x + y * img->stride[PLANE_Y]; + data += img->h * img->stride[PLANE_Y]; + + if (!(img->fmt & VPX_IMG_FMT_UV_FLIP)) + { + img->planes[PLANE_U] = data + + (x >> img->x_chroma_shift) + + (y >> img->y_chroma_shift) * img->stride[PLANE_U]; + data += (img->h >> img->y_chroma_shift) * img->stride[PLANE_U]; + img->planes[PLANE_V] = data + + (x >> img->x_chroma_shift) + + (y >> img->y_chroma_shift) * img->stride[PLANE_V]; + } + else + { + img->planes[PLANE_V] = data + + (x >> img->x_chroma_shift) + + (y >> img->y_chroma_shift) * img->stride[PLANE_V]; + data += (img->h >> img->y_chroma_shift) * img->stride[PLANE_V]; + img->planes[PLANE_U] = data + + (x >> img->x_chroma_shift) + + (y >> img->y_chroma_shift) * img->stride[PLANE_U]; + } + } + + return 0; + } + + return -1; +} + +void vpx_img_flip(vpx_image_t *img) +{ + /* Note: In the calculation pointer adjustment calculation, we want the + * rhs to be promoted to a signed type. Section 6.3.1.8 of the ISO C99 + * standard indicates that if the adjustment parameter is unsigned, the + * stride parameter will be promoted to unsigned, causing errors when + * the lhs is a larger type than the rhs. + */ + img->planes[PLANE_Y] += (signed)(img->d_h - 1) * img->stride[PLANE_Y]; + img->stride[PLANE_Y] = -img->stride[PLANE_Y]; + + img->planes[PLANE_U] += (signed)((img->d_h >> img->y_chroma_shift) - 1) + * img->stride[PLANE_U]; + img->stride[PLANE_U] = -img->stride[PLANE_U]; + + img->planes[PLANE_V] += (signed)((img->d_h >> img->y_chroma_shift) - 1) + * img->stride[PLANE_V]; + img->stride[PLANE_V] = -img->stride[PLANE_V]; + + img->planes[PLANE_ALPHA] += (signed)(img->d_h - 1) * img->stride[PLANE_ALPHA]; + img->stride[PLANE_ALPHA] = -img->stride[PLANE_ALPHA]; +} + +void vpx_img_free(vpx_image_t *img) +{ + if (img) + { + if (img->img_data && img->img_data_owner) + free(img->img_data); + + if (img->self_allocd) + free(img); + } +} |