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#include <stdlib.h> 13#include <string.h> 14#include "./vp8_rtcd.h" 15#include "./vpx_dsp_rtcd.h" 16#include "./vpx_scale_rtcd.h" 17#include "vpx/vpx_decoder.h" 18#include "vpx/vp8dx.h" 19#include "vpx/internal/vpx_codec_internal.h" 20#include "vpx_version.h" 21#include "common/alloccommon.h" 22#include "common/common.h" 23#include "common/onyxd.h" 24#include "decoder/onyxd_int.h" 25#include "vpx_dsp/vpx_dsp_common.h" 26#include "vpx_mem/vpx_mem.h" 27#if CONFIG_ERROR_CONCEALMENT 28#include "decoder/error_concealment.h" 29#endif 30#include "decoder/decoderthreading.h" 31 32#define VP8_CAP_POSTPROC (CONFIG_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0) 33#define VP8_CAP_ERROR_CONCEALMENT (CONFIG_ERROR_CONCEALMENT ? \ 34 VPX_CODEC_CAP_ERROR_CONCEALMENT : 0) 35 36typedef vpx_codec_stream_info_t vp8_stream_info_t; 37 38/* Structures for handling memory allocations */ 39typedef enum 40{ 41 VP8_SEG_ALG_PRIV = 256, 42 VP8_SEG_MAX 43} mem_seg_id_t; 44#define NELEMENTS(x) ((int)(sizeof(x)/sizeof(x[0]))) 45 46struct vpx_codec_alg_priv 47{ 48 vpx_codec_priv_t base; 49 vpx_codec_dec_cfg_t cfg; 50 vp8_stream_info_t si; 51 int decoder_init; 52 int postproc_cfg_set; 53 vp8_postproc_cfg_t postproc_cfg; 54#if CONFIG_POSTPROC_VISUALIZER 55 unsigned int dbg_postproc_flag; 56 int dbg_color_ref_frame_flag; 57 int dbg_color_mb_modes_flag; 58 int dbg_color_b_modes_flag; 59 int dbg_display_mv_flag; 60#endif 61 vpx_decrypt_cb decrypt_cb; 62 void *decrypt_state; 63 vpx_image_t img; 64 int img_setup; 65 struct frame_buffers yv12_frame_buffers; 66 void *user_priv; 67 FRAGMENT_DATA fragments; 68}; 69 70static void vp8_init_ctx(vpx_codec_ctx_t *ctx) 71{ 72 vpx_codec_alg_priv_t *priv = 73 (vpx_codec_alg_priv_t *)vpx_calloc(1, sizeof(*priv)); 74 75 ctx->priv = (vpx_codec_priv_t *)priv; 76 ctx->priv->init_flags = ctx->init_flags; 77 78 priv->si.sz = sizeof(priv->si); 79 priv->decrypt_cb = NULL; 80 priv->decrypt_state = NULL; 81 82 if (ctx->config.dec) 83 { 84 /* Update the reference to the config structure to an internal copy. */ 85 priv->cfg = *ctx->config.dec; 86 ctx->config.dec = &priv->cfg; 87 } 88} 89 90static vpx_codec_err_t vp8_init(vpx_codec_ctx_t *ctx, 91 vpx_codec_priv_enc_mr_cfg_t *data) 92{ 93 vpx_codec_err_t res = VPX_CODEC_OK; 94 vpx_codec_alg_priv_t *priv = NULL; 95 (void) data; 96 97 vp8_rtcd(); 98 vpx_dsp_rtcd(); 99 vpx_scale_rtcd(); 100 101 /* This function only allocates space for the vpx_codec_alg_priv_t 102 * structure. More memory may be required at the time the stream 103 * information becomes known. 104 */ 105 if (!ctx->priv) { 106 vp8_init_ctx(ctx); 107 priv = (vpx_codec_alg_priv_t *)ctx->priv; 108 109 /* initialize number of fragments to zero */ 110 priv->fragments.count = 0; 111 /* is input fragments enabled? */ 112 priv->fragments.enabled = 113 (priv->base.init_flags & VPX_CODEC_USE_INPUT_FRAGMENTS); 114 115 /*post processing level initialized to do nothing */ 116 } else { 117 priv = (vpx_codec_alg_priv_t *)ctx->priv; 118 } 119 120 priv->yv12_frame_buffers.use_frame_threads = 121 (ctx->priv->init_flags & VPX_CODEC_USE_FRAME_THREADING); 122 123 /* for now, disable frame threading */ 124 priv->yv12_frame_buffers.use_frame_threads = 0; 125 126 if (priv->yv12_frame_buffers.use_frame_threads && 127 ((ctx->priv->init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT) || 128 (ctx->priv->init_flags & VPX_CODEC_USE_INPUT_FRAGMENTS))) { 129 /* row-based threading, error concealment, and input fragments will 130 * not be supported when using frame-based threading */ 131 res = VPX_CODEC_INVALID_PARAM; 132 } 133 134 return res; 135} 136 137static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx) 138{ 139 vp8_remove_decoder_instances(&ctx->yv12_frame_buffers); 140 141 vpx_free(ctx); 142 143 return VPX_CODEC_OK; 144} 145 146static vpx_codec_err_t vp8_peek_si_internal(const uint8_t *data, 147 unsigned int data_sz, 148 vpx_codec_stream_info_t *si, 149 vpx_decrypt_cb decrypt_cb, 150 void *decrypt_state) 151{ 152 vpx_codec_err_t res = VPX_CODEC_OK; 153 154 if(data + data_sz <= data) 155 { 156 res = VPX_CODEC_INVALID_PARAM; 157 } 158 else 159 { 160 /* Parse uncompresssed part of key frame header. 161 * 3 bytes:- including version, frame type and an offset 162 * 3 bytes:- sync code (0x9d, 0x01, 0x2a) 163 * 4 bytes:- including image width and height in the lowest 14 bits 164 * of each 2-byte value. 165 */ 166 uint8_t clear_buffer[10]; 167 const uint8_t *clear = data; 168 if (decrypt_cb) 169 { 170 int n = VPXMIN(sizeof(clear_buffer), data_sz); 171 decrypt_cb(decrypt_state, data, clear_buffer, n); 172 clear = clear_buffer; 173 } 174 si->is_kf = 0; 175 176 if (data_sz >= 10 && !(clear[0] & 0x01)) /* I-Frame */ 177 { 178 si->is_kf = 1; 179 180 /* vet via sync code */ 181 if (clear[3] != 0x9d || clear[4] != 0x01 || clear[5] != 0x2a) 182 return VPX_CODEC_UNSUP_BITSTREAM; 183 184 si->w = (clear[6] | (clear[7] << 8)) & 0x3fff; 185 si->h = (clear[8] | (clear[9] << 8)) & 0x3fff; 186 187 /*printf("w=%d, h=%d\n", si->w, si->h);*/ 188 if (!(si->h | si->w)) 189 res = VPX_CODEC_UNSUP_BITSTREAM; 190 } 191 else 192 { 193 res = VPX_CODEC_UNSUP_BITSTREAM; 194 } 195 } 196 197 return res; 198} 199 200static vpx_codec_err_t vp8_peek_si(const uint8_t *data, 201 unsigned int data_sz, 202 vpx_codec_stream_info_t *si) { 203 return vp8_peek_si_internal(data, data_sz, si, NULL, NULL); 204} 205 206static vpx_codec_err_t vp8_get_si(vpx_codec_alg_priv_t *ctx, 207 vpx_codec_stream_info_t *si) 208{ 209 210 unsigned int sz; 211 212 if (si->sz >= sizeof(vp8_stream_info_t)) 213 sz = sizeof(vp8_stream_info_t); 214 else 215 sz = sizeof(vpx_codec_stream_info_t); 216 217 memcpy(si, &ctx->si, sz); 218 si->sz = sz; 219 220 return VPX_CODEC_OK; 221} 222 223 224static vpx_codec_err_t 225update_error_state(vpx_codec_alg_priv_t *ctx, 226 const struct vpx_internal_error_info *error) 227{ 228 vpx_codec_err_t res; 229 230 if ((res = error->error_code)) 231 ctx->base.err_detail = error->has_detail 232 ? error->detail 233 : NULL; 234 235 return res; 236} 237 238static void yuvconfig2image(vpx_image_t *img, 239 const YV12_BUFFER_CONFIG *yv12, 240 void *user_priv) 241{ 242 /** vpx_img_wrap() doesn't allow specifying independent strides for 243 * the Y, U, and V planes, nor other alignment adjustments that 244 * might be representable by a YV12_BUFFER_CONFIG, so we just 245 * initialize all the fields.*/ 246 img->fmt = VPX_IMG_FMT_I420; 247 img->w = yv12->y_stride; 248 img->h = (yv12->y_height + 2 * VP8BORDERINPIXELS + 15) & ~15; 249 img->d_w = img->r_w = yv12->y_width; 250 img->d_h = img->r_h = yv12->y_height; 251 img->x_chroma_shift = 1; 252 img->y_chroma_shift = 1; 253 img->planes[VPX_PLANE_Y] = yv12->y_buffer; 254 img->planes[VPX_PLANE_U] = yv12->u_buffer; 255 img->planes[VPX_PLANE_V] = yv12->v_buffer; 256 img->planes[VPX_PLANE_ALPHA] = NULL; 257 img->stride[VPX_PLANE_Y] = yv12->y_stride; 258 img->stride[VPX_PLANE_U] = yv12->uv_stride; 259 img->stride[VPX_PLANE_V] = yv12->uv_stride; 260 img->stride[VPX_PLANE_ALPHA] = yv12->y_stride; 261 img->bit_depth = 8; 262 img->bps = 12; 263 img->user_priv = user_priv; 264 img->img_data = yv12->buffer_alloc; 265 img->img_data_owner = 0; 266 img->self_allocd = 0; 267} 268 269static int 270update_fragments(vpx_codec_alg_priv_t *ctx, 271 const uint8_t *data, 272 unsigned int data_sz, 273 vpx_codec_err_t *res) 274{ 275 *res = VPX_CODEC_OK; 276 277 if (ctx->fragments.count == 0) 278 { 279 /* New frame, reset fragment pointers and sizes */ 280 memset((void*)ctx->fragments.ptrs, 0, sizeof(ctx->fragments.ptrs)); 281 memset(ctx->fragments.sizes, 0, sizeof(ctx->fragments.sizes)); 282 } 283 if (ctx->fragments.enabled && !(data == NULL && data_sz == 0)) 284 { 285 /* Store a pointer to this fragment and return. We haven't 286 * received the complete frame yet, so we will wait with decoding. 287 */ 288 ctx->fragments.ptrs[ctx->fragments.count] = data; 289 ctx->fragments.sizes[ctx->fragments.count] = data_sz; 290 ctx->fragments.count++; 291 if (ctx->fragments.count > (1 << EIGHT_PARTITION) + 1) 292 { 293 ctx->fragments.count = 0; 294 *res = VPX_CODEC_INVALID_PARAM; 295 return -1; 296 } 297 return 0; 298 } 299 300 if (!ctx->fragments.enabled && (data == NULL && data_sz == 0)) 301 { 302 return 0; 303 } 304 305 if (!ctx->fragments.enabled) 306 { 307 ctx->fragments.ptrs[0] = data; 308 ctx->fragments.sizes[0] = data_sz; 309 ctx->fragments.count = 1; 310 } 311 312 return 1; 313} 314 315static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, 316 const uint8_t *data, 317 unsigned int data_sz, 318 void *user_priv, 319 long deadline) 320{ 321 vpx_codec_err_t res = VPX_CODEC_OK; 322 unsigned int resolution_change = 0; 323 unsigned int w, h; 324 325 if (!ctx->fragments.enabled && (data == NULL && data_sz == 0)) 326 { 327 return 0; 328 } 329 330 /* Update the input fragment data */ 331 if(update_fragments(ctx, data, data_sz, &res) <= 0) 332 return res; 333 334 /* Determine the stream parameters. Note that we rely on peek_si to 335 * validate that we have a buffer that does not wrap around the top 336 * of the heap. 337 */ 338 w = ctx->si.w; 339 h = ctx->si.h; 340 341 res = vp8_peek_si_internal(ctx->fragments.ptrs[0], ctx->fragments.sizes[0], 342 &ctx->si, ctx->decrypt_cb, ctx->decrypt_state); 343 344 if((res == VPX_CODEC_UNSUP_BITSTREAM) && !ctx->si.is_kf) 345 { 346 /* the peek function returns an error for non keyframes, however for 347 * this case, it is not an error */ 348 res = VPX_CODEC_OK; 349 } 350 351 if(!ctx->decoder_init && !ctx->si.is_kf) 352 res = VPX_CODEC_UNSUP_BITSTREAM; 353 354 if ((ctx->si.h != h) || (ctx->si.w != w)) 355 resolution_change = 1; 356 357 /* Initialize the decoder instance on the first frame*/ 358 if (!res && !ctx->decoder_init) 359 { 360 VP8D_CONFIG oxcf; 361 362 oxcf.Width = ctx->si.w; 363 oxcf.Height = ctx->si.h; 364 oxcf.Version = 9; 365 oxcf.postprocess = 0; 366 oxcf.max_threads = ctx->cfg.threads; 367 oxcf.error_concealment = 368 (ctx->base.init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT); 369 370 /* If postprocessing was enabled by the application and a 371 * configuration has not been provided, default it. 372 */ 373 if (!ctx->postproc_cfg_set 374 && (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)) { 375 ctx->postproc_cfg.post_proc_flag = 376 VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE; 377 ctx->postproc_cfg.deblocking_level = 4; 378 ctx->postproc_cfg.noise_level = 0; 379 } 380 381 res = vp8_create_decoder_instances(&ctx->yv12_frame_buffers, &oxcf); 382 ctx->decoder_init = 1; 383 } 384 385 /* Set these even if already initialized. The caller may have changed the 386 * decrypt config between frames. 387 */ 388 if (ctx->decoder_init) { 389 ctx->yv12_frame_buffers.pbi[0]->decrypt_cb = ctx->decrypt_cb; 390 ctx->yv12_frame_buffers.pbi[0]->decrypt_state = ctx->decrypt_state; 391 } 392 393 if (!res) 394 { 395 VP8D_COMP *pbi = ctx->yv12_frame_buffers.pbi[0]; 396 if (resolution_change) 397 { 398 VP8_COMMON *const pc = & pbi->common; 399 MACROBLOCKD *const xd = & pbi->mb; 400#if CONFIG_MULTITHREAD 401 int i; 402#endif 403 pc->Width = ctx->si.w; 404 pc->Height = ctx->si.h; 405 { 406 int prev_mb_rows = pc->mb_rows; 407 408 if (setjmp(pbi->common.error.jmp)) 409 { 410 pbi->common.error.setjmp = 0; 411 vp8_clear_system_state(); 412 /* same return value as used in vp8dx_receive_compressed_data */ 413 return -1; 414 } 415 416 pbi->common.error.setjmp = 1; 417 418 if (pc->Width <= 0) 419 { 420 pc->Width = w; 421 vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, 422 "Invalid frame width"); 423 } 424 425 if (pc->Height <= 0) 426 { 427 pc->Height = h; 428 vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, 429 "Invalid frame height"); 430 } 431 432 if (vp8_alloc_frame_buffers(pc, pc->Width, pc->Height)) 433 vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, 434 "Failed to allocate frame buffers"); 435 436 xd->pre = pc->yv12_fb[pc->lst_fb_idx]; 437 xd->dst = pc->yv12_fb[pc->new_fb_idx]; 438 439#if CONFIG_MULTITHREAD 440 for (i = 0; i < pbi->allocated_decoding_thread_count; i++) 441 { 442 pbi->mb_row_di[i].mbd.dst = pc->yv12_fb[pc->new_fb_idx]; 443 vp8_build_block_doffsets(&pbi->mb_row_di[i].mbd); 444 } 445#endif 446 vp8_build_block_doffsets(&pbi->mb); 447 448 /* allocate memory for last frame MODE_INFO array */ 449#if CONFIG_ERROR_CONCEALMENT 450 451 if (pbi->ec_enabled) 452 { 453 /* old prev_mip was released by vp8_de_alloc_frame_buffers() 454 * called in vp8_alloc_frame_buffers() */ 455 pc->prev_mip = vpx_calloc( 456 (pc->mb_cols + 1) * (pc->mb_rows + 1), 457 sizeof(MODE_INFO)); 458 459 if (!pc->prev_mip) 460 { 461 vp8_de_alloc_frame_buffers(pc); 462 vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, 463 "Failed to allocate" 464 "last frame MODE_INFO array"); 465 } 466 467 pc->prev_mi = pc->prev_mip + pc->mode_info_stride + 1; 468 469 if (vp8_alloc_overlap_lists(pbi)) 470 vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, 471 "Failed to allocate overlap lists " 472 "for error concealment"); 473 } 474 475#endif 476 477#if CONFIG_MULTITHREAD 478 if (pbi->b_multithreaded_rd) 479 vp8mt_alloc_temp_buffers(pbi, pc->Width, prev_mb_rows); 480#else 481 (void)prev_mb_rows; 482#endif 483 } 484 485 pbi->common.error.setjmp = 0; 486 487 /* required to get past the first get_free_fb() call */ 488 pbi->common.fb_idx_ref_cnt[0] = 0; 489 } 490 491 /* update the pbi fragment data */ 492 pbi->fragments = ctx->fragments; 493 494 ctx->user_priv = user_priv; 495 if (vp8dx_receive_compressed_data(pbi, data_sz, data, deadline)) 496 { 497 res = update_error_state(ctx, &pbi->common.error); 498 } 499 500 /* get ready for the next series of fragments */ 501 ctx->fragments.count = 0; 502 } 503 504 return res; 505} 506 507static vpx_image_t *vp8_get_frame(vpx_codec_alg_priv_t *ctx, 508 vpx_codec_iter_t *iter) 509{ 510 vpx_image_t *img = NULL; 511 512 /* iter acts as a flip flop, so an image is only returned on the first 513 * call to get_frame. 514 */ 515 if (!(*iter) && ctx->yv12_frame_buffers.pbi[0]) 516 { 517 YV12_BUFFER_CONFIG sd; 518 int64_t time_stamp = 0, time_end_stamp = 0; 519 vp8_ppflags_t flags = {0}; 520 521 if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) 522 { 523 flags.post_proc_flag= ctx->postproc_cfg.post_proc_flag 524#if CONFIG_POSTPROC_VISUALIZER 525 526 | ((ctx->dbg_color_ref_frame_flag != 0) ? VP8D_DEBUG_CLR_FRM_REF_BLKS : 0) 527 | ((ctx->dbg_color_mb_modes_flag != 0) ? VP8D_DEBUG_CLR_BLK_MODES : 0) 528 | ((ctx->dbg_color_b_modes_flag != 0) ? VP8D_DEBUG_CLR_BLK_MODES : 0) 529 | ((ctx->dbg_display_mv_flag != 0) ? VP8D_DEBUG_DRAW_MV : 0) 530#endif 531 ; 532 flags.deblocking_level = ctx->postproc_cfg.deblocking_level; 533 flags.noise_level = ctx->postproc_cfg.noise_level; 534#if CONFIG_POSTPROC_VISUALIZER 535 flags.display_ref_frame_flag= ctx->dbg_color_ref_frame_flag; 536 flags.display_mb_modes_flag = ctx->dbg_color_mb_modes_flag; 537 flags.display_b_modes_flag = ctx->dbg_color_b_modes_flag; 538 flags.display_mv_flag = ctx->dbg_display_mv_flag; 539#endif 540 } 541 542 if (0 == vp8dx_get_raw_frame(ctx->yv12_frame_buffers.pbi[0], &sd, 543 &time_stamp, &time_end_stamp, &flags)) 544 { 545 yuvconfig2image(&ctx->img, &sd, ctx->user_priv); 546 547 img = &ctx->img; 548 *iter = img; 549 } 550 } 551 552 return img; 553} 554 555static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, 556 YV12_BUFFER_CONFIG *yv12) 557{ 558 const int y_w = img->d_w; 559 const int y_h = img->d_h; 560 const int uv_w = (img->d_w + 1) / 2; 561 const int uv_h = (img->d_h + 1) / 2; 562 vpx_codec_err_t res = VPX_CODEC_OK; 563 yv12->y_buffer = img->planes[VPX_PLANE_Y]; 564 yv12->u_buffer = img->planes[VPX_PLANE_U]; 565 yv12->v_buffer = img->planes[VPX_PLANE_V]; 566 567 yv12->y_crop_width = y_w; 568 yv12->y_crop_height = y_h; 569 yv12->y_width = y_w; 570 yv12->y_height = y_h; 571 yv12->uv_crop_width = uv_w; 572 yv12->uv_crop_height = uv_h; 573 yv12->uv_width = uv_w; 574 yv12->uv_height = uv_h; 575 576 yv12->y_stride = img->stride[VPX_PLANE_Y]; 577 yv12->uv_stride = img->stride[VPX_PLANE_U]; 578 579 yv12->border = (img->stride[VPX_PLANE_Y] - img->d_w) / 2; 580 return res; 581} 582 583 584static vpx_codec_err_t vp8_set_reference(vpx_codec_alg_priv_t *ctx, 585 va_list args) 586{ 587 588 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 589 590 if (data && !ctx->yv12_frame_buffers.use_frame_threads) 591 { 592 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 593 YV12_BUFFER_CONFIG sd; 594 595 image2yuvconfig(&frame->img, &sd); 596 597 return vp8dx_set_reference(ctx->yv12_frame_buffers.pbi[0], 598 frame->frame_type, &sd); 599 } 600 else 601 return VPX_CODEC_INVALID_PARAM; 602 603} 604 605static vpx_codec_err_t vp8_get_reference(vpx_codec_alg_priv_t *ctx, 606 va_list args) 607{ 608 609 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 610 611 if (data && !ctx->yv12_frame_buffers.use_frame_threads) 612 { 613 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 614 YV12_BUFFER_CONFIG sd; 615 616 image2yuvconfig(&frame->img, &sd); 617 618 return vp8dx_get_reference(ctx->yv12_frame_buffers.pbi[0], 619 frame->frame_type, &sd); 620 } 621 else 622 return VPX_CODEC_INVALID_PARAM; 623 624} 625 626static vpx_codec_err_t vp8_set_postproc(vpx_codec_alg_priv_t *ctx, 627 va_list args) 628{ 629#if CONFIG_POSTPROC 630 vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *); 631 632 if (data) 633 { 634 ctx->postproc_cfg_set = 1; 635 ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data); 636 return VPX_CODEC_OK; 637 } 638 else 639 return VPX_CODEC_INVALID_PARAM; 640 641#else 642 (void)ctx; 643 (void)args; 644 return VPX_CODEC_INCAPABLE; 645#endif 646} 647 648 649static vpx_codec_err_t vp8_set_dbg_color_ref_frame(vpx_codec_alg_priv_t *ctx, 650 va_list args) { 651#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC 652 ctx->dbg_color_ref_frame_flag = va_arg(args, int); 653 return VPX_CODEC_OK; 654#else 655 (void)ctx; 656 (void)args; 657 return VPX_CODEC_INCAPABLE; 658#endif 659} 660 661static vpx_codec_err_t vp8_set_dbg_color_mb_modes(vpx_codec_alg_priv_t *ctx, 662 va_list args) { 663#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC 664 ctx->dbg_color_mb_modes_flag = va_arg(args, int); 665 return VPX_CODEC_OK; 666#else 667 (void)ctx; 668 (void)args; 669 return VPX_CODEC_INCAPABLE; 670#endif 671} 672 673static vpx_codec_err_t vp8_set_dbg_color_b_modes(vpx_codec_alg_priv_t *ctx, 674 va_list args) { 675#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC 676 ctx->dbg_color_b_modes_flag = va_arg(args, int); 677 return VPX_CODEC_OK; 678#else 679 (void)ctx; 680 (void)args; 681 return VPX_CODEC_INCAPABLE; 682#endif 683} 684 685static vpx_codec_err_t vp8_set_dbg_display_mv(vpx_codec_alg_priv_t *ctx, 686 va_list args) { 687#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC 688 ctx->dbg_display_mv_flag = va_arg(args, int); 689 return VPX_CODEC_OK; 690#else 691 (void)ctx; 692 (void)args; 693 return VPX_CODEC_INCAPABLE; 694#endif 695} 696 697static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx, 698 va_list args) 699{ 700 int *update_info = va_arg(args, int *); 701 702 if (update_info && !ctx->yv12_frame_buffers.use_frame_threads) 703 { 704 VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; 705 706 *update_info = pbi->common.refresh_alt_ref_frame * (int) VP8_ALTR_FRAME 707 + pbi->common.refresh_golden_frame * (int) VP8_GOLD_FRAME 708 + pbi->common.refresh_last_frame * (int) VP8_LAST_FRAME; 709 710 return VPX_CODEC_OK; 711 } 712 else 713 return VPX_CODEC_INVALID_PARAM; 714} 715 716extern int vp8dx_references_buffer( VP8_COMMON *oci, int ref_frame ); 717static vpx_codec_err_t vp8_get_last_ref_frame(vpx_codec_alg_priv_t *ctx, 718 va_list args) 719{ 720 int *ref_info = va_arg(args, int *); 721 722 if (ref_info && !ctx->yv12_frame_buffers.use_frame_threads) 723 { 724 VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; 725 VP8_COMMON *oci = &pbi->common; 726 *ref_info = 727 (vp8dx_references_buffer( oci, ALTREF_FRAME )?VP8_ALTR_FRAME:0) | 728 (vp8dx_references_buffer( oci, GOLDEN_FRAME )?VP8_GOLD_FRAME:0) | 729 (vp8dx_references_buffer( oci, LAST_FRAME )?VP8_LAST_FRAME:0); 730 731 return VPX_CODEC_OK; 732 } 733 else 734 return VPX_CODEC_INVALID_PARAM; 735} 736 737static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, 738 va_list args) 739{ 740 741 int *corrupted = va_arg(args, int *); 742 VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; 743 744 if (corrupted && pbi) 745 { 746 const YV12_BUFFER_CONFIG *const frame = pbi->common.frame_to_show; 747 if (frame == NULL) return VPX_CODEC_ERROR; 748 *corrupted = frame->corrupted; 749 return VPX_CODEC_OK; 750 } 751 else 752 return VPX_CODEC_INVALID_PARAM; 753 754} 755 756static vpx_codec_err_t vp8_set_decryptor(vpx_codec_alg_priv_t *ctx, 757 va_list args) 758{ 759 vpx_decrypt_init *init = va_arg(args, vpx_decrypt_init *); 760 761 if (init) 762 { 763 ctx->decrypt_cb = init->decrypt_cb; 764 ctx->decrypt_state = init->decrypt_state; 765 } 766 else 767 { 768 ctx->decrypt_cb = NULL; 769 ctx->decrypt_state = NULL; 770 } 771 return VPX_CODEC_OK; 772} 773 774vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] = 775{ 776 {VP8_SET_REFERENCE, vp8_set_reference}, 777 {VP8_COPY_REFERENCE, vp8_get_reference}, 778 {VP8_SET_POSTPROC, vp8_set_postproc}, 779 {VP8_SET_DBG_COLOR_REF_FRAME, vp8_set_dbg_color_ref_frame}, 780 {VP8_SET_DBG_COLOR_MB_MODES, vp8_set_dbg_color_mb_modes}, 781 {VP8_SET_DBG_COLOR_B_MODES, vp8_set_dbg_color_b_modes}, 782 {VP8_SET_DBG_DISPLAY_MV, vp8_set_dbg_display_mv}, 783 {VP8D_GET_LAST_REF_UPDATES, vp8_get_last_ref_updates}, 784 {VP8D_GET_FRAME_CORRUPTED, vp8_get_frame_corrupted}, 785 {VP8D_GET_LAST_REF_USED, vp8_get_last_ref_frame}, 786 {VPXD_SET_DECRYPTOR, vp8_set_decryptor}, 787 { -1, NULL}, 788}; 789 790 791#ifndef VERSION_STRING 792#define VERSION_STRING 793#endif 794CODEC_INTERFACE(vpx_codec_vp8_dx) = 795{ 796 "WebM Project VP8 Decoder" VERSION_STRING, 797 VPX_CODEC_INTERNAL_ABI_VERSION, 798 VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC | VP8_CAP_ERROR_CONCEALMENT | 799 VPX_CODEC_CAP_INPUT_FRAGMENTS, 800 /* vpx_codec_caps_t caps; */ 801 vp8_init, /* vpx_codec_init_fn_t init; */ 802 vp8_destroy, /* vpx_codec_destroy_fn_t destroy; */ 803 vp8_ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */ 804 { 805 vp8_peek_si, /* vpx_codec_peek_si_fn_t peek_si; */ 806 vp8_get_si, /* vpx_codec_get_si_fn_t get_si; */ 807 vp8_decode, /* vpx_codec_decode_fn_t decode; */ 808 vp8_get_frame, /* vpx_codec_frame_get_fn_t frame_get; */ 809 NULL, 810 }, 811 { /* encoder functions */ 812 0, 813 NULL, 814 NULL, 815 NULL, 816 NULL, 817 NULL, 818 NULL 819 } 820}; 821