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