| File: | root/firefox-clang/media/libvpx/libvpx/vpx/src/vpx_encoder.c |
| Warning: | line 286, column 47 Addition of a null pointer (from variable 'dst_buf') and a probably nonzero integer value (via field 'sz') may result in undefined behavior |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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 | /*!\file | |||
| 12 | * \brief Provides the high level interface to wrap encoder algorithms. | |||
| 13 | * | |||
| 14 | */ | |||
| 15 | #include <assert.h> | |||
| 16 | #include <limits.h> | |||
| 17 | #include <stdint.h> | |||
| 18 | #include <string.h> | |||
| 19 | #include "vpx_config.h" | |||
| 20 | #include "vpx/vpx_encoder.h" | |||
| 21 | #include "vpx/internal/vpx_codec_internal.h" | |||
| 22 | ||||
| 23 | #define SAVE_STATUS(ctx, var)((ctx) ? ((ctx)->err = (var)) : (var)) ((ctx) ? ((ctx)->err = (var)) : (var)) | |||
| 24 | ||||
| 25 | static vpx_codec_alg_priv_t *get_alg_priv(vpx_codec_ctx_t *ctx) { | |||
| 26 | return (vpx_codec_alg_priv_t *)ctx->priv; | |||
| 27 | } | |||
| 28 | ||||
| 29 | vpx_codec_err_t vpx_codec_enc_init_ver(vpx_codec_ctx_t *ctx, | |||
| 30 | vpx_codec_iface_t *iface, | |||
| 31 | const vpx_codec_enc_cfg_t *cfg, | |||
| 32 | vpx_codec_flags_t flags, int ver) { | |||
| 33 | vpx_codec_err_t res; | |||
| 34 | ||||
| 35 | if (ver != VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (6 + 4))) | |||
| 36 | res = VPX_CODEC_ABI_MISMATCH; | |||
| 37 | else if (!ctx || !iface || !cfg) | |||
| 38 | res = VPX_CODEC_INVALID_PARAM; | |||
| 39 | else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION(5)) | |||
| 40 | res = VPX_CODEC_ABI_MISMATCH; | |||
| 41 | else if (!(iface->caps & VPX_CODEC_CAP_ENCODER0x2)) | |||
| 42 | res = VPX_CODEC_INCAPABLE; | |||
| 43 | else if ((flags & VPX_CODEC_USE_PSNR0x10000) && !(iface->caps & VPX_CODEC_CAP_PSNR0x10000)) | |||
| 44 | res = VPX_CODEC_INCAPABLE; | |||
| 45 | else if ((flags & VPX_CODEC_USE_OUTPUT_PARTITION0x20000) && | |||
| 46 | !(iface->caps & VPX_CODEC_CAP_OUTPUT_PARTITION0x20000)) | |||
| 47 | res = VPX_CODEC_INCAPABLE; | |||
| 48 | else { | |||
| 49 | ctx->iface = iface; | |||
| 50 | ctx->name = iface->name; | |||
| 51 | ctx->priv = NULL((void*)0); | |||
| 52 | ctx->init_flags = flags; | |||
| 53 | ctx->config.enc = cfg; | |||
| 54 | res = ctx->iface->init(ctx, NULL((void*)0)); | |||
| 55 | ||||
| 56 | if (res) { | |||
| 57 | // IMPORTANT: ctx->priv->err_detail must be null or point to a string | |||
| 58 | // that remains valid after ctx->priv is destroyed, such as a C string | |||
| 59 | // literal. This makes it safe to call vpx_codec_error_detail() after | |||
| 60 | // vpx_codec_enc_init_ver() failed. | |||
| 61 | ctx->err_detail = ctx->priv ? ctx->priv->err_detail : NULL((void*)0); | |||
| 62 | vpx_codec_destroy(ctx); | |||
| 63 | } | |||
| 64 | } | |||
| 65 | ||||
| 66 | return SAVE_STATUS(ctx, res)((ctx) ? ((ctx)->err = (res)) : (res)); | |||
| 67 | } | |||
| 68 | ||||
| 69 | vpx_codec_err_t vpx_codec_enc_init_multi_ver( | |||
| 70 | vpx_codec_ctx_t *ctx, vpx_codec_iface_t *iface, | |||
| 71 | const vpx_codec_enc_cfg_t *cfg, int num_enc, vpx_codec_flags_t flags, | |||
| 72 | const vpx_rational_t *dsf, int ver) { | |||
| 73 | vpx_codec_err_t res = VPX_CODEC_OK; | |||
| 74 | ||||
| 75 | if (ver != VPX_ENCODER_ABI_VERSION(18 + (4 + (5)) + (6 + 4))) | |||
| 76 | res = VPX_CODEC_ABI_MISMATCH; | |||
| 77 | else if (!ctx || !iface || !cfg || (num_enc > 16 || num_enc < 1) || !dsf) | |||
| 78 | res = VPX_CODEC_INVALID_PARAM; | |||
| 79 | else if (iface->abi_version != VPX_CODEC_INTERNAL_ABI_VERSION(5)) | |||
| 80 | res = VPX_CODEC_ABI_MISMATCH; | |||
| 81 | else if (!(iface->caps & VPX_CODEC_CAP_ENCODER0x2)) | |||
| 82 | res = VPX_CODEC_INCAPABLE; | |||
| 83 | else if ((flags & VPX_CODEC_USE_PSNR0x10000) && !(iface->caps & VPX_CODEC_CAP_PSNR0x10000)) | |||
| 84 | res = VPX_CODEC_INCAPABLE; | |||
| 85 | else if ((flags & VPX_CODEC_USE_OUTPUT_PARTITION0x20000) && | |||
| 86 | !(iface->caps & VPX_CODEC_CAP_OUTPUT_PARTITION0x20000)) | |||
| 87 | res = VPX_CODEC_INCAPABLE; | |||
| 88 | else { | |||
| 89 | int i; | |||
| 90 | #if CONFIG_MULTI_RES_ENCODING1 | |||
| 91 | int mem_loc_owned = 0; | |||
| 92 | #endif | |||
| 93 | void *mem_loc; | |||
| 94 | ||||
| 95 | if (iface->enc.mr_get_mem_loc == NULL((void*)0)) return VPX_CODEC_INCAPABLE; | |||
| 96 | ||||
| 97 | if (!(res = iface->enc.mr_get_mem_loc(cfg, &mem_loc))) { | |||
| 98 | for (i = 0; i < num_enc; i++) { | |||
| 99 | vpx_codec_priv_enc_mr_cfg_t mr_cfg; | |||
| 100 | ||||
| 101 | /* Validate down-sampling factor. */ | |||
| 102 | if (dsf->num < 1 || dsf->num > 4096 || dsf->den < 1 || | |||
| 103 | dsf->den > dsf->num) { | |||
| 104 | res = VPX_CODEC_INVALID_PARAM; | |||
| 105 | } else { | |||
| 106 | mr_cfg.mr_low_res_mode_info = mem_loc; | |||
| 107 | mr_cfg.mr_total_resolutions = num_enc; | |||
| 108 | mr_cfg.mr_encoder_id = num_enc - 1 - i; | |||
| 109 | mr_cfg.mr_down_sampling_factor = *dsf; | |||
| 110 | ||||
| 111 | ctx->iface = iface; | |||
| 112 | ctx->name = iface->name; | |||
| 113 | ctx->priv = NULL((void*)0); | |||
| 114 | ctx->init_flags = flags; | |||
| 115 | ctx->config.enc = cfg; | |||
| 116 | // ctx takes ownership of mr_cfg.mr_low_res_mode_info if and only if | |||
| 117 | // this call succeeds. The first ctx entry in the array is | |||
| 118 | // responsible for freeing the memory. | |||
| 119 | res = ctx->iface->init(ctx, &mr_cfg); | |||
| 120 | } | |||
| 121 | ||||
| 122 | if (res) { | |||
| 123 | const char *error_detail = ctx->priv ? ctx->priv->err_detail : NULL((void*)0); | |||
| 124 | /* Destroy current ctx */ | |||
| 125 | ctx->err_detail = error_detail; | |||
| 126 | vpx_codec_destroy(ctx); | |||
| 127 | ||||
| 128 | /* Destroy already allocated high-level ctx */ | |||
| 129 | while (i) { | |||
| 130 | ctx--; | |||
| 131 | ctx->err_detail = error_detail; | |||
| 132 | vpx_codec_destroy(ctx); | |||
| 133 | i--; | |||
| 134 | } | |||
| 135 | #if CONFIG_MULTI_RES_ENCODING1 | |||
| 136 | if (!mem_loc_owned) { | |||
| 137 | assert(mem_loc)((void) sizeof ((mem_loc) ? 1 : 0), __extension__ ({ if (mem_loc ) ; else __assert_fail ("mem_loc", "/root/firefox-clang/media/libvpx/libvpx/vpx/src/vpx_encoder.c" , 137, __extension__ __PRETTY_FUNCTION__); })); | |||
| 138 | iface->enc.mr_free_mem_loc(mem_loc); | |||
| 139 | } | |||
| 140 | #endif | |||
| 141 | return SAVE_STATUS(ctx, res)((ctx) ? ((ctx)->err = (res)) : (res)); | |||
| 142 | } | |||
| 143 | #if CONFIG_MULTI_RES_ENCODING1 | |||
| 144 | mem_loc_owned = 1; | |||
| 145 | #endif | |||
| 146 | ctx++; | |||
| 147 | cfg++; | |||
| 148 | dsf++; | |||
| 149 | } | |||
| 150 | ctx--; | |||
| 151 | } | |||
| 152 | } | |||
| 153 | ||||
| 154 | return SAVE_STATUS(ctx, res)((ctx) ? ((ctx)->err = (res)) : (res)); | |||
| 155 | } | |||
| 156 | ||||
| 157 | vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface, | |||
| 158 | vpx_codec_enc_cfg_t *cfg, | |||
| 159 | unsigned int usage) { | |||
| 160 | vpx_codec_err_t res; | |||
| 161 | ||||
| 162 | if (!iface || !cfg || usage != 0) | |||
| 163 | res = VPX_CODEC_INVALID_PARAM; | |||
| 164 | else if (!(iface->caps & VPX_CODEC_CAP_ENCODER0x2)) | |||
| 165 | res = VPX_CODEC_INCAPABLE; | |||
| 166 | else { | |||
| 167 | assert(iface->enc.cfg_map_count == 1)((void) sizeof ((iface->enc.cfg_map_count == 1) ? 1 : 0), __extension__ ({ if (iface->enc.cfg_map_count == 1) ; else __assert_fail ("iface->enc.cfg_map_count == 1", "/root/firefox-clang/media/libvpx/libvpx/vpx/src/vpx_encoder.c" , 167, __extension__ __PRETTY_FUNCTION__); })); | |||
| 168 | *cfg = iface->enc.cfg_maps->cfg; | |||
| 169 | res = VPX_CODEC_OK; | |||
| 170 | } | |||
| 171 | ||||
| 172 | return res; | |||
| 173 | } | |||
| 174 | ||||
| 175 | #if VPX_ARCH_X860 || VPX_ARCH_X86_641 | |||
| 176 | /* On X86, disable the x87 unit's internal 80 bit precision for better | |||
| 177 | * consistency with the SSE unit's 64 bit precision. | |||
| 178 | */ | |||
| 179 | #include "vpx_ports/x86.h" | |||
| 180 | #define FLOATING_POINT_INIT()do { unsigned short x87_orig_mode = x87_set_double_precision( ) \ | |||
| 181 | do { \ | |||
| 182 | unsigned short x87_orig_mode = x87_set_double_precision() | |||
| 183 | #define FLOATING_POINT_RESTORE()x87_set_control_word(x87_orig_mode); } while (0) \ | |||
| 184 | x87_set_control_word(x87_orig_mode); \ | |||
| 185 | } \ | |||
| 186 | while (0) | |||
| 187 | ||||
| 188 | #else | |||
| 189 | static void FLOATING_POINT_INIT(void) {} | |||
| 190 | static void FLOATING_POINT_RESTORE(void) {} | |||
| 191 | #endif | |||
| 192 | ||||
| 193 | vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx, const vpx_image_t *img, | |||
| 194 | vpx_codec_pts_t pts, unsigned long duration, | |||
| 195 | vpx_enc_frame_flags_t flags, | |||
| 196 | vpx_enc_deadline_t deadline) { | |||
| 197 | vpx_codec_err_t res = VPX_CODEC_OK; | |||
| 198 | ||||
| 199 | if (!ctx || (img && !duration)) | |||
| 200 | res = VPX_CODEC_INVALID_PARAM; | |||
| 201 | else if (!ctx->iface || !ctx->priv) | |||
| 202 | res = VPX_CODEC_ERROR; | |||
| 203 | else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER0x2)) | |||
| 204 | res = VPX_CODEC_INCAPABLE; | |||
| 205 | #if ULONG_MAX(9223372036854775807L *2UL+1UL) > UINT32_MAX(4294967295U) | |||
| 206 | else if (duration > UINT32_MAX(4294967295U) || deadline > UINT32_MAX(4294967295U)) | |||
| 207 | res = VPX_CODEC_INVALID_PARAM; | |||
| 208 | #endif | |||
| 209 | else { | |||
| 210 | unsigned int num_enc = ctx->priv->enc.total_encoders; | |||
| 211 | ||||
| 212 | /* Execute in a normalized floating point environment, if the platform | |||
| 213 | * requires it. | |||
| 214 | */ | |||
| 215 | FLOATING_POINT_INIT()do { unsigned short x87_orig_mode = x87_set_double_precision( ); | |||
| 216 | ||||
| 217 | if (num_enc == 1) | |||
| 218 | res = ctx->iface->enc.encode(get_alg_priv(ctx), img, pts, duration, flags, | |||
| 219 | deadline); | |||
| 220 | else { | |||
| 221 | /* Multi-resolution encoding: | |||
| 222 | * Encode multi-levels in reverse order. For example, | |||
| 223 | * if mr_total_resolutions = 3, first encode level 2, | |||
| 224 | * then encode level 1, and finally encode level 0. | |||
| 225 | */ | |||
| 226 | int i; | |||
| 227 | ||||
| 228 | ctx += num_enc - 1; | |||
| 229 | if (img) img += num_enc - 1; | |||
| 230 | ||||
| 231 | for (i = num_enc - 1; i >= 0; i--) { | |||
| 232 | if ((res = ctx->iface->enc.encode(get_alg_priv(ctx), img, pts, duration, | |||
| 233 | flags, deadline))) | |||
| 234 | break; | |||
| 235 | ||||
| 236 | ctx--; | |||
| 237 | if (img) img--; | |||
| 238 | } | |||
| 239 | ctx++; | |||
| 240 | } | |||
| 241 | ||||
| 242 | FLOATING_POINT_RESTORE()x87_set_control_word(x87_orig_mode); } while (0); | |||
| 243 | } | |||
| 244 | ||||
| 245 | return SAVE_STATUS(ctx, res)((ctx) ? ((ctx)->err = (res)) : (res)); | |||
| 246 | } | |||
| 247 | ||||
| 248 | const vpx_codec_cx_pkt_t *vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx, | |||
| 249 | vpx_codec_iter_t *iter) { | |||
| 250 | const vpx_codec_cx_pkt_t *pkt = NULL((void*)0); | |||
| 251 | ||||
| 252 | if (ctx) { | |||
| ||||
| 253 | if (!iter) | |||
| 254 | ctx->err = VPX_CODEC_INVALID_PARAM; | |||
| 255 | else if (!ctx->iface || !ctx->priv) | |||
| 256 | ctx->err = VPX_CODEC_ERROR; | |||
| 257 | else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER0x2)) | |||
| 258 | ctx->err = VPX_CODEC_INCAPABLE; | |||
| 259 | else | |||
| 260 | pkt = ctx->iface->enc.get_cx_data(get_alg_priv(ctx), iter); | |||
| 261 | } | |||
| 262 | ||||
| 263 | if (pkt && pkt->kind == VPX_CODEC_CX_FRAME_PKT) { | |||
| 264 | // If the application has specified a destination area for the | |||
| 265 | // compressed data, and the codec has not placed the data there, | |||
| 266 | // and it fits, copy it. | |||
| 267 | vpx_codec_priv_t *const priv = ctx->priv; | |||
| 268 | char *const dst_buf = (char *)priv->enc.cx_data_dst_buf.buf; | |||
| 269 | ||||
| 270 | if (dst_buf && pkt->data.raw.buf != dst_buf && | |||
| 271 | pkt->data.raw.sz + priv->enc.cx_data_pad_before + | |||
| 272 | priv->enc.cx_data_pad_after <= | |||
| 273 | priv->enc.cx_data_dst_buf.sz) { | |||
| 274 | vpx_codec_cx_pkt_t *modified_pkt = &priv->enc.cx_data_pkt; | |||
| 275 | ||||
| 276 | memcpy(dst_buf + priv->enc.cx_data_pad_before, pkt->data.raw.buf, | |||
| 277 | pkt->data.raw.sz); | |||
| 278 | *modified_pkt = *pkt; | |||
| 279 | modified_pkt->data.raw.buf = dst_buf; | |||
| 280 | modified_pkt->data.raw.sz += | |||
| 281 | priv->enc.cx_data_pad_before + priv->enc.cx_data_pad_after; | |||
| 282 | pkt = modified_pkt; | |||
| 283 | } | |||
| 284 | ||||
| 285 | if (dst_buf == pkt->data.raw.buf) { | |||
| 286 | priv->enc.cx_data_dst_buf.buf = dst_buf + pkt->data.raw.sz; | |||
| ||||
| 287 | priv->enc.cx_data_dst_buf.sz -= pkt->data.raw.sz; | |||
| 288 | } | |||
| 289 | } | |||
| 290 | ||||
| 291 | return pkt; | |||
| 292 | } | |||
| 293 | ||||
| 294 | vpx_codec_err_t vpx_codec_set_cx_data_buf(vpx_codec_ctx_t *ctx, | |||
| 295 | const vpx_fixed_buf_t *buf, | |||
| 296 | unsigned int pad_before, | |||
| 297 | unsigned int pad_after) { | |||
| 298 | if (!ctx || !ctx->priv) return VPX_CODEC_INVALID_PARAM; | |||
| 299 | ||||
| 300 | if (buf) { | |||
| 301 | ctx->priv->enc.cx_data_dst_buf = *buf; | |||
| 302 | ctx->priv->enc.cx_data_pad_before = pad_before; | |||
| 303 | ctx->priv->enc.cx_data_pad_after = pad_after; | |||
| 304 | } else { | |||
| 305 | ctx->priv->enc.cx_data_dst_buf.buf = NULL((void*)0); | |||
| 306 | ctx->priv->enc.cx_data_dst_buf.sz = 0; | |||
| 307 | ctx->priv->enc.cx_data_pad_before = 0; | |||
| 308 | ctx->priv->enc.cx_data_pad_after = 0; | |||
| 309 | } | |||
| 310 | ||||
| 311 | return VPX_CODEC_OK; | |||
| 312 | } | |||
| 313 | ||||
| 314 | const vpx_image_t *vpx_codec_get_preview_frame(vpx_codec_ctx_t *ctx) { | |||
| 315 | vpx_image_t *img = NULL((void*)0); | |||
| 316 | ||||
| 317 | if (ctx) { | |||
| 318 | if (!ctx->iface || !ctx->priv) | |||
| 319 | ctx->err = VPX_CODEC_ERROR; | |||
| 320 | else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER0x2)) | |||
| 321 | ctx->err = VPX_CODEC_INCAPABLE; | |||
| 322 | else if (!ctx->iface->enc.get_preview) | |||
| 323 | ctx->err = VPX_CODEC_INCAPABLE; | |||
| 324 | else | |||
| 325 | img = ctx->iface->enc.get_preview(get_alg_priv(ctx)); | |||
| 326 | } | |||
| 327 | ||||
| 328 | return img; | |||
| 329 | } | |||
| 330 | ||||
| 331 | vpx_fixed_buf_t *vpx_codec_get_global_headers(vpx_codec_ctx_t *ctx) { | |||
| 332 | vpx_fixed_buf_t *buf = NULL((void*)0); | |||
| 333 | ||||
| 334 | if (ctx) { | |||
| 335 | if (!ctx->iface || !ctx->priv) | |||
| 336 | ctx->err = VPX_CODEC_ERROR; | |||
| 337 | else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER0x2)) | |||
| 338 | ctx->err = VPX_CODEC_INCAPABLE; | |||
| 339 | else if (!ctx->iface->enc.get_glob_hdrs) | |||
| 340 | ctx->err = VPX_CODEC_INCAPABLE; | |||
| 341 | else | |||
| 342 | buf = ctx->iface->enc.get_glob_hdrs(get_alg_priv(ctx)); | |||
| 343 | } | |||
| 344 | ||||
| 345 | return buf; | |||
| 346 | } | |||
| 347 | ||||
| 348 | vpx_codec_err_t vpx_codec_enc_config_set(vpx_codec_ctx_t *ctx, | |||
| 349 | const vpx_codec_enc_cfg_t *cfg) { | |||
| 350 | vpx_codec_err_t res; | |||
| 351 | ||||
| 352 | if (!ctx || !ctx->iface || !ctx->priv || !cfg) | |||
| 353 | res = VPX_CODEC_INVALID_PARAM; | |||
| 354 | else if (!(ctx->iface->caps & VPX_CODEC_CAP_ENCODER0x2)) | |||
| 355 | res = VPX_CODEC_INCAPABLE; | |||
| 356 | else | |||
| 357 | res = ctx->iface->enc.cfg_set(get_alg_priv(ctx), cfg); | |||
| 358 | ||||
| 359 | return SAVE_STATUS(ctx, res)((ctx) ? ((ctx)->err = (res)) : (res)); | |||
| 360 | } | |||
| 361 | ||||
| 362 | int vpx_codec_pkt_list_add(struct vpx_codec_pkt_list *list, | |||
| 363 | const struct vpx_codec_cx_pkt *pkt) { | |||
| 364 | if (list->cnt < list->max) { | |||
| 365 | list->pkts[list->cnt++] = *pkt; | |||
| 366 | return 0; | |||
| 367 | } | |||
| 368 | ||||
| 369 | return 1; | |||
| 370 | } | |||
| 371 | ||||
| 372 | const vpx_codec_cx_pkt_t *vpx_codec_pkt_list_get( | |||
| 373 | struct vpx_codec_pkt_list *list, vpx_codec_iter_t *iter) { | |||
| 374 | const vpx_codec_cx_pkt_t *pkt; | |||
| 375 | ||||
| 376 | if (!(*iter)) { | |||
| 377 | *iter = list->pkts; | |||
| 378 | } | |||
| 379 | ||||
| 380 | pkt = (const vpx_codec_cx_pkt_t *)*iter; | |||
| 381 | ||||
| 382 | if ((size_t)(pkt - list->pkts) < list->cnt) | |||
| 383 | *iter = pkt + 1; | |||
| 384 | else | |||
| 385 | pkt = NULL((void*)0); | |||
| 386 | ||||
| 387 | return pkt; | |||
| 388 | } |