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 32 typedef vpx_codec_stream_info_t vp8_stream_info_t; 33 34 /* Structures for handling memory allocations */ 35 typedef 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 42 static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t); 43 44 static 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 50 struct 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 76 static 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 87 static 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 113 static void vp8_finalize_mmaps(vpx_codec_alg_priv_t *ctx) 114 { 115 /* nothing to clean up */ 116 } 117 118 static 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 176 static 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 191 static 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 245 static 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 251 static 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 269 static vpx_codec_err_t 270 update_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 283 static 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 313 static int 314 update_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 354 static 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 573 static 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 622 static 623 vpx_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 660 static 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 704 static 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 727 static 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 749 static 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 771 static 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 792 static 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 815 static 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 835 extern int vp8dx_references_buffer( VP8_COMMON *oci, int ref_frame ); 836 static 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 857 static 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 876 static 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 895 vpx_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 915 CODEC_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