1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libvpx/vp8/vp8_dx_iface.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,941 @@ 1.4 +/* 1.5 + * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license 1.8 + * that can be found in the LICENSE file in the root of the source 1.9 + * tree. An additional intellectual property rights grant can be found 1.10 + * in the file PATENTS. All contributing project authors may 1.11 + * be found in the AUTHORS file in the root of the source tree. 1.12 + */ 1.13 + 1.14 + 1.15 +#include <stdlib.h> 1.16 +#include <string.h> 1.17 +#include "vp8_rtcd.h" 1.18 +#include "vpx/vpx_decoder.h" 1.19 +#include "vpx/vp8dx.h" 1.20 +#include "vpx/internal/vpx_codec_internal.h" 1.21 +#include "vpx_version.h" 1.22 +#include "common/onyxd.h" 1.23 +#include "decoder/onyxd_int.h" 1.24 +#include "common/alloccommon.h" 1.25 +#include "vpx_mem/vpx_mem.h" 1.26 +#if CONFIG_ERROR_CONCEALMENT 1.27 +#include "decoder/error_concealment.h" 1.28 +#endif 1.29 +#include "decoder/decoderthreading.h" 1.30 + 1.31 +#define VP8_CAP_POSTPROC (CONFIG_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0) 1.32 +#define VP8_CAP_ERROR_CONCEALMENT (CONFIG_ERROR_CONCEALMENT ? \ 1.33 + VPX_CODEC_CAP_ERROR_CONCEALMENT : 0) 1.34 + 1.35 +typedef vpx_codec_stream_info_t vp8_stream_info_t; 1.36 + 1.37 +/* Structures for handling memory allocations */ 1.38 +typedef enum 1.39 +{ 1.40 + VP8_SEG_ALG_PRIV = 256, 1.41 + VP8_SEG_MAX 1.42 +} mem_seg_id_t; 1.43 +#define NELEMENTS(x) ((int)(sizeof(x)/sizeof(x[0]))) 1.44 + 1.45 +static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t); 1.46 + 1.47 +static const mem_req_t vp8_mem_req_segs[] = 1.48 +{ 1.49 + {VP8_SEG_ALG_PRIV, 0, 8, VPX_CODEC_MEM_ZERO, vp8_priv_sz}, 1.50 + {VP8_SEG_MAX, 0, 0, 0, NULL} 1.51 +}; 1.52 + 1.53 +struct vpx_codec_alg_priv 1.54 +{ 1.55 + vpx_codec_priv_t base; 1.56 + vpx_codec_mmap_t mmaps[NELEMENTS(vp8_mem_req_segs)-1]; 1.57 + vpx_codec_dec_cfg_t cfg; 1.58 + vp8_stream_info_t si; 1.59 + int defer_alloc; 1.60 + int decoder_init; 1.61 + int postproc_cfg_set; 1.62 + vp8_postproc_cfg_t postproc_cfg; 1.63 +#if CONFIG_POSTPROC_VISUALIZER 1.64 + unsigned int dbg_postproc_flag; 1.65 + int dbg_color_ref_frame_flag; 1.66 + int dbg_color_mb_modes_flag; 1.67 + int dbg_color_b_modes_flag; 1.68 + int dbg_display_mv_flag; 1.69 +#endif 1.70 + vp8_decrypt_cb *decrypt_cb; 1.71 + void *decrypt_state; 1.72 + vpx_image_t img; 1.73 + int img_setup; 1.74 + struct frame_buffers yv12_frame_buffers; 1.75 + void *user_priv; 1.76 + FRAGMENT_DATA fragments; 1.77 +}; 1.78 + 1.79 +static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t flags) 1.80 +{ 1.81 + /* Although this declaration is constant, we can't use it in the requested 1.82 + * segments list because we want to define the requested segments list 1.83 + * before defining the private type (so that the number of memory maps is 1.84 + * known) 1.85 + */ 1.86 + (void)si; 1.87 + return sizeof(vpx_codec_alg_priv_t); 1.88 +} 1.89 + 1.90 +static void vp8_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap) 1.91 +{ 1.92 + int i; 1.93 + 1.94 + ctx->priv = mmap->base; 1.95 + ctx->priv->sz = sizeof(*ctx->priv); 1.96 + ctx->priv->iface = ctx->iface; 1.97 + ctx->priv->alg_priv = mmap->base; 1.98 + 1.99 + for (i = 0; i < NELEMENTS(ctx->priv->alg_priv->mmaps); i++) 1.100 + ctx->priv->alg_priv->mmaps[i].id = vp8_mem_req_segs[i].id; 1.101 + 1.102 + ctx->priv->alg_priv->mmaps[0] = *mmap; 1.103 + ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si); 1.104 + ctx->priv->alg_priv->decrypt_cb = NULL; 1.105 + ctx->priv->alg_priv->decrypt_state = NULL; 1.106 + ctx->priv->init_flags = ctx->init_flags; 1.107 + 1.108 + if (ctx->config.dec) 1.109 + { 1.110 + /* Update the reference to the config structure to an internal copy. */ 1.111 + ctx->priv->alg_priv->cfg = *ctx->config.dec; 1.112 + ctx->config.dec = &ctx->priv->alg_priv->cfg; 1.113 + } 1.114 +} 1.115 + 1.116 +static void vp8_finalize_mmaps(vpx_codec_alg_priv_t *ctx) 1.117 +{ 1.118 + /* nothing to clean up */ 1.119 +} 1.120 + 1.121 +static vpx_codec_err_t vp8_init(vpx_codec_ctx_t *ctx, 1.122 + vpx_codec_priv_enc_mr_cfg_t *data) 1.123 +{ 1.124 + vpx_codec_err_t res = VPX_CODEC_OK; 1.125 + (void) data; 1.126 + 1.127 + vp8_rtcd(); 1.128 + 1.129 + /* This function only allocates space for the vpx_codec_alg_priv_t 1.130 + * structure. More memory may be required at the time the stream 1.131 + * information becomes known. 1.132 + */ 1.133 + if (!ctx->priv) 1.134 + { 1.135 + vpx_codec_mmap_t mmap; 1.136 + 1.137 + mmap.id = vp8_mem_req_segs[0].id; 1.138 + mmap.sz = sizeof(vpx_codec_alg_priv_t); 1.139 + mmap.align = vp8_mem_req_segs[0].align; 1.140 + mmap.flags = vp8_mem_req_segs[0].flags; 1.141 + 1.142 + res = vpx_mmap_alloc(&mmap); 1.143 + if (res != VPX_CODEC_OK) return res; 1.144 + 1.145 + vp8_init_ctx(ctx, &mmap); 1.146 + 1.147 + /* initialize number of fragments to zero */ 1.148 + ctx->priv->alg_priv->fragments.count = 0; 1.149 + /* is input fragments enabled? */ 1.150 + ctx->priv->alg_priv->fragments.enabled = 1.151 + (ctx->priv->alg_priv->base.init_flags & 1.152 + VPX_CODEC_USE_INPUT_FRAGMENTS); 1.153 + 1.154 + ctx->priv->alg_priv->defer_alloc = 1; 1.155 + /*post processing level initialized to do nothing */ 1.156 + } 1.157 + 1.158 + ctx->priv->alg_priv->yv12_frame_buffers.use_frame_threads = 1.159 + (ctx->priv->alg_priv->base.init_flags & 1.160 + VPX_CODEC_USE_FRAME_THREADING); 1.161 + 1.162 + /* for now, disable frame threading */ 1.163 + ctx->priv->alg_priv->yv12_frame_buffers.use_frame_threads = 0; 1.164 + 1.165 + if(ctx->priv->alg_priv->yv12_frame_buffers.use_frame_threads && 1.166 + (( ctx->priv->alg_priv->base.init_flags & 1.167 + VPX_CODEC_USE_ERROR_CONCEALMENT) 1.168 + || ( ctx->priv->alg_priv->base.init_flags & 1.169 + VPX_CODEC_USE_INPUT_FRAGMENTS) ) ) 1.170 + { 1.171 + /* row-based threading, error concealment, and input fragments will 1.172 + * not be supported when using frame-based threading */ 1.173 + res = VPX_CODEC_INVALID_PARAM; 1.174 + } 1.175 + 1.176 + return res; 1.177 +} 1.178 + 1.179 +static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx) 1.180 +{ 1.181 + int i; 1.182 + 1.183 + vp8_remove_decoder_instances(&ctx->yv12_frame_buffers); 1.184 + 1.185 + for (i = NELEMENTS(ctx->mmaps) - 1; i >= 0; i--) 1.186 + { 1.187 + if (ctx->mmaps[i].dtor) 1.188 + ctx->mmaps[i].dtor(&ctx->mmaps[i]); 1.189 + } 1.190 + 1.191 + return VPX_CODEC_OK; 1.192 +} 1.193 + 1.194 +static vpx_codec_err_t vp8_peek_si_internal(const uint8_t *data, 1.195 + unsigned int data_sz, 1.196 + vpx_codec_stream_info_t *si, 1.197 + vp8_decrypt_cb *decrypt_cb, 1.198 + void *decrypt_state) 1.199 +{ 1.200 + vpx_codec_err_t res = VPX_CODEC_OK; 1.201 + 1.202 + if(data + data_sz <= data) 1.203 + { 1.204 + res = VPX_CODEC_INVALID_PARAM; 1.205 + } 1.206 + else 1.207 + { 1.208 + /* Parse uncompresssed part of key frame header. 1.209 + * 3 bytes:- including version, frame type and an offset 1.210 + * 3 bytes:- sync code (0x9d, 0x01, 0x2a) 1.211 + * 4 bytes:- including image width and height in the lowest 14 bits 1.212 + * of each 2-byte value. 1.213 + */ 1.214 + uint8_t clear_buffer[10]; 1.215 + const uint8_t *clear = data; 1.216 + if (decrypt_cb) 1.217 + { 1.218 + int n = data_sz > 10 ? 10 : data_sz; 1.219 + decrypt_cb(decrypt_state, data, clear_buffer, n); 1.220 + clear = clear_buffer; 1.221 + } 1.222 + si->is_kf = 0; 1.223 + 1.224 + if (data_sz >= 10 && !(clear[0] & 0x01)) /* I-Frame */ 1.225 + { 1.226 + si->is_kf = 1; 1.227 + 1.228 + /* vet via sync code */ 1.229 + if (clear[3] != 0x9d || clear[4] != 0x01 || clear[5] != 0x2a) 1.230 + res = VPX_CODEC_UNSUP_BITSTREAM; 1.231 + 1.232 + si->w = (clear[6] | (clear[7] << 8)) & 0x3fff; 1.233 + si->h = (clear[8] | (clear[9] << 8)) & 0x3fff; 1.234 + 1.235 + /*printf("w=%d, h=%d\n", si->w, si->h);*/ 1.236 + if (!(si->h | si->w)) 1.237 + res = VPX_CODEC_UNSUP_BITSTREAM; 1.238 + } 1.239 + else 1.240 + { 1.241 + res = VPX_CODEC_UNSUP_BITSTREAM; 1.242 + } 1.243 + } 1.244 + 1.245 + return res; 1.246 +} 1.247 + 1.248 +static vpx_codec_err_t vp8_peek_si(const uint8_t *data, 1.249 + unsigned int data_sz, 1.250 + vpx_codec_stream_info_t *si) { 1.251 + return vp8_peek_si_internal(data, data_sz, si, NULL, NULL); 1.252 +} 1.253 + 1.254 +static vpx_codec_err_t vp8_get_si(vpx_codec_alg_priv_t *ctx, 1.255 + vpx_codec_stream_info_t *si) 1.256 +{ 1.257 + 1.258 + unsigned int sz; 1.259 + 1.260 + if (si->sz >= sizeof(vp8_stream_info_t)) 1.261 + sz = sizeof(vp8_stream_info_t); 1.262 + else 1.263 + sz = sizeof(vpx_codec_stream_info_t); 1.264 + 1.265 + memcpy(si, &ctx->si, sz); 1.266 + si->sz = sz; 1.267 + 1.268 + return VPX_CODEC_OK; 1.269 +} 1.270 + 1.271 + 1.272 +static vpx_codec_err_t 1.273 +update_error_state(vpx_codec_alg_priv_t *ctx, 1.274 + const struct vpx_internal_error_info *error) 1.275 +{ 1.276 + vpx_codec_err_t res; 1.277 + 1.278 + if ((res = error->error_code)) 1.279 + ctx->base.err_detail = error->has_detail 1.280 + ? error->detail 1.281 + : NULL; 1.282 + 1.283 + return res; 1.284 +} 1.285 + 1.286 +static void yuvconfig2image(vpx_image_t *img, 1.287 + const YV12_BUFFER_CONFIG *yv12, 1.288 + void *user_priv) 1.289 +{ 1.290 + /** vpx_img_wrap() doesn't allow specifying independent strides for 1.291 + * the Y, U, and V planes, nor other alignment adjustments that 1.292 + * might be representable by a YV12_BUFFER_CONFIG, so we just 1.293 + * initialize all the fields.*/ 1.294 + img->fmt = VPX_IMG_FMT_I420; 1.295 + img->w = yv12->y_stride; 1.296 + img->h = (yv12->y_height + 2 * VP8BORDERINPIXELS + 15) & ~15; 1.297 + img->d_w = yv12->y_width; 1.298 + img->d_h = yv12->y_height; 1.299 + img->x_chroma_shift = 1; 1.300 + img->y_chroma_shift = 1; 1.301 + img->planes[VPX_PLANE_Y] = yv12->y_buffer; 1.302 + img->planes[VPX_PLANE_U] = yv12->u_buffer; 1.303 + img->planes[VPX_PLANE_V] = yv12->v_buffer; 1.304 + img->planes[VPX_PLANE_ALPHA] = NULL; 1.305 + img->stride[VPX_PLANE_Y] = yv12->y_stride; 1.306 + img->stride[VPX_PLANE_U] = yv12->uv_stride; 1.307 + img->stride[VPX_PLANE_V] = yv12->uv_stride; 1.308 + img->stride[VPX_PLANE_ALPHA] = yv12->y_stride; 1.309 + img->bps = 12; 1.310 + img->user_priv = user_priv; 1.311 + img->img_data = yv12->buffer_alloc; 1.312 + img->img_data_owner = 0; 1.313 + img->self_allocd = 0; 1.314 +} 1.315 + 1.316 +static int 1.317 +update_fragments(vpx_codec_alg_priv_t *ctx, 1.318 + const uint8_t *data, 1.319 + unsigned int data_sz, 1.320 + vpx_codec_err_t *res) 1.321 +{ 1.322 + *res = VPX_CODEC_OK; 1.323 + 1.324 + if (ctx->fragments.count == 0) 1.325 + { 1.326 + /* New frame, reset fragment pointers and sizes */ 1.327 + vpx_memset((void*)ctx->fragments.ptrs, 0, sizeof(ctx->fragments.ptrs)); 1.328 + vpx_memset(ctx->fragments.sizes, 0, sizeof(ctx->fragments.sizes)); 1.329 + } 1.330 + if (ctx->fragments.enabled && !(data == NULL && data_sz == 0)) 1.331 + { 1.332 + /* Store a pointer to this fragment and return. We haven't 1.333 + * received the complete frame yet, so we will wait with decoding. 1.334 + */ 1.335 + ctx->fragments.ptrs[ctx->fragments.count] = data; 1.336 + ctx->fragments.sizes[ctx->fragments.count] = data_sz; 1.337 + ctx->fragments.count++; 1.338 + if (ctx->fragments.count > (1 << EIGHT_PARTITION) + 1) 1.339 + { 1.340 + ctx->fragments.count = 0; 1.341 + *res = VPX_CODEC_INVALID_PARAM; 1.342 + return -1; 1.343 + } 1.344 + return 0; 1.345 + } 1.346 + 1.347 + if (!ctx->fragments.enabled) 1.348 + { 1.349 + ctx->fragments.ptrs[0] = data; 1.350 + ctx->fragments.sizes[0] = data_sz; 1.351 + ctx->fragments.count = 1; 1.352 + } 1.353 + 1.354 + return 1; 1.355 +} 1.356 + 1.357 +static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, 1.358 + const uint8_t *data, 1.359 + unsigned int data_sz, 1.360 + void *user_priv, 1.361 + long deadline) 1.362 +{ 1.363 + vpx_codec_err_t res = VPX_CODEC_OK; 1.364 + unsigned int resolution_change = 0; 1.365 + unsigned int w, h; 1.366 + 1.367 + 1.368 + /* Update the input fragment data */ 1.369 + if(update_fragments(ctx, data, data_sz, &res) <= 0) 1.370 + return res; 1.371 + 1.372 + /* Determine the stream parameters. Note that we rely on peek_si to 1.373 + * validate that we have a buffer that does not wrap around the top 1.374 + * of the heap. 1.375 + */ 1.376 + w = ctx->si.w; 1.377 + h = ctx->si.h; 1.378 + 1.379 + res = vp8_peek_si_internal(ctx->fragments.ptrs[0], ctx->fragments.sizes[0], 1.380 + &ctx->si, ctx->decrypt_cb, ctx->decrypt_state); 1.381 + 1.382 + if((res == VPX_CODEC_UNSUP_BITSTREAM) && !ctx->si.is_kf) 1.383 + { 1.384 + /* the peek function returns an error for non keyframes, however for 1.385 + * this case, it is not an error */ 1.386 + res = VPX_CODEC_OK; 1.387 + } 1.388 + 1.389 + if(!ctx->decoder_init && !ctx->si.is_kf) 1.390 + res = VPX_CODEC_UNSUP_BITSTREAM; 1.391 + 1.392 + if ((ctx->si.h != h) || (ctx->si.w != w)) 1.393 + resolution_change = 1; 1.394 + 1.395 + /* Perform deferred allocations, if required */ 1.396 + if (!res && ctx->defer_alloc) 1.397 + { 1.398 + int i; 1.399 + 1.400 + for (i = 1; !res && i < NELEMENTS(ctx->mmaps); i++) 1.401 + { 1.402 + vpx_codec_dec_cfg_t cfg; 1.403 + 1.404 + cfg.w = ctx->si.w; 1.405 + cfg.h = ctx->si.h; 1.406 + ctx->mmaps[i].id = vp8_mem_req_segs[i].id; 1.407 + ctx->mmaps[i].sz = vp8_mem_req_segs[i].sz; 1.408 + ctx->mmaps[i].align = vp8_mem_req_segs[i].align; 1.409 + ctx->mmaps[i].flags = vp8_mem_req_segs[i].flags; 1.410 + 1.411 + if (!ctx->mmaps[i].sz) 1.412 + ctx->mmaps[i].sz = vp8_mem_req_segs[i].calc_sz(&cfg, 1.413 + ctx->base.init_flags); 1.414 + 1.415 + res = vpx_mmap_alloc(&ctx->mmaps[i]); 1.416 + } 1.417 + 1.418 + if (!res) 1.419 + vp8_finalize_mmaps(ctx); 1.420 + 1.421 + ctx->defer_alloc = 0; 1.422 + } 1.423 + 1.424 + /* Initialize the decoder instance on the first frame*/ 1.425 + if (!res && !ctx->decoder_init) 1.426 + { 1.427 + res = vpx_validate_mmaps(&ctx->si, ctx->mmaps, 1.428 + vp8_mem_req_segs, NELEMENTS(vp8_mem_req_segs), 1.429 + ctx->base.init_flags); 1.430 + 1.431 + if (!res) 1.432 + { 1.433 + VP8D_CONFIG oxcf; 1.434 + 1.435 + oxcf.Width = ctx->si.w; 1.436 + oxcf.Height = ctx->si.h; 1.437 + oxcf.Version = 9; 1.438 + oxcf.postprocess = 0; 1.439 + oxcf.max_threads = ctx->cfg.threads; 1.440 + oxcf.error_concealment = 1.441 + (ctx->base.init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT); 1.442 + 1.443 + /* If postprocessing was enabled by the application and a 1.444 + * configuration has not been provided, default it. 1.445 + */ 1.446 + if (!ctx->postproc_cfg_set 1.447 + && (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)) 1.448 + { 1.449 + ctx->postproc_cfg.post_proc_flag = 1.450 + VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE; 1.451 + ctx->postproc_cfg.deblocking_level = 4; 1.452 + ctx->postproc_cfg.noise_level = 0; 1.453 + } 1.454 + 1.455 + res = vp8_create_decoder_instances(&ctx->yv12_frame_buffers, &oxcf); 1.456 + ctx->yv12_frame_buffers.pbi[0]->decrypt_cb = ctx->decrypt_cb; 1.457 + ctx->yv12_frame_buffers.pbi[0]->decrypt_state = ctx->decrypt_state; 1.458 + } 1.459 + 1.460 + ctx->decoder_init = 1; 1.461 + } 1.462 + 1.463 + if (!res) 1.464 + { 1.465 + VP8D_COMP *pbi = ctx->yv12_frame_buffers.pbi[0]; 1.466 + if(resolution_change) 1.467 + { 1.468 + VP8_COMMON *const pc = & pbi->common; 1.469 + MACROBLOCKD *const xd = & pbi->mb; 1.470 +#if CONFIG_MULTITHREAD 1.471 + int i; 1.472 +#endif 1.473 + pc->Width = ctx->si.w; 1.474 + pc->Height = ctx->si.h; 1.475 + { 1.476 + int prev_mb_rows = pc->mb_rows; 1.477 + 1.478 + if (setjmp(pbi->common.error.jmp)) 1.479 + { 1.480 + pbi->common.error.setjmp = 0; 1.481 + /* same return value as used in vp8dx_receive_compressed_data */ 1.482 + return -1; 1.483 + } 1.484 + 1.485 + pbi->common.error.setjmp = 1; 1.486 + 1.487 + if (pc->Width <= 0) 1.488 + { 1.489 + pc->Width = w; 1.490 + vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, 1.491 + "Invalid frame width"); 1.492 + } 1.493 + 1.494 + if (pc->Height <= 0) 1.495 + { 1.496 + pc->Height = h; 1.497 + vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, 1.498 + "Invalid frame height"); 1.499 + } 1.500 + 1.501 + if (vp8_alloc_frame_buffers(pc, pc->Width, pc->Height)) 1.502 + vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, 1.503 + "Failed to allocate frame buffers"); 1.504 + 1.505 + xd->pre = pc->yv12_fb[pc->lst_fb_idx]; 1.506 + xd->dst = pc->yv12_fb[pc->new_fb_idx]; 1.507 + 1.508 +#if CONFIG_MULTITHREAD 1.509 + for (i = 0; i < pbi->allocated_decoding_thread_count; i++) 1.510 + { 1.511 + pbi->mb_row_di[i].mbd.dst = pc->yv12_fb[pc->new_fb_idx]; 1.512 + vp8_build_block_doffsets(&pbi->mb_row_di[i].mbd); 1.513 + } 1.514 +#endif 1.515 + vp8_build_block_doffsets(&pbi->mb); 1.516 + 1.517 + /* allocate memory for last frame MODE_INFO array */ 1.518 +#if CONFIG_ERROR_CONCEALMENT 1.519 + 1.520 + if (pbi->ec_enabled) 1.521 + { 1.522 + /* old prev_mip was released by vp8_de_alloc_frame_buffers() 1.523 + * called in vp8_alloc_frame_buffers() */ 1.524 + pc->prev_mip = vpx_calloc( 1.525 + (pc->mb_cols + 1) * (pc->mb_rows + 1), 1.526 + sizeof(MODE_INFO)); 1.527 + 1.528 + if (!pc->prev_mip) 1.529 + { 1.530 + vp8_de_alloc_frame_buffers(pc); 1.531 + vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, 1.532 + "Failed to allocate" 1.533 + "last frame MODE_INFO array"); 1.534 + } 1.535 + 1.536 + pc->prev_mi = pc->prev_mip + pc->mode_info_stride + 1; 1.537 + 1.538 + if (vp8_alloc_overlap_lists(pbi)) 1.539 + vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, 1.540 + "Failed to allocate overlap lists " 1.541 + "for error concealment"); 1.542 + } 1.543 + 1.544 +#endif 1.545 + 1.546 +#if CONFIG_MULTITHREAD 1.547 + if (pbi->b_multithreaded_rd) 1.548 + vp8mt_alloc_temp_buffers(pbi, pc->Width, prev_mb_rows); 1.549 +#else 1.550 + (void)prev_mb_rows; 1.551 +#endif 1.552 + } 1.553 + 1.554 + pbi->common.error.setjmp = 0; 1.555 + 1.556 + /* required to get past the first get_free_fb() call */ 1.557 + pbi->common.fb_idx_ref_cnt[0] = 0; 1.558 + } 1.559 + 1.560 + /* update the pbi fragment data */ 1.561 + pbi->fragments = ctx->fragments; 1.562 + 1.563 + ctx->user_priv = user_priv; 1.564 + if (vp8dx_receive_compressed_data(pbi, data_sz, data, deadline)) 1.565 + { 1.566 + res = update_error_state(ctx, &pbi->common.error); 1.567 + } 1.568 + 1.569 + /* get ready for the next series of fragments */ 1.570 + ctx->fragments.count = 0; 1.571 + } 1.572 + 1.573 + return res; 1.574 +} 1.575 + 1.576 +static vpx_image_t *vp8_get_frame(vpx_codec_alg_priv_t *ctx, 1.577 + vpx_codec_iter_t *iter) 1.578 +{ 1.579 + vpx_image_t *img = NULL; 1.580 + 1.581 + /* iter acts as a flip flop, so an image is only returned on the first 1.582 + * call to get_frame. 1.583 + */ 1.584 + if (!(*iter) && ctx->yv12_frame_buffers.pbi[0]) 1.585 + { 1.586 + YV12_BUFFER_CONFIG sd; 1.587 + int64_t time_stamp = 0, time_end_stamp = 0; 1.588 + vp8_ppflags_t flags = {0}; 1.589 + 1.590 + if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) 1.591 + { 1.592 + flags.post_proc_flag= ctx->postproc_cfg.post_proc_flag 1.593 +#if CONFIG_POSTPROC_VISUALIZER 1.594 + 1.595 + | ((ctx->dbg_color_ref_frame_flag != 0) ? VP8D_DEBUG_CLR_FRM_REF_BLKS : 0) 1.596 + | ((ctx->dbg_color_mb_modes_flag != 0) ? VP8D_DEBUG_CLR_BLK_MODES : 0) 1.597 + | ((ctx->dbg_color_b_modes_flag != 0) ? VP8D_DEBUG_CLR_BLK_MODES : 0) 1.598 + | ((ctx->dbg_display_mv_flag != 0) ? VP8D_DEBUG_DRAW_MV : 0) 1.599 +#endif 1.600 + ; 1.601 + flags.deblocking_level = ctx->postproc_cfg.deblocking_level; 1.602 + flags.noise_level = ctx->postproc_cfg.noise_level; 1.603 +#if CONFIG_POSTPROC_VISUALIZER 1.604 + flags.display_ref_frame_flag= ctx->dbg_color_ref_frame_flag; 1.605 + flags.display_mb_modes_flag = ctx->dbg_color_mb_modes_flag; 1.606 + flags.display_b_modes_flag = ctx->dbg_color_b_modes_flag; 1.607 + flags.display_mv_flag = ctx->dbg_display_mv_flag; 1.608 +#endif 1.609 + } 1.610 + 1.611 + if (0 == vp8dx_get_raw_frame(ctx->yv12_frame_buffers.pbi[0], &sd, 1.612 + &time_stamp, &time_end_stamp, &flags)) 1.613 + { 1.614 + yuvconfig2image(&ctx->img, &sd, ctx->user_priv); 1.615 + 1.616 + img = &ctx->img; 1.617 + *iter = img; 1.618 + } 1.619 + } 1.620 + 1.621 + return img; 1.622 +} 1.623 + 1.624 + 1.625 +static 1.626 +vpx_codec_err_t vp8_xma_get_mmap(const vpx_codec_ctx_t *ctx, 1.627 + vpx_codec_mmap_t *mmap, 1.628 + vpx_codec_iter_t *iter) 1.629 +{ 1.630 + vpx_codec_err_t res; 1.631 + const mem_req_t *seg_iter = *iter; 1.632 + 1.633 + /* Get address of next segment request */ 1.634 + do 1.635 + { 1.636 + if (!seg_iter) 1.637 + seg_iter = vp8_mem_req_segs; 1.638 + else if (seg_iter->id != VP8_SEG_MAX) 1.639 + seg_iter++; 1.640 + 1.641 + *iter = (vpx_codec_iter_t)seg_iter; 1.642 + 1.643 + if (seg_iter->id != VP8_SEG_MAX) 1.644 + { 1.645 + mmap->id = seg_iter->id; 1.646 + mmap->sz = seg_iter->sz; 1.647 + mmap->align = seg_iter->align; 1.648 + mmap->flags = seg_iter->flags; 1.649 + 1.650 + if (!seg_iter->sz) 1.651 + mmap->sz = seg_iter->calc_sz(ctx->config.dec, ctx->init_flags); 1.652 + 1.653 + res = VPX_CODEC_OK; 1.654 + } 1.655 + else 1.656 + res = VPX_CODEC_LIST_END; 1.657 + } 1.658 + while (!mmap->sz && res != VPX_CODEC_LIST_END); 1.659 + 1.660 + return res; 1.661 +} 1.662 + 1.663 +static vpx_codec_err_t vp8_xma_set_mmap(vpx_codec_ctx_t *ctx, 1.664 + const vpx_codec_mmap_t *mmap) 1.665 +{ 1.666 + vpx_codec_err_t res = VPX_CODEC_MEM_ERROR; 1.667 + int i, done; 1.668 + 1.669 + if (!ctx->priv) 1.670 + { 1.671 + if (mmap->id == VP8_SEG_ALG_PRIV) 1.672 + { 1.673 + if (!ctx->priv) 1.674 + { 1.675 + vp8_init_ctx(ctx, mmap); 1.676 + res = VPX_CODEC_OK; 1.677 + } 1.678 + } 1.679 + } 1.680 + 1.681 + done = 1; 1.682 + 1.683 + if (!res && ctx->priv->alg_priv) 1.684 + { 1.685 + for (i = 0; i < NELEMENTS(ctx->priv->alg_priv->mmaps); i++) 1.686 + { 1.687 + if (ctx->priv->alg_priv->mmaps[i].id == mmap->id) 1.688 + if (!ctx->priv->alg_priv->mmaps[i].base) 1.689 + { 1.690 + ctx->priv->alg_priv->mmaps[i] = *mmap; 1.691 + res = VPX_CODEC_OK; 1.692 + } 1.693 + 1.694 + done &= (ctx->priv->alg_priv->mmaps[i].base != NULL); 1.695 + } 1.696 + } 1.697 + 1.698 + if (done && !res) 1.699 + { 1.700 + vp8_finalize_mmaps(ctx->priv->alg_priv); 1.701 + res = ctx->iface->init(ctx, NULL); 1.702 + } 1.703 + 1.704 + return res; 1.705 +} 1.706 + 1.707 +static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, 1.708 + YV12_BUFFER_CONFIG *yv12) 1.709 +{ 1.710 + vpx_codec_err_t res = VPX_CODEC_OK; 1.711 + yv12->y_buffer = img->planes[VPX_PLANE_Y]; 1.712 + yv12->u_buffer = img->planes[VPX_PLANE_U]; 1.713 + yv12->v_buffer = img->planes[VPX_PLANE_V]; 1.714 + 1.715 + yv12->y_crop_width = img->d_w; 1.716 + yv12->y_crop_height = img->d_h; 1.717 + yv12->y_width = img->d_w; 1.718 + yv12->y_height = img->d_h; 1.719 + yv12->uv_width = yv12->y_width / 2; 1.720 + yv12->uv_height = yv12->y_height / 2; 1.721 + 1.722 + yv12->y_stride = img->stride[VPX_PLANE_Y]; 1.723 + yv12->uv_stride = img->stride[VPX_PLANE_U]; 1.724 + 1.725 + yv12->border = (img->stride[VPX_PLANE_Y] - img->d_w) / 2; 1.726 + return res; 1.727 +} 1.728 + 1.729 + 1.730 +static vpx_codec_err_t vp8_set_reference(vpx_codec_alg_priv_t *ctx, 1.731 + int ctr_id, 1.732 + va_list args) 1.733 +{ 1.734 + 1.735 + vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 1.736 + 1.737 + if (data && !ctx->yv12_frame_buffers.use_frame_threads) 1.738 + { 1.739 + vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 1.740 + YV12_BUFFER_CONFIG sd; 1.741 + 1.742 + image2yuvconfig(&frame->img, &sd); 1.743 + 1.744 + return vp8dx_set_reference(ctx->yv12_frame_buffers.pbi[0], 1.745 + frame->frame_type, &sd); 1.746 + } 1.747 + else 1.748 + return VPX_CODEC_INVALID_PARAM; 1.749 + 1.750 +} 1.751 + 1.752 +static vpx_codec_err_t vp8_get_reference(vpx_codec_alg_priv_t *ctx, 1.753 + int ctr_id, 1.754 + va_list args) 1.755 +{ 1.756 + 1.757 + vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 1.758 + 1.759 + if (data && !ctx->yv12_frame_buffers.use_frame_threads) 1.760 + { 1.761 + vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 1.762 + YV12_BUFFER_CONFIG sd; 1.763 + 1.764 + image2yuvconfig(&frame->img, &sd); 1.765 + 1.766 + return vp8dx_get_reference(ctx->yv12_frame_buffers.pbi[0], 1.767 + frame->frame_type, &sd); 1.768 + } 1.769 + else 1.770 + return VPX_CODEC_INVALID_PARAM; 1.771 + 1.772 +} 1.773 + 1.774 +static vpx_codec_err_t vp8_set_postproc(vpx_codec_alg_priv_t *ctx, 1.775 + int ctr_id, 1.776 + va_list args) 1.777 +{ 1.778 +#if CONFIG_POSTPROC 1.779 + vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *); 1.780 + 1.781 + if (data) 1.782 + { 1.783 + ctx->postproc_cfg_set = 1; 1.784 + ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data); 1.785 + return VPX_CODEC_OK; 1.786 + } 1.787 + else 1.788 + return VPX_CODEC_INVALID_PARAM; 1.789 + 1.790 +#else 1.791 + return VPX_CODEC_INCAPABLE; 1.792 +#endif 1.793 +} 1.794 + 1.795 +static vpx_codec_err_t vp8_set_dbg_options(vpx_codec_alg_priv_t *ctx, 1.796 + int ctrl_id, 1.797 + va_list args) 1.798 +{ 1.799 +#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC 1.800 + int data = va_arg(args, int); 1.801 + 1.802 +#define MAP(id, var) case id: var = data; break; 1.803 + 1.804 + switch (ctrl_id) 1.805 + { 1.806 + MAP (VP8_SET_DBG_COLOR_REF_FRAME, ctx->dbg_color_ref_frame_flag); 1.807 + MAP (VP8_SET_DBG_COLOR_MB_MODES, ctx->dbg_color_mb_modes_flag); 1.808 + MAP (VP8_SET_DBG_COLOR_B_MODES, ctx->dbg_color_b_modes_flag); 1.809 + MAP (VP8_SET_DBG_DISPLAY_MV, ctx->dbg_display_mv_flag); 1.810 + } 1.811 + 1.812 + return VPX_CODEC_OK; 1.813 +#else 1.814 + return VPX_CODEC_INCAPABLE; 1.815 +#endif 1.816 +} 1.817 + 1.818 +static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx, 1.819 + int ctrl_id, 1.820 + va_list args) 1.821 +{ 1.822 + int *update_info = va_arg(args, int *); 1.823 + 1.824 + if (update_info && !ctx->yv12_frame_buffers.use_frame_threads) 1.825 + { 1.826 + VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; 1.827 + 1.828 + *update_info = pbi->common.refresh_alt_ref_frame * (int) VP8_ALTR_FRAME 1.829 + + pbi->common.refresh_golden_frame * (int) VP8_GOLD_FRAME 1.830 + + pbi->common.refresh_last_frame * (int) VP8_LAST_FRAME; 1.831 + 1.832 + return VPX_CODEC_OK; 1.833 + } 1.834 + else 1.835 + return VPX_CODEC_INVALID_PARAM; 1.836 +} 1.837 + 1.838 +extern int vp8dx_references_buffer( VP8_COMMON *oci, int ref_frame ); 1.839 +static vpx_codec_err_t vp8_get_last_ref_frame(vpx_codec_alg_priv_t *ctx, 1.840 + int ctrl_id, 1.841 + va_list args) 1.842 +{ 1.843 + int *ref_info = va_arg(args, int *); 1.844 + 1.845 + if (ref_info && !ctx->yv12_frame_buffers.use_frame_threads) 1.846 + { 1.847 + VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; 1.848 + VP8_COMMON *oci = &pbi->common; 1.849 + *ref_info = 1.850 + (vp8dx_references_buffer( oci, ALTREF_FRAME )?VP8_ALTR_FRAME:0) | 1.851 + (vp8dx_references_buffer( oci, GOLDEN_FRAME )?VP8_GOLD_FRAME:0) | 1.852 + (vp8dx_references_buffer( oci, LAST_FRAME )?VP8_LAST_FRAME:0); 1.853 + 1.854 + return VPX_CODEC_OK; 1.855 + } 1.856 + else 1.857 + return VPX_CODEC_INVALID_PARAM; 1.858 +} 1.859 + 1.860 +static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, 1.861 + int ctrl_id, 1.862 + va_list args) 1.863 +{ 1.864 + 1.865 + int *corrupted = va_arg(args, int *); 1.866 + VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; 1.867 + 1.868 + if (corrupted && pbi) 1.869 + { 1.870 + *corrupted = pbi->common.frame_to_show->corrupted; 1.871 + 1.872 + return VPX_CODEC_OK; 1.873 + } 1.874 + else 1.875 + return VPX_CODEC_INVALID_PARAM; 1.876 + 1.877 +} 1.878 + 1.879 +static vpx_codec_err_t vp8_set_decryptor(vpx_codec_alg_priv_t *ctx, 1.880 + int ctrl_id, 1.881 + va_list args) 1.882 +{ 1.883 + vp8_decrypt_init *init = va_arg(args, vp8_decrypt_init *); 1.884 + 1.885 + if (init) 1.886 + { 1.887 + ctx->decrypt_cb = init->decrypt_cb; 1.888 + ctx->decrypt_state = init->decrypt_state; 1.889 + } 1.890 + else 1.891 + { 1.892 + ctx->decrypt_cb = NULL; 1.893 + ctx->decrypt_state = NULL; 1.894 + } 1.895 + return VPX_CODEC_OK; 1.896 +} 1.897 + 1.898 +vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] = 1.899 +{ 1.900 + {VP8_SET_REFERENCE, vp8_set_reference}, 1.901 + {VP8_COPY_REFERENCE, vp8_get_reference}, 1.902 + {VP8_SET_POSTPROC, vp8_set_postproc}, 1.903 + {VP8_SET_DBG_COLOR_REF_FRAME, vp8_set_dbg_options}, 1.904 + {VP8_SET_DBG_COLOR_MB_MODES, vp8_set_dbg_options}, 1.905 + {VP8_SET_DBG_COLOR_B_MODES, vp8_set_dbg_options}, 1.906 + {VP8_SET_DBG_DISPLAY_MV, vp8_set_dbg_options}, 1.907 + {VP8D_GET_LAST_REF_UPDATES, vp8_get_last_ref_updates}, 1.908 + {VP8D_GET_FRAME_CORRUPTED, vp8_get_frame_corrupted}, 1.909 + {VP8D_GET_LAST_REF_USED, vp8_get_last_ref_frame}, 1.910 + {VP8D_SET_DECRYPTOR, vp8_set_decryptor}, 1.911 + { -1, NULL}, 1.912 +}; 1.913 + 1.914 + 1.915 +#ifndef VERSION_STRING 1.916 +#define VERSION_STRING 1.917 +#endif 1.918 +CODEC_INTERFACE(vpx_codec_vp8_dx) = 1.919 +{ 1.920 + "WebM Project VP8 Decoder" VERSION_STRING, 1.921 + VPX_CODEC_INTERNAL_ABI_VERSION, 1.922 + VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC | VP8_CAP_ERROR_CONCEALMENT | 1.923 + VPX_CODEC_CAP_INPUT_FRAGMENTS, 1.924 + /* vpx_codec_caps_t caps; */ 1.925 + vp8_init, /* vpx_codec_init_fn_t init; */ 1.926 + vp8_destroy, /* vpx_codec_destroy_fn_t destroy; */ 1.927 + vp8_ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */ 1.928 + vp8_xma_get_mmap, /* vpx_codec_get_mmap_fn_t get_mmap; */ 1.929 + vp8_xma_set_mmap, /* vpx_codec_set_mmap_fn_t set_mmap; */ 1.930 + { 1.931 + vp8_peek_si, /* vpx_codec_peek_si_fn_t peek_si; */ 1.932 + vp8_get_si, /* vpx_codec_get_si_fn_t get_si; */ 1.933 + vp8_decode, /* vpx_codec_decode_fn_t decode; */ 1.934 + vp8_get_frame, /* vpx_codec_frame_get_fn_t frame_get; */ 1.935 + }, 1.936 + { /* encoder functions */ 1.937 + NOT_IMPLEMENTED, 1.938 + NOT_IMPLEMENTED, 1.939 + NOT_IMPLEMENTED, 1.940 + NOT_IMPLEMENTED, 1.941 + NOT_IMPLEMENTED, 1.942 + NOT_IMPLEMENTED 1.943 + } 1.944 +};