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