| File: | root/firefox-clang/media/libvpx/libvpx/vp9/vp9_dx_iface.c |
| Warning: | line 371, column 42 Addition of a null pointer (from variable 'data') and a nonzero integer value (from variable 'data_sz') results 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 | #include <stdlib.h> | |||
| 12 | #include <string.h> | |||
| 13 | ||||
| 14 | #include "./vpx_config.h" | |||
| 15 | #include "./vpx_version.h" | |||
| 16 | ||||
| 17 | #include "vpx/internal/vpx_codec_internal.h" | |||
| 18 | #include "vpx/vp8dx.h" | |||
| 19 | #include "vpx/vpx_decoder.h" | |||
| 20 | #include "vpx_dsp/bitreader_buffer.h" | |||
| 21 | #include "vpx_dsp/vpx_dsp_common.h" | |||
| 22 | ||||
| 23 | #include "vp9/common/vp9_alloccommon.h" | |||
| 24 | #include "vp9/common/vp9_frame_buffers.h" | |||
| 25 | ||||
| 26 | #include "vp9/decoder/vp9_decodeframe.h" | |||
| 27 | ||||
| 28 | #include "vp9/vp9_dx_iface.h" | |||
| 29 | #include "vp9/vp9_iface_common.h" | |||
| 30 | ||||
| 31 | #define VP9_CAP_POSTPROC(1 ? 0x40000 : 0) (CONFIG_VP9_POSTPROC1 ? VPX_CODEC_CAP_POSTPROC0x40000 : 0) | |||
| 32 | ||||
| 33 | static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx, | |||
| 34 | vpx_codec_priv_enc_mr_cfg_t *data) { | |||
| 35 | // This function only allocates space for the vpx_codec_alg_priv_t | |||
| 36 | // structure. More memory may be required at the time the stream | |||
| 37 | // information becomes known. | |||
| 38 | (void)data; | |||
| 39 | ||||
| 40 | if (!ctx->priv) { | |||
| 41 | vpx_codec_alg_priv_t *const priv = | |||
| 42 | (vpx_codec_alg_priv_t *)vpx_calloc(1, sizeof(*priv)); | |||
| 43 | if (priv == NULL((void*)0)) return VPX_CODEC_MEM_ERROR; | |||
| 44 | ||||
| 45 | ctx->priv = (vpx_codec_priv_t *)priv; | |||
| 46 | ctx->priv->init_flags = ctx->init_flags; | |||
| 47 | priv->si.sz = sizeof(priv->si); | |||
| 48 | priv->flushed = 0; | |||
| 49 | if (ctx->config.dec) { | |||
| 50 | priv->cfg = *ctx->config.dec; | |||
| 51 | ctx->config.dec = &priv->cfg; | |||
| 52 | } | |||
| 53 | } | |||
| 54 | ||||
| 55 | return VPX_CODEC_OK; | |||
| 56 | } | |||
| 57 | ||||
| 58 | static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) { | |||
| 59 | if (ctx->pbi != NULL((void*)0)) { | |||
| 60 | vp9_decoder_remove(ctx->pbi); | |||
| 61 | } | |||
| 62 | ||||
| 63 | if (ctx->buffer_pool) { | |||
| 64 | vp9_free_ref_frame_buffers(ctx->buffer_pool); | |||
| 65 | vp9_free_internal_frame_buffers(&ctx->buffer_pool->int_frame_buffers); | |||
| 66 | } | |||
| 67 | ||||
| 68 | vpx_free(ctx->buffer_pool); | |||
| 69 | vpx_free(ctx); | |||
| 70 | return VPX_CODEC_OK; | |||
| 71 | } | |||
| 72 | ||||
| 73 | static int parse_bitdepth_colorspace_sampling(BITSTREAM_PROFILE profile, | |||
| 74 | struct vpx_read_bit_buffer *rb) { | |||
| 75 | vpx_color_space_t color_space; | |||
| 76 | if (profile >= PROFILE_2) rb->bit_offset += 1; // Bit-depth 10 or 12. | |||
| 77 | color_space = (vpx_color_space_t)vpx_rb_read_literal(rb, 3); | |||
| 78 | if (color_space != VPX_CS_SRGB) { | |||
| 79 | rb->bit_offset += 1; // [16,235] (including xvycc) vs [0,255] range. | |||
| 80 | if (profile == PROFILE_1 || profile == PROFILE_3) { | |||
| 81 | rb->bit_offset += 2; // subsampling x/y. | |||
| 82 | rb->bit_offset += 1; // unused. | |||
| 83 | } | |||
| 84 | } else { | |||
| 85 | if (profile == PROFILE_1 || profile == PROFILE_3) { | |||
| 86 | rb->bit_offset += 1; // unused | |||
| 87 | } else { | |||
| 88 | // RGB is only available in version 1. | |||
| 89 | return 0; | |||
| 90 | } | |||
| 91 | } | |||
| 92 | return 1; | |||
| 93 | } | |||
| 94 | ||||
| 95 | static vpx_codec_err_t decoder_peek_si_internal( | |||
| 96 | const uint8_t *data, unsigned int data_sz, vpx_codec_stream_info_t *si, | |||
| 97 | int *is_intra_only, vpx_decrypt_cb decrypt_cb, void *decrypt_state) { | |||
| 98 | int intra_only_flag = 0; | |||
| 99 | uint8_t clear_buffer[11]; | |||
| 100 | ||||
| 101 | if (data + data_sz <= data) return VPX_CODEC_INVALID_PARAM; | |||
| 102 | ||||
| 103 | si->is_kf = 0; | |||
| 104 | si->w = si->h = 0; | |||
| 105 | ||||
| 106 | if (decrypt_cb) { | |||
| 107 | data_sz = VPXMIN(sizeof(clear_buffer), data_sz)(((sizeof(clear_buffer)) < (data_sz)) ? (sizeof(clear_buffer )) : (data_sz)); | |||
| 108 | decrypt_cb(decrypt_state, data, clear_buffer, data_sz); | |||
| 109 | data = clear_buffer; | |||
| 110 | } | |||
| 111 | ||||
| 112 | // A maximum of 6 bits are needed to read the frame marker, profile and | |||
| 113 | // show_existing_frame. | |||
| 114 | if (data_sz < 1) return VPX_CODEC_UNSUP_BITSTREAM; | |||
| 115 | ||||
| 116 | { | |||
| 117 | int show_frame; | |||
| 118 | int error_resilient; | |||
| 119 | struct vpx_read_bit_buffer rb = { data, data + data_sz, 0, NULL((void*)0), NULL((void*)0) }; | |||
| 120 | const int frame_marker = vpx_rb_read_literal(&rb, 2); | |||
| 121 | const BITSTREAM_PROFILE profile = vp9_read_profile(&rb); | |||
| 122 | ||||
| 123 | if (frame_marker != VP9_FRAME_MARKER0x2) return VPX_CODEC_UNSUP_BITSTREAM; | |||
| 124 | ||||
| 125 | if (profile >= MAX_PROFILES) return VPX_CODEC_UNSUP_BITSTREAM; | |||
| 126 | ||||
| 127 | if (vpx_rb_read_bit(&rb)) { // show an existing frame | |||
| 128 | // If profile is > 2 and show_existing_frame is true, then at least 1 more | |||
| 129 | // byte (6+3=9 bits) is needed. | |||
| 130 | if (profile > 2 && data_sz < 2) return VPX_CODEC_UNSUP_BITSTREAM; | |||
| 131 | vpx_rb_read_literal(&rb, 3); // Frame buffer to show. | |||
| 132 | return VPX_CODEC_OK; | |||
| 133 | } | |||
| 134 | ||||
| 135 | // For the rest of the function, a maximum of 9 more bytes are needed | |||
| 136 | // (computed by taking the maximum possible bits needed in each case). Note | |||
| 137 | // that this has to be updated if we read any more bits in this function. | |||
| 138 | if (data_sz < 10) return VPX_CODEC_UNSUP_BITSTREAM; | |||
| 139 | ||||
| 140 | si->is_kf = !vpx_rb_read_bit(&rb); | |||
| 141 | show_frame = vpx_rb_read_bit(&rb); | |||
| 142 | error_resilient = vpx_rb_read_bit(&rb); | |||
| 143 | ||||
| 144 | if (si->is_kf) { | |||
| 145 | if (!vp9_read_sync_code(&rb)) return VPX_CODEC_UNSUP_BITSTREAM; | |||
| 146 | ||||
| 147 | if (!parse_bitdepth_colorspace_sampling(profile, &rb)) | |||
| 148 | return VPX_CODEC_UNSUP_BITSTREAM; | |||
| 149 | vp9_read_frame_size(&rb, (int *)&si->w, (int *)&si->h); | |||
| 150 | } else { | |||
| 151 | intra_only_flag = show_frame ? 0 : vpx_rb_read_bit(&rb); | |||
| 152 | ||||
| 153 | rb.bit_offset += error_resilient ? 0 : 2; // reset_frame_context | |||
| 154 | ||||
| 155 | if (intra_only_flag) { | |||
| 156 | if (!vp9_read_sync_code(&rb)) return VPX_CODEC_UNSUP_BITSTREAM; | |||
| 157 | if (profile > PROFILE_0) { | |||
| 158 | if (!parse_bitdepth_colorspace_sampling(profile, &rb)) | |||
| 159 | return VPX_CODEC_UNSUP_BITSTREAM; | |||
| 160 | // The colorspace info may cause vp9_read_frame_size() to need 11 | |||
| 161 | // bytes. | |||
| 162 | if (data_sz < 11) return VPX_CODEC_UNSUP_BITSTREAM; | |||
| 163 | } | |||
| 164 | rb.bit_offset += REF_FRAMES(1 << 3); // refresh_frame_flags | |||
| 165 | vp9_read_frame_size(&rb, (int *)&si->w, (int *)&si->h); | |||
| 166 | } | |||
| 167 | } | |||
| 168 | } | |||
| 169 | if (is_intra_only != NULL((void*)0)) *is_intra_only = intra_only_flag; | |||
| 170 | return VPX_CODEC_OK; | |||
| 171 | } | |||
| 172 | ||||
| 173 | static vpx_codec_err_t decoder_peek_si(const uint8_t *data, | |||
| 174 | unsigned int data_sz, | |||
| 175 | vpx_codec_stream_info_t *si) { | |||
| 176 | return decoder_peek_si_internal(data, data_sz, si, NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
| 177 | } | |||
| 178 | ||||
| 179 | static vpx_codec_err_t decoder_get_si(vpx_codec_alg_priv_t *ctx, | |||
| 180 | vpx_codec_stream_info_t *si) { | |||
| 181 | const size_t sz = (si->sz >= sizeof(vp9_stream_info_t)) | |||
| 182 | ? sizeof(vp9_stream_info_t) | |||
| 183 | : sizeof(vpx_codec_stream_info_t); | |||
| 184 | memcpy(si, &ctx->si, sz); | |||
| 185 | si->sz = (unsigned int)sz; | |||
| 186 | ||||
| 187 | return VPX_CODEC_OK; | |||
| 188 | } | |||
| 189 | ||||
| 190 | static void set_error_detail(vpx_codec_alg_priv_t *ctx, | |||
| 191 | const char *const error) { | |||
| 192 | ctx->base.err_detail = error; | |||
| 193 | } | |||
| 194 | ||||
| 195 | static vpx_codec_err_t update_error_state( | |||
| 196 | vpx_codec_alg_priv_t *ctx, const struct vpx_internal_error_info *error) { | |||
| 197 | if (error->error_code) | |||
| 198 | set_error_detail(ctx, error->has_detail ? error->detail : NULL((void*)0)); | |||
| 199 | ||||
| 200 | return error->error_code; | |||
| 201 | } | |||
| 202 | ||||
| 203 | static vpx_codec_err_t init_buffer_callbacks(vpx_codec_alg_priv_t *ctx) { | |||
| 204 | VP9_COMMON *const cm = &ctx->pbi->common; | |||
| 205 | BufferPool *const pool = cm->buffer_pool; | |||
| 206 | ||||
| 207 | cm->new_fb_idx = INVALID_IDX(-1); | |||
| 208 | cm->byte_alignment = ctx->byte_alignment; | |||
| 209 | cm->skip_loop_filter = ctx->skip_loop_filter; | |||
| 210 | ||||
| 211 | if (ctx->get_ext_fb_cb != NULL((void*)0) && ctx->release_ext_fb_cb != NULL((void*)0)) { | |||
| 212 | pool->get_fb_cb = ctx->get_ext_fb_cb; | |||
| 213 | pool->release_fb_cb = ctx->release_ext_fb_cb; | |||
| 214 | pool->cb_priv = ctx->ext_priv; | |||
| 215 | } else { | |||
| 216 | pool->get_fb_cb = vp9_get_frame_buffer; | |||
| 217 | pool->release_fb_cb = vp9_release_frame_buffer; | |||
| 218 | ||||
| 219 | if (vp9_alloc_internal_frame_buffers(&pool->int_frame_buffers)) { | |||
| 220 | vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, | |||
| 221 | "Failed to initialize internal frame buffers"); | |||
| 222 | return VPX_CODEC_MEM_ERROR; | |||
| 223 | } | |||
| 224 | ||||
| 225 | pool->cb_priv = &pool->int_frame_buffers; | |||
| 226 | } | |||
| 227 | ||||
| 228 | return VPX_CODEC_OK; | |||
| 229 | } | |||
| 230 | ||||
| 231 | static void set_default_ppflags(vp8_postproc_cfg_t *cfg) { | |||
| 232 | cfg->post_proc_flag = VP8_DEBLOCK | VP8_DEMACROBLOCK; | |||
| 233 | cfg->deblocking_level = 4; | |||
| 234 | cfg->noise_level = 0; | |||
| 235 | } | |||
| 236 | ||||
| 237 | static void set_ppflags(const vpx_codec_alg_priv_t *ctx, vp9_ppflags_t *flags) { | |||
| 238 | flags->post_proc_flag = ctx->postproc_cfg.post_proc_flag; | |||
| 239 | ||||
| 240 | flags->deblocking_level = ctx->postproc_cfg.deblocking_level; | |||
| 241 | flags->noise_level = ctx->postproc_cfg.noise_level; | |||
| 242 | } | |||
| 243 | ||||
| 244 | #undef ERROR | |||
| 245 | #define ERROR(str)do { ctx->base.err_detail = str; return VPX_CODEC_INVALID_PARAM ; } while (0) \ | |||
| 246 | do { \ | |||
| 247 | ctx->base.err_detail = str; \ | |||
| 248 | return VPX_CODEC_INVALID_PARAM; \ | |||
| 249 | } while (0) | |||
| 250 | ||||
| 251 | #define RANGE_CHECK(p, memb, lo, hi)do { if (!(((p)->memb == (lo) || (p)->memb > (lo)) && (p)->memb <= (hi))) do { ctx->base.err_detail = "memb" " out of range [" "lo" ".." "hi" "]"; return VPX_CODEC_INVALID_PARAM ; } while (0); } while (0) \ | |||
| 252 | do { \ | |||
| 253 | if (!(((p)->memb == (lo) || (p)->memb > (lo)) && (p)->memb <= (hi))) \ | |||
| 254 | ERROR(#memb " out of range [" #lo ".." #hi "]")do { ctx->base.err_detail = #memb " out of range [" #lo ".." #hi "]"; return VPX_CODEC_INVALID_PARAM; } while (0); \ | |||
| 255 | } while (0) | |||
| 256 | ||||
| 257 | static vpx_codec_err_t init_decoder(vpx_codec_alg_priv_t *ctx) { | |||
| 258 | vpx_codec_err_t res; | |||
| 259 | ctx->last_show_frame = -1; | |||
| 260 | ctx->need_resync = 1; | |||
| 261 | ctx->flushed = 0; | |||
| 262 | ||||
| 263 | ctx->buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(BufferPool)); | |||
| 264 | if (ctx->buffer_pool == NULL((void*)0)) return VPX_CODEC_MEM_ERROR; | |||
| 265 | ||||
| 266 | ctx->pbi = vp9_decoder_create(ctx->buffer_pool); | |||
| 267 | if (ctx->pbi == NULL((void*)0)) { | |||
| 268 | vpx_free(ctx->buffer_pool); | |||
| 269 | ctx->buffer_pool = NULL((void*)0); | |||
| 270 | set_error_detail(ctx, "Failed to allocate decoder"); | |||
| 271 | return VPX_CODEC_MEM_ERROR; | |||
| 272 | } | |||
| 273 | ctx->pbi->max_threads = ctx->cfg.threads; | |||
| 274 | ctx->pbi->inv_tile_order = ctx->invert_tile_order; | |||
| 275 | ||||
| 276 | RANGE_CHECK(ctx, row_mt, 0, 1)do { if (!(((ctx)->row_mt == (0) || (ctx)->row_mt > ( 0)) && (ctx)->row_mt <= (1))) do { ctx->base .err_detail = "row_mt" " out of range [" "0" ".." "1" "]"; return VPX_CODEC_INVALID_PARAM; } while (0); } while (0); | |||
| 277 | ctx->pbi->row_mt = ctx->row_mt; | |||
| 278 | ||||
| 279 | RANGE_CHECK(ctx, lpf_opt, 0, 1)do { if (!(((ctx)->lpf_opt == (0) || (ctx)->lpf_opt > (0)) && (ctx)->lpf_opt <= (1))) do { ctx->base .err_detail = "lpf_opt" " out of range [" "0" ".." "1" "]"; return VPX_CODEC_INVALID_PARAM; } while (0); } while (0); | |||
| 280 | ctx->pbi->lpf_mt_opt = ctx->lpf_opt; | |||
| 281 | ||||
| 282 | // If postprocessing was enabled by the application and a | |||
| 283 | // configuration has not been provided, default it. | |||
| 284 | if (!ctx->postproc_cfg_set && (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC0x10000)) | |||
| 285 | set_default_ppflags(&ctx->postproc_cfg); | |||
| 286 | ||||
| 287 | res = init_buffer_callbacks(ctx); | |||
| 288 | if (res != VPX_CODEC_OK) { | |||
| 289 | vpx_free(ctx->buffer_pool); | |||
| 290 | ctx->buffer_pool = NULL((void*)0); | |||
| 291 | vp9_decoder_remove(ctx->pbi); | |||
| 292 | ctx->pbi = NULL((void*)0); | |||
| 293 | } | |||
| 294 | return res; | |||
| 295 | } | |||
| 296 | ||||
| 297 | static INLINEinline void check_resync(vpx_codec_alg_priv_t *const ctx, | |||
| 298 | const VP9Decoder *const pbi) { | |||
| 299 | // Clear resync flag if the decoder got a key frame or intra only frame. | |||
| 300 | if (ctx->need_resync == 1 && pbi->need_resync == 0 && | |||
| 301 | (pbi->common.intra_only || pbi->common.frame_type == KEY_FRAME)) | |||
| 302 | ctx->need_resync = 0; | |||
| 303 | } | |||
| 304 | ||||
| 305 | static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, | |||
| 306 | const uint8_t **data, unsigned int data_sz, | |||
| 307 | void *user_priv) { | |||
| 308 | // Determine the stream parameters. Note that we rely on peek_si to | |||
| 309 | // validate that we have a buffer that does not wrap around the top | |||
| 310 | // of the heap. | |||
| 311 | if (!ctx->si.h) { | |||
| 312 | int is_intra_only = 0; | |||
| 313 | const vpx_codec_err_t res = | |||
| 314 | decoder_peek_si_internal(*data, data_sz, &ctx->si, &is_intra_only, | |||
| 315 | ctx->decrypt_cb, ctx->decrypt_state); | |||
| 316 | if (res != VPX_CODEC_OK) return res; | |||
| 317 | ||||
| 318 | if (!ctx->si.is_kf && !is_intra_only) return VPX_CODEC_ERROR; | |||
| 319 | } | |||
| 320 | ||||
| 321 | ctx->user_priv = user_priv; | |||
| 322 | ||||
| 323 | // Set these even if already initialized. The caller may have changed the | |||
| 324 | // decrypt config between frames. | |||
| 325 | ctx->pbi->decrypt_cb = ctx->decrypt_cb; | |||
| 326 | ctx->pbi->decrypt_state = ctx->decrypt_state; | |||
| 327 | ||||
| 328 | if (vp9_receive_compressed_data(ctx->pbi, data_sz, data)) { | |||
| 329 | ctx->pbi->cur_buf->buf.corrupted = 1; | |||
| 330 | ctx->pbi->need_resync = 1; | |||
| 331 | ctx->need_resync = 1; | |||
| 332 | return update_error_state(ctx, &ctx->pbi->common.error); | |||
| 333 | } | |||
| 334 | ||||
| 335 | check_resync(ctx, ctx->pbi); | |||
| 336 | ||||
| 337 | return VPX_CODEC_OK; | |||
| 338 | } | |||
| 339 | ||||
| 340 | static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx, | |||
| 341 | const uint8_t *data, unsigned int data_sz, | |||
| 342 | void *user_priv) { | |||
| 343 | const uint8_t *data_start = data; | |||
| 344 | vpx_codec_err_t res; | |||
| 345 | uint32_t frame_sizes[8]; | |||
| 346 | int frame_count; | |||
| 347 | ||||
| 348 | if (data == NULL((void*)0) && data_sz == 0) { | |||
| ||||
| 349 | ctx->flushed = 1; | |||
| 350 | return VPX_CODEC_OK; | |||
| 351 | } | |||
| 352 | ||||
| 353 | // Reset flushed when receiving a valid frame. | |||
| 354 | ctx->flushed = 0; | |||
| 355 | ||||
| 356 | // Initialize the decoder on the first frame. | |||
| 357 | if (ctx->pbi == NULL((void*)0)) { | |||
| 358 | res = init_decoder(ctx); | |||
| 359 | if (res != VPX_CODEC_OK) return res; | |||
| 360 | } | |||
| 361 | ||||
| 362 | res = vp9_parse_superframe_index(data, data_sz, frame_sizes, &frame_count, | |||
| 363 | ctx->decrypt_cb, ctx->decrypt_state); | |||
| 364 | if (res != VPX_CODEC_OK) return res; | |||
| 365 | ||||
| 366 | if (ctx->svc_decoding && ctx->svc_spatial_layer < frame_count - 1) | |||
| 367 | frame_count = ctx->svc_spatial_layer + 1; | |||
| 368 | ||||
| 369 | // Decode in serial mode. | |||
| 370 | if (frame_count > 0) { | |||
| 371 | const uint8_t *const data_end = data + data_sz; | |||
| ||||
| 372 | int i; | |||
| 373 | ||||
| 374 | for (i = 0; i < frame_count; ++i) { | |||
| 375 | const uint8_t *data_start_copy = data_start; | |||
| 376 | const uint32_t frame_size = frame_sizes[i]; | |||
| 377 | if (data_start < data || frame_size > (uint32_t)(data_end - data_start)) { | |||
| 378 | set_error_detail(ctx, "Invalid frame size in index"); | |||
| 379 | return VPX_CODEC_CORRUPT_FRAME; | |||
| 380 | } | |||
| 381 | ||||
| 382 | res = decode_one(ctx, &data_start_copy, frame_size, user_priv); | |||
| 383 | if (res != VPX_CODEC_OK) return res; | |||
| 384 | ||||
| 385 | data_start += frame_size; | |||
| 386 | } | |||
| 387 | } else { | |||
| 388 | const uint8_t *const data_end = data + data_sz; | |||
| 389 | while (data_start < data_end) { | |||
| 390 | const uint32_t frame_size = (uint32_t)(data_end - data_start); | |||
| 391 | res = decode_one(ctx, &data_start, frame_size, user_priv); | |||
| 392 | if (res != VPX_CODEC_OK) return res; | |||
| 393 | ||||
| 394 | // Account for suboptimal termination by the encoder. | |||
| 395 | while (data_start < data_end) { | |||
| 396 | const uint8_t marker = | |||
| 397 | read_marker(ctx->decrypt_cb, ctx->decrypt_state, data_start); | |||
| 398 | if (marker) break; | |||
| 399 | ++data_start; | |||
| 400 | } | |||
| 401 | } | |||
| 402 | } | |||
| 403 | ||||
| 404 | return res; | |||
| 405 | } | |||
| 406 | ||||
| 407 | static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx, | |||
| 408 | vpx_codec_iter_t *iter) { | |||
| 409 | vpx_image_t *img = NULL((void*)0); | |||
| 410 | ||||
| 411 | // Legacy parameter carried over from VP8. Has no effect for VP9 since we | |||
| 412 | // always return only 1 frame per decode call. | |||
| 413 | (void)iter; | |||
| 414 | ||||
| 415 | if (ctx->pbi != NULL((void*)0)) { | |||
| 416 | YV12_BUFFER_CONFIG sd; | |||
| 417 | vp9_ppflags_t flags = { 0, 0, 0 }; | |||
| 418 | if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC0x10000) set_ppflags(ctx, &flags); | |||
| 419 | if (vp9_get_raw_frame(ctx->pbi, &sd, &flags) == 0) { | |||
| 420 | VP9_COMMON *const cm = &ctx->pbi->common; | |||
| 421 | RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs; | |||
| 422 | ctx->last_show_frame = ctx->pbi->common.new_fb_idx; | |||
| 423 | if (ctx->need_resync) return NULL((void*)0); | |||
| 424 | yuvconfig2image(&ctx->img, &sd, ctx->user_priv); | |||
| 425 | ctx->img.fb_priv = frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv; | |||
| 426 | img = &ctx->img; | |||
| 427 | return img; | |||
| 428 | } | |||
| 429 | } | |||
| 430 | return NULL((void*)0); | |||
| 431 | } | |||
| 432 | ||||
| 433 | static vpx_codec_err_t decoder_set_fb_fn( | |||
| 434 | vpx_codec_alg_priv_t *ctx, vpx_get_frame_buffer_cb_fn_t cb_get, | |||
| 435 | vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) { | |||
| 436 | if (cb_get == NULL((void*)0) || cb_release == NULL((void*)0)) { | |||
| 437 | return VPX_CODEC_INVALID_PARAM; | |||
| 438 | } else if (ctx->pbi == NULL((void*)0)) { | |||
| 439 | // If the decoder has already been initialized, do not accept changes to | |||
| 440 | // the frame buffer functions. | |||
| 441 | ctx->get_ext_fb_cb = cb_get; | |||
| 442 | ctx->release_ext_fb_cb = cb_release; | |||
| 443 | ctx->ext_priv = cb_priv; | |||
| 444 | return VPX_CODEC_OK; | |||
| 445 | } | |||
| 446 | ||||
| 447 | return VPX_CODEC_ERROR; | |||
| 448 | } | |||
| 449 | ||||
| 450 | static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx, | |||
| 451 | va_list args) { | |||
| 452 | vpx_ref_frame_t *const data = va_arg(args, vpx_ref_frame_t *)__builtin_va_arg(args, vpx_ref_frame_t *); | |||
| 453 | ||||
| 454 | if (data) { | |||
| 455 | vpx_ref_frame_t *const frame = (vpx_ref_frame_t *)data; | |||
| 456 | YV12_BUFFER_CONFIG sd; | |||
| 457 | image2yuvconfig(&frame->img, &sd); | |||
| 458 | return vp9_set_reference_dec( | |||
| 459 | &ctx->pbi->common, ref_frame_to_vp9_reframe(frame->frame_type), &sd); | |||
| 460 | } else { | |||
| 461 | return VPX_CODEC_INVALID_PARAM; | |||
| 462 | } | |||
| 463 | } | |||
| 464 | ||||
| 465 | static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx, | |||
| 466 | va_list args) { | |||
| 467 | vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *)__builtin_va_arg(args, vpx_ref_frame_t *); | |||
| 468 | ||||
| 469 | if (data) { | |||
| 470 | vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; | |||
| 471 | YV12_BUFFER_CONFIG sd; | |||
| 472 | image2yuvconfig(&frame->img, &sd); | |||
| 473 | return vp9_copy_reference_dec(ctx->pbi, (VP9_REFFRAME)frame->frame_type, | |||
| 474 | &sd); | |||
| 475 | } else { | |||
| 476 | return VPX_CODEC_INVALID_PARAM; | |||
| 477 | } | |||
| 478 | } | |||
| 479 | ||||
| 480 | static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx, | |||
| 481 | va_list args) { | |||
| 482 | vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *)__builtin_va_arg(args, vp9_ref_frame_t *); | |||
| 483 | ||||
| 484 | if (data) { | |||
| 485 | if (ctx->pbi) { | |||
| 486 | const int fb_idx = ctx->pbi->common.cur_show_frame_fb_idx; | |||
| 487 | YV12_BUFFER_CONFIG *fb = get_buf_frame(&ctx->pbi->common, fb_idx); | |||
| 488 | if (fb == NULL((void*)0)) return VPX_CODEC_ERROR; | |||
| 489 | yuvconfig2image(&data->img, fb, NULL((void*)0)); | |||
| 490 | return VPX_CODEC_OK; | |||
| 491 | } else { | |||
| 492 | return VPX_CODEC_ERROR; | |||
| 493 | } | |||
| 494 | } else { | |||
| 495 | return VPX_CODEC_INVALID_PARAM; | |||
| 496 | } | |||
| 497 | } | |||
| 498 | ||||
| 499 | static vpx_codec_err_t ctrl_set_postproc(vpx_codec_alg_priv_t *ctx, | |||
| 500 | va_list args) { | |||
| 501 | #if CONFIG_VP9_POSTPROC1 | |||
| 502 | vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *)__builtin_va_arg(args, vp8_postproc_cfg_t *); | |||
| 503 | ||||
| 504 | if (data) { | |||
| 505 | ctx->postproc_cfg_set = 1; | |||
| 506 | ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data); | |||
| 507 | return VPX_CODEC_OK; | |||
| 508 | } else { | |||
| 509 | return VPX_CODEC_INVALID_PARAM; | |||
| 510 | } | |||
| 511 | #else | |||
| 512 | (void)ctx; | |||
| 513 | (void)args; | |||
| 514 | return VPX_CODEC_INCAPABLE; | |||
| 515 | #endif | |||
| 516 | } | |||
| 517 | ||||
| 518 | static vpx_codec_err_t ctrl_get_quantizer(vpx_codec_alg_priv_t *ctx, | |||
| 519 | va_list args) { | |||
| 520 | int *const arg = va_arg(args, int *)__builtin_va_arg(args, int *); | |||
| 521 | if (arg == NULL((void*)0) || ctx->pbi == NULL((void*)0)) return VPX_CODEC_INVALID_PARAM; | |||
| 522 | *arg = ctx->pbi->common.base_qindex; | |||
| 523 | return VPX_CODEC_OK; | |||
| 524 | } | |||
| 525 | ||||
| 526 | static vpx_codec_err_t ctrl_get_last_ref_updates(vpx_codec_alg_priv_t *ctx, | |||
| 527 | va_list args) { | |||
| 528 | int *const update_info = va_arg(args, int *)__builtin_va_arg(args, int *); | |||
| 529 | ||||
| 530 | if (update_info) { | |||
| 531 | if (ctx->pbi != NULL((void*)0)) { | |||
| 532 | *update_info = ctx->pbi->refresh_frame_flags; | |||
| 533 | return VPX_CODEC_OK; | |||
| 534 | } else { | |||
| 535 | return VPX_CODEC_ERROR; | |||
| 536 | } | |||
| 537 | } | |||
| 538 | ||||
| 539 | return VPX_CODEC_INVALID_PARAM; | |||
| 540 | } | |||
| 541 | ||||
| 542 | static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, | |||
| 543 | va_list args) { | |||
| 544 | int *corrupted = va_arg(args, int *)__builtin_va_arg(args, int *); | |||
| 545 | ||||
| 546 | if (corrupted) { | |||
| 547 | if (ctx->pbi != NULL((void*)0)) { | |||
| 548 | RefCntBuffer *const frame_bufs = ctx->pbi->common.buffer_pool->frame_bufs; | |||
| 549 | if (ctx->pbi->common.frame_to_show == NULL((void*)0)) return VPX_CODEC_ERROR; | |||
| 550 | if (ctx->last_show_frame >= 0) | |||
| 551 | *corrupted = frame_bufs[ctx->last_show_frame].buf.corrupted; | |||
| 552 | return VPX_CODEC_OK; | |||
| 553 | } else { | |||
| 554 | return VPX_CODEC_ERROR; | |||
| 555 | } | |||
| 556 | } | |||
| 557 | ||||
| 558 | return VPX_CODEC_INVALID_PARAM; | |||
| 559 | } | |||
| 560 | ||||
| 561 | static vpx_codec_err_t ctrl_get_frame_size(vpx_codec_alg_priv_t *ctx, | |||
| 562 | va_list args) { | |||
| 563 | int *const frame_size = va_arg(args, int *)__builtin_va_arg(args, int *); | |||
| 564 | ||||
| 565 | if (frame_size) { | |||
| 566 | if (ctx->pbi != NULL((void*)0)) { | |||
| 567 | const VP9_COMMON *const cm = &ctx->pbi->common; | |||
| 568 | frame_size[0] = cm->width; | |||
| 569 | frame_size[1] = cm->height; | |||
| 570 | return VPX_CODEC_OK; | |||
| 571 | } else { | |||
| 572 | return VPX_CODEC_ERROR; | |||
| 573 | } | |||
| 574 | } | |||
| 575 | ||||
| 576 | return VPX_CODEC_INVALID_PARAM; | |||
| 577 | } | |||
| 578 | ||||
| 579 | static vpx_codec_err_t ctrl_get_render_size(vpx_codec_alg_priv_t *ctx, | |||
| 580 | va_list args) { | |||
| 581 | int *const render_size = va_arg(args, int *)__builtin_va_arg(args, int *); | |||
| 582 | ||||
| 583 | if (render_size) { | |||
| 584 | if (ctx->pbi != NULL((void*)0)) { | |||
| 585 | const VP9_COMMON *const cm = &ctx->pbi->common; | |||
| 586 | render_size[0] = cm->render_width; | |||
| 587 | render_size[1] = cm->render_height; | |||
| 588 | return VPX_CODEC_OK; | |||
| 589 | } else { | |||
| 590 | return VPX_CODEC_ERROR; | |||
| 591 | } | |||
| 592 | } | |||
| 593 | ||||
| 594 | return VPX_CODEC_INVALID_PARAM; | |||
| 595 | } | |||
| 596 | ||||
| 597 | static vpx_codec_err_t ctrl_get_bit_depth(vpx_codec_alg_priv_t *ctx, | |||
| 598 | va_list args) { | |||
| 599 | unsigned int *const bit_depth = va_arg(args, unsigned int *)__builtin_va_arg(args, unsigned int *); | |||
| 600 | ||||
| 601 | if (bit_depth) { | |||
| 602 | if (ctx->pbi != NULL((void*)0)) { | |||
| 603 | const VP9_COMMON *const cm = &ctx->pbi->common; | |||
| 604 | *bit_depth = cm->bit_depth; | |||
| 605 | return VPX_CODEC_OK; | |||
| 606 | } else { | |||
| 607 | return VPX_CODEC_ERROR; | |||
| 608 | } | |||
| 609 | } | |||
| 610 | ||||
| 611 | return VPX_CODEC_INVALID_PARAM; | |||
| 612 | } | |||
| 613 | ||||
| 614 | static vpx_codec_err_t ctrl_set_invert_tile_order(vpx_codec_alg_priv_t *ctx, | |||
| 615 | va_list args) { | |||
| 616 | ctx->invert_tile_order = va_arg(args, int)__builtin_va_arg(args, int); | |||
| 617 | return VPX_CODEC_OK; | |||
| 618 | } | |||
| 619 | ||||
| 620 | static vpx_codec_err_t ctrl_set_decryptor(vpx_codec_alg_priv_t *ctx, | |||
| 621 | va_list args) { | |||
| 622 | vpx_decrypt_init *init = va_arg(args, vpx_decrypt_init *)__builtin_va_arg(args, vpx_decrypt_init *); | |||
| 623 | ctx->decrypt_cb = init ? init->decrypt_cb : NULL((void*)0); | |||
| 624 | ctx->decrypt_state = init ? init->decrypt_state : NULL((void*)0); | |||
| 625 | return VPX_CODEC_OK; | |||
| 626 | } | |||
| 627 | ||||
| 628 | static vpx_codec_err_t ctrl_set_byte_alignment(vpx_codec_alg_priv_t *ctx, | |||
| 629 | va_list args) { | |||
| 630 | const int legacy_byte_alignment = 0; | |||
| 631 | const int min_byte_alignment = 32; | |||
| 632 | const int max_byte_alignment = 1024; | |||
| 633 | const int byte_alignment = va_arg(args, int)__builtin_va_arg(args, int); | |||
| 634 | ||||
| 635 | if (byte_alignment != legacy_byte_alignment && | |||
| 636 | (byte_alignment < min_byte_alignment || | |||
| 637 | byte_alignment > max_byte_alignment || | |||
| 638 | (byte_alignment & (byte_alignment - 1)) != 0)) | |||
| 639 | return VPX_CODEC_INVALID_PARAM; | |||
| 640 | ||||
| 641 | ctx->byte_alignment = byte_alignment; | |||
| 642 | if (ctx->pbi != NULL((void*)0)) { | |||
| 643 | ctx->pbi->common.byte_alignment = byte_alignment; | |||
| 644 | } | |||
| 645 | return VPX_CODEC_OK; | |||
| 646 | } | |||
| 647 | ||||
| 648 | static vpx_codec_err_t ctrl_set_skip_loop_filter(vpx_codec_alg_priv_t *ctx, | |||
| 649 | va_list args) { | |||
| 650 | ctx->skip_loop_filter = va_arg(args, int)__builtin_va_arg(args, int); | |||
| 651 | ||||
| 652 | if (ctx->pbi != NULL((void*)0)) { | |||
| 653 | ctx->pbi->common.skip_loop_filter = ctx->skip_loop_filter; | |||
| 654 | } | |||
| 655 | ||||
| 656 | return VPX_CODEC_OK; | |||
| 657 | } | |||
| 658 | ||||
| 659 | static vpx_codec_err_t ctrl_set_spatial_layer_svc(vpx_codec_alg_priv_t *ctx, | |||
| 660 | va_list args) { | |||
| 661 | ctx->svc_decoding = 1; | |||
| 662 | ctx->svc_spatial_layer = va_arg(args, int)__builtin_va_arg(args, int); | |||
| 663 | if (ctx->svc_spatial_layer < 0) | |||
| 664 | return VPX_CODEC_INVALID_PARAM; | |||
| 665 | else | |||
| 666 | return VPX_CODEC_OK; | |||
| 667 | } | |||
| 668 | ||||
| 669 | static vpx_codec_err_t ctrl_set_row_mt(vpx_codec_alg_priv_t *ctx, | |||
| 670 | va_list args) { | |||
| 671 | ctx->row_mt = va_arg(args, int)__builtin_va_arg(args, int); | |||
| 672 | ||||
| 673 | return VPX_CODEC_OK; | |||
| 674 | } | |||
| 675 | ||||
| 676 | static vpx_codec_err_t ctrl_enable_lpf_opt(vpx_codec_alg_priv_t *ctx, | |||
| 677 | va_list args) { | |||
| 678 | ctx->lpf_opt = va_arg(args, int)__builtin_va_arg(args, int); | |||
| 679 | ||||
| 680 | return VPX_CODEC_OK; | |||
| 681 | } | |||
| 682 | ||||
| 683 | static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = { | |||
| 684 | { VP8_COPY_REFERENCE, ctrl_copy_reference }, | |||
| 685 | ||||
| 686 | // Setters | |||
| 687 | { VP8_SET_REFERENCE, ctrl_set_reference }, | |||
| 688 | { VP8_SET_POSTPROC, ctrl_set_postproc }, | |||
| 689 | { VP9_INVERT_TILE_DECODE_ORDER, ctrl_set_invert_tile_order }, | |||
| 690 | { VPXD_SET_DECRYPTOR, ctrl_set_decryptor }, | |||
| 691 | { VP9_SET_BYTE_ALIGNMENT, ctrl_set_byte_alignment }, | |||
| 692 | { VP9_SET_SKIP_LOOP_FILTER, ctrl_set_skip_loop_filter }, | |||
| 693 | { VP9_DECODE_SVC_SPATIAL_LAYER, ctrl_set_spatial_layer_svc }, | |||
| 694 | { VP9D_SET_ROW_MT, ctrl_set_row_mt }, | |||
| 695 | { VP9D_SET_LOOP_FILTER_OPT, ctrl_enable_lpf_opt }, | |||
| 696 | ||||
| 697 | // Getters | |||
| 698 | { VPXD_GET_LAST_QUANTIZER, ctrl_get_quantizer }, | |||
| 699 | { VP8D_GET_LAST_REF_UPDATES, ctrl_get_last_ref_updates }, | |||
| 700 | { VP8D_GET_FRAME_CORRUPTED, ctrl_get_frame_corrupted }, | |||
| 701 | { VP9_GET_REFERENCE, ctrl_get_reference }, | |||
| 702 | { VP9D_GET_DISPLAY_SIZE, ctrl_get_render_size }, | |||
| 703 | { VP9D_GET_BIT_DEPTH, ctrl_get_bit_depth }, | |||
| 704 | { VP9D_GET_FRAME_SIZE, ctrl_get_frame_size }, | |||
| 705 | ||||
| 706 | { -1, NULL((void*)0) }, | |||
| 707 | }; | |||
| 708 | ||||
| 709 | #ifndef VERSION_STRING" v1.15.2" | |||
| 710 | #define VERSION_STRING" v1.15.2" | |||
| 711 | #endif | |||
| 712 | CODEC_INTERFACE(vpx_codec_vp9_dx)vpx_codec_iface_t *vpx_codec_vp9_dx(void) { return &vpx_codec_vp9_dx_algo ; } vpx_codec_iface_t vpx_codec_vp9_dx_algo = { | |||
| 713 | "WebM Project VP9 Decoder" VERSION_STRING" v1.15.2", | |||
| 714 | VPX_CODEC_INTERNAL_ABI_VERSION(5), | |||
| 715 | #if CONFIG_VP9_HIGHBITDEPTH0 | |||
| 716 | VPX_CODEC_CAP_HIGHBITDEPTH0x4 | | |||
| 717 | #endif | |||
| 718 | VPX_CODEC_CAP_DECODER0x1 | VP9_CAP_POSTPROC(1 ? 0x40000 : 0) | | |||
| 719 | VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER0x400000, // vpx_codec_caps_t | |||
| 720 | decoder_init, // vpx_codec_init_fn_t | |||
| 721 | decoder_destroy, // vpx_codec_destroy_fn_t | |||
| 722 | decoder_ctrl_maps, // vpx_codec_ctrl_fn_map_t | |||
| 723 | { | |||
| 724 | // NOLINT | |||
| 725 | decoder_peek_si, // vpx_codec_peek_si_fn_t | |||
| 726 | decoder_get_si, // vpx_codec_get_si_fn_t | |||
| 727 | decoder_decode, // vpx_codec_decode_fn_t | |||
| 728 | decoder_get_frame, // vpx_codec_frame_get_fn_t | |||
| 729 | decoder_set_fb_fn, // vpx_codec_set_fb_fn_t | |||
| 730 | }, | |||
| 731 | { | |||
| 732 | // NOLINT | |||
| 733 | 0, | |||
| 734 | NULL((void*)0), // vpx_codec_enc_cfg_map_t | |||
| 735 | NULL((void*)0), // vpx_codec_encode_fn_t | |||
| 736 | NULL((void*)0), // vpx_codec_get_cx_data_fn_t | |||
| 737 | NULL((void*)0), // vpx_codec_enc_config_set_fn_t | |||
| 738 | NULL((void*)0), // vpx_codec_get_global_headers_fn_t | |||
| 739 | NULL((void*)0), // vpx_codec_get_preview_frame_fn_t | |||
| 740 | NULL((void*)0), // vpx_codec_enc_mr_get_mem_loc_fn_t | |||
| 741 | NULL((void*)0) // vpx_codec_enc_mr_free_mem_loc_fn_t | |||
| 742 | } | |||
| 743 | }; |