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