1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libvpx/vp9/vp9_dx_iface.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,722 @@ 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 "vpx/vpx_decoder.h" 1.18 +#include "vpx/vp8dx.h" 1.19 +#include "vpx/internal/vpx_codec_internal.h" 1.20 +#include "./vpx_version.h" 1.21 +#include "vp9/decoder/vp9_onyxd.h" 1.22 +#include "vp9/decoder/vp9_onyxd_int.h" 1.23 +#include "vp9/decoder/vp9_read_bit_buffer.h" 1.24 +#include "vp9/vp9_iface_common.h" 1.25 + 1.26 +#define VP9_CAP_POSTPROC (CONFIG_VP9_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0) 1.27 +typedef vpx_codec_stream_info_t vp9_stream_info_t; 1.28 + 1.29 +/* Structures for handling memory allocations */ 1.30 +typedef enum { 1.31 + VP9_SEG_ALG_PRIV = 256, 1.32 + VP9_SEG_MAX 1.33 +} mem_seg_id_t; 1.34 +#define NELEMENTS(x) ((int)(sizeof(x)/sizeof(x[0]))) 1.35 + 1.36 +static unsigned long priv_sz(const vpx_codec_dec_cfg_t *si, 1.37 + vpx_codec_flags_t flags); 1.38 + 1.39 +static const mem_req_t vp9_mem_req_segs[] = { 1.40 + {VP9_SEG_ALG_PRIV, 0, 8, VPX_CODEC_MEM_ZERO, priv_sz}, 1.41 + {VP9_SEG_MAX, 0, 0, 0, NULL} 1.42 +}; 1.43 + 1.44 +struct vpx_codec_alg_priv { 1.45 + vpx_codec_priv_t base; 1.46 + vpx_codec_mmap_t mmaps[NELEMENTS(vp9_mem_req_segs) - 1]; 1.47 + vpx_codec_dec_cfg_t cfg; 1.48 + vp9_stream_info_t si; 1.49 + int defer_alloc; 1.50 + int decoder_init; 1.51 + VP9D_PTR pbi; 1.52 + int postproc_cfg_set; 1.53 + vp8_postproc_cfg_t postproc_cfg; 1.54 +#if CONFIG_POSTPROC_VISUALIZER 1.55 + unsigned int dbg_postproc_flag; 1.56 + int dbg_color_ref_frame_flag; 1.57 + int dbg_color_mb_modes_flag; 1.58 + int dbg_color_b_modes_flag; 1.59 + int dbg_display_mv_flag; 1.60 +#endif 1.61 + vpx_image_t img; 1.62 + int img_setup; 1.63 + int img_avail; 1.64 + int invert_tile_order; 1.65 +}; 1.66 + 1.67 +static unsigned long priv_sz(const vpx_codec_dec_cfg_t *si, 1.68 + vpx_codec_flags_t flags) { 1.69 + /* Although this declaration is constant, we can't use it in the requested 1.70 + * segments list because we want to define the requested segments list 1.71 + * before defining the private type (so that the number of memory maps is 1.72 + * known) 1.73 + */ 1.74 + (void)si; 1.75 + return sizeof(vpx_codec_alg_priv_t); 1.76 +} 1.77 + 1.78 +static void vp9_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap) { 1.79 + int i; 1.80 + 1.81 + ctx->priv = mmap->base; 1.82 + ctx->priv->sz = sizeof(*ctx->priv); 1.83 + ctx->priv->iface = ctx->iface; 1.84 + ctx->priv->alg_priv = mmap->base; 1.85 + 1.86 + for (i = 0; i < NELEMENTS(ctx->priv->alg_priv->mmaps); i++) 1.87 + ctx->priv->alg_priv->mmaps[i].id = vp9_mem_req_segs[i].id; 1.88 + 1.89 + ctx->priv->alg_priv->mmaps[0] = *mmap; 1.90 + ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si); 1.91 + ctx->priv->init_flags = ctx->init_flags; 1.92 + 1.93 + if (ctx->config.dec) { 1.94 + /* Update the reference to the config structure to an internal copy. */ 1.95 + ctx->priv->alg_priv->cfg = *ctx->config.dec; 1.96 + ctx->config.dec = &ctx->priv->alg_priv->cfg; 1.97 + } 1.98 +} 1.99 + 1.100 +static void vp9_finalize_mmaps(vpx_codec_alg_priv_t *ctx) { 1.101 + /* nothing to clean up */ 1.102 +} 1.103 + 1.104 +static vpx_codec_err_t vp9_init(vpx_codec_ctx_t *ctx, 1.105 + vpx_codec_priv_enc_mr_cfg_t *data) { 1.106 + vpx_codec_err_t res = VPX_CODEC_OK; 1.107 + 1.108 + /* This function only allocates space for the vpx_codec_alg_priv_t 1.109 + * structure. More memory may be required at the time the stream 1.110 + * information becomes known. 1.111 + */ 1.112 + if (!ctx->priv) { 1.113 + vpx_codec_mmap_t mmap; 1.114 + 1.115 + mmap.id = vp9_mem_req_segs[0].id; 1.116 + mmap.sz = sizeof(vpx_codec_alg_priv_t); 1.117 + mmap.align = vp9_mem_req_segs[0].align; 1.118 + mmap.flags = vp9_mem_req_segs[0].flags; 1.119 + 1.120 + res = vpx_mmap_alloc(&mmap); 1.121 + 1.122 + if (!res) { 1.123 + vp9_init_ctx(ctx, &mmap); 1.124 + 1.125 + ctx->priv->alg_priv->defer_alloc = 1; 1.126 + /*post processing level initialized to do nothing */ 1.127 + } 1.128 + } 1.129 + 1.130 + return res; 1.131 +} 1.132 + 1.133 +static vpx_codec_err_t vp9_destroy(vpx_codec_alg_priv_t *ctx) { 1.134 + int i; 1.135 + 1.136 + vp9_remove_decompressor(ctx->pbi); 1.137 + 1.138 + for (i = NELEMENTS(ctx->mmaps) - 1; i >= 0; i--) { 1.139 + if (ctx->mmaps[i].dtor) 1.140 + ctx->mmaps[i].dtor(&ctx->mmaps[i]); 1.141 + } 1.142 + 1.143 + return VPX_CODEC_OK; 1.144 +} 1.145 + 1.146 +static vpx_codec_err_t vp9_peek_si(const uint8_t *data, 1.147 + unsigned int data_sz, 1.148 + vpx_codec_stream_info_t *si) { 1.149 + if (data_sz <= 8) return VPX_CODEC_UNSUP_BITSTREAM; 1.150 + if (data + data_sz <= data) return VPX_CODEC_INVALID_PARAM; 1.151 + 1.152 + si->is_kf = 0; 1.153 + si->w = si->h = 0; 1.154 + 1.155 + { 1.156 + struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL }; 1.157 + const int frame_marker = vp9_rb_read_literal(&rb, 2); 1.158 + const int version = vp9_rb_read_bit(&rb) | (vp9_rb_read_bit(&rb) << 1); 1.159 + if (frame_marker != 0x2) return VPX_CODEC_UNSUP_BITSTREAM; 1.160 +#if CONFIG_NON420 1.161 + if (version > 1) return VPX_CODEC_UNSUP_BITSTREAM; 1.162 +#else 1.163 + if (version != 0) return VPX_CODEC_UNSUP_BITSTREAM; 1.164 +#endif 1.165 + 1.166 + if (vp9_rb_read_bit(&rb)) { // show an existing frame 1.167 + return VPX_CODEC_OK; 1.168 + } 1.169 + 1.170 + si->is_kf = !vp9_rb_read_bit(&rb); 1.171 + if (si->is_kf) { 1.172 + const int sRGB = 7; 1.173 + int colorspace; 1.174 + 1.175 + rb.bit_offset += 1; // show frame 1.176 + rb.bit_offset += 1; // error resilient 1.177 + 1.178 + if (vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_0 || 1.179 + vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_1 || 1.180 + vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_2) { 1.181 + return VPX_CODEC_UNSUP_BITSTREAM; 1.182 + } 1.183 + 1.184 + colorspace = vp9_rb_read_literal(&rb, 3); 1.185 + if (colorspace != sRGB) { 1.186 + rb.bit_offset += 1; // [16,235] (including xvycc) vs [0,255] range 1.187 + if (version == 1) { 1.188 + rb.bit_offset += 2; // subsampling x/y 1.189 + rb.bit_offset += 1; // has extra plane 1.190 + } 1.191 + } else { 1.192 + if (version == 1) { 1.193 + rb.bit_offset += 1; // has extra plane 1.194 + } else { 1.195 + // RGB is only available in version 1 1.196 + return VPX_CODEC_UNSUP_BITSTREAM; 1.197 + } 1.198 + } 1.199 + 1.200 + // TODO(jzern): these are available on non-keyframes in intra only mode. 1.201 + si->w = vp9_rb_read_literal(&rb, 16) + 1; 1.202 + si->h = vp9_rb_read_literal(&rb, 16) + 1; 1.203 + } 1.204 + } 1.205 + 1.206 + return VPX_CODEC_OK; 1.207 +} 1.208 + 1.209 +static vpx_codec_err_t vp9_get_si(vpx_codec_alg_priv_t *ctx, 1.210 + vpx_codec_stream_info_t *si) { 1.211 + unsigned int sz; 1.212 + 1.213 + if (si->sz >= sizeof(vp9_stream_info_t)) 1.214 + sz = sizeof(vp9_stream_info_t); 1.215 + else 1.216 + sz = sizeof(vpx_codec_stream_info_t); 1.217 + 1.218 + memcpy(si, &ctx->si, sz); 1.219 + si->sz = sz; 1.220 + 1.221 + return VPX_CODEC_OK; 1.222 +} 1.223 + 1.224 + 1.225 +static vpx_codec_err_t 1.226 +update_error_state(vpx_codec_alg_priv_t *ctx, 1.227 + const struct vpx_internal_error_info *error) { 1.228 + vpx_codec_err_t res; 1.229 + 1.230 + if ((res = error->error_code)) 1.231 + ctx->base.err_detail = error->has_detail 1.232 + ? error->detail 1.233 + : NULL; 1.234 + 1.235 + return res; 1.236 +} 1.237 + 1.238 +static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, 1.239 + const uint8_t **data, 1.240 + unsigned int data_sz, 1.241 + void *user_priv, 1.242 + long deadline) { 1.243 + vpx_codec_err_t res = VPX_CODEC_OK; 1.244 + 1.245 + ctx->img_avail = 0; 1.246 + 1.247 + /* Determine the stream parameters. Note that we rely on peek_si to 1.248 + * validate that we have a buffer that does not wrap around the top 1.249 + * of the heap. 1.250 + */ 1.251 + if (!ctx->si.h) 1.252 + res = ctx->base.iface->dec.peek_si(*data, data_sz, &ctx->si); 1.253 + 1.254 + 1.255 + /* Perform deferred allocations, if required */ 1.256 + if (!res && ctx->defer_alloc) { 1.257 + int i; 1.258 + 1.259 + for (i = 1; !res && i < NELEMENTS(ctx->mmaps); i++) { 1.260 + vpx_codec_dec_cfg_t cfg; 1.261 + 1.262 + cfg.w = ctx->si.w; 1.263 + cfg.h = ctx->si.h; 1.264 + ctx->mmaps[i].id = vp9_mem_req_segs[i].id; 1.265 + ctx->mmaps[i].sz = vp9_mem_req_segs[i].sz; 1.266 + ctx->mmaps[i].align = vp9_mem_req_segs[i].align; 1.267 + ctx->mmaps[i].flags = vp9_mem_req_segs[i].flags; 1.268 + 1.269 + if (!ctx->mmaps[i].sz) 1.270 + ctx->mmaps[i].sz = vp9_mem_req_segs[i].calc_sz(&cfg, 1.271 + ctx->base.init_flags); 1.272 + 1.273 + res = vpx_mmap_alloc(&ctx->mmaps[i]); 1.274 + } 1.275 + 1.276 + if (!res) 1.277 + vp9_finalize_mmaps(ctx); 1.278 + 1.279 + ctx->defer_alloc = 0; 1.280 + } 1.281 + 1.282 + /* Initialize the decoder instance on the first frame*/ 1.283 + if (!res && !ctx->decoder_init) { 1.284 + res = vpx_validate_mmaps(&ctx->si, ctx->mmaps, 1.285 + vp9_mem_req_segs, NELEMENTS(vp9_mem_req_segs), 1.286 + ctx->base.init_flags); 1.287 + 1.288 + if (!res) { 1.289 + VP9D_CONFIG oxcf; 1.290 + VP9D_PTR optr; 1.291 + 1.292 + vp9_initialize_dec(); 1.293 + 1.294 + oxcf.width = ctx->si.w; 1.295 + oxcf.height = ctx->si.h; 1.296 + oxcf.version = 9; 1.297 + oxcf.postprocess = 0; 1.298 + oxcf.max_threads = ctx->cfg.threads; 1.299 + oxcf.inv_tile_order = ctx->invert_tile_order; 1.300 + optr = vp9_create_decompressor(&oxcf); 1.301 + 1.302 + /* If postprocessing was enabled by the application and a 1.303 + * configuration has not been provided, default it. 1.304 + */ 1.305 + if (!ctx->postproc_cfg_set 1.306 + && (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)) { 1.307 + ctx->postproc_cfg.post_proc_flag = 1.308 + VP8_DEBLOCK | VP8_DEMACROBLOCK; 1.309 + ctx->postproc_cfg.deblocking_level = 4; 1.310 + ctx->postproc_cfg.noise_level = 0; 1.311 + } 1.312 + 1.313 + if (!optr) 1.314 + res = VPX_CODEC_ERROR; 1.315 + else 1.316 + ctx->pbi = optr; 1.317 + } 1.318 + 1.319 + ctx->decoder_init = 1; 1.320 + } 1.321 + 1.322 + if (!res && ctx->pbi) { 1.323 + YV12_BUFFER_CONFIG sd; 1.324 + int64_t time_stamp = 0, time_end_stamp = 0; 1.325 + vp9_ppflags_t flags = {0}; 1.326 + 1.327 + if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) { 1.328 + flags.post_proc_flag = 1.329 +#if CONFIG_POSTPROC_VISUALIZER 1.330 + ((ctx->dbg_color_ref_frame_flag != 0) ? 1.331 + VP9D_DEBUG_CLR_FRM_REF_BLKS : 0) 1.332 + | ((ctx->dbg_color_mb_modes_flag != 0) ? 1.333 + VP9D_DEBUG_CLR_BLK_MODES : 0) 1.334 + | ((ctx->dbg_color_b_modes_flag != 0) ? 1.335 + VP9D_DEBUG_CLR_BLK_MODES : 0) 1.336 + | ((ctx->dbg_display_mv_flag != 0) ? 1.337 + VP9D_DEBUG_DRAW_MV : 0) 1.338 + | 1.339 +#endif 1.340 + ctx->postproc_cfg.post_proc_flag; 1.341 + 1.342 + flags.deblocking_level = ctx->postproc_cfg.deblocking_level; 1.343 + flags.noise_level = ctx->postproc_cfg.noise_level; 1.344 +#if CONFIG_POSTPROC_VISUALIZER 1.345 + flags.display_ref_frame_flag = ctx->dbg_color_ref_frame_flag; 1.346 + flags.display_mb_modes_flag = ctx->dbg_color_mb_modes_flag; 1.347 + flags.display_b_modes_flag = ctx->dbg_color_b_modes_flag; 1.348 + flags.display_mv_flag = ctx->dbg_display_mv_flag; 1.349 +#endif 1.350 + } 1.351 + 1.352 + if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) { 1.353 + VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi; 1.354 + res = update_error_state(ctx, &pbi->common.error); 1.355 + } 1.356 + 1.357 + if (!res && 0 == vp9_get_raw_frame(ctx->pbi, &sd, &time_stamp, 1.358 + &time_end_stamp, &flags)) { 1.359 + yuvconfig2image(&ctx->img, &sd, user_priv); 1.360 + ctx->img_avail = 1; 1.361 + } 1.362 + } 1.363 + 1.364 + return res; 1.365 +} 1.366 + 1.367 +static void parse_superframe_index(const uint8_t *data, 1.368 + size_t data_sz, 1.369 + uint32_t sizes[8], 1.370 + int *count) { 1.371 + uint8_t marker; 1.372 + 1.373 + assert(data_sz); 1.374 + marker = data[data_sz - 1]; 1.375 + *count = 0; 1.376 + 1.377 + if ((marker & 0xe0) == 0xc0) { 1.378 + const uint32_t frames = (marker & 0x7) + 1; 1.379 + const uint32_t mag = ((marker >> 3) & 0x3) + 1; 1.380 + const size_t index_sz = 2 + mag * frames; 1.381 + 1.382 + if (data_sz >= index_sz && data[data_sz - index_sz] == marker) { 1.383 + // found a valid superframe index 1.384 + uint32_t i, j; 1.385 + const uint8_t *x = data + data_sz - index_sz + 1; 1.386 + 1.387 + for (i = 0; i < frames; i++) { 1.388 + uint32_t this_sz = 0; 1.389 + 1.390 + for (j = 0; j < mag; j++) 1.391 + this_sz |= (*x++) << (j * 8); 1.392 + sizes[i] = this_sz; 1.393 + } 1.394 + 1.395 + *count = frames; 1.396 + } 1.397 + } 1.398 +} 1.399 + 1.400 +static vpx_codec_err_t vp9_decode(vpx_codec_alg_priv_t *ctx, 1.401 + const uint8_t *data, 1.402 + unsigned int data_sz, 1.403 + void *user_priv, 1.404 + long deadline) { 1.405 + const uint8_t *data_start = data; 1.406 + const uint8_t *data_end = data + data_sz; 1.407 + vpx_codec_err_t res = 0; 1.408 + uint32_t sizes[8]; 1.409 + int frames_this_pts, frame_count = 0; 1.410 + 1.411 + if (data == NULL || data_sz == 0) return VPX_CODEC_INVALID_PARAM; 1.412 + 1.413 + parse_superframe_index(data, data_sz, sizes, &frames_this_pts); 1.414 + 1.415 + do { 1.416 + // Skip over the superframe index, if present 1.417 + if (data_sz && (*data_start & 0xe0) == 0xc0) { 1.418 + const uint8_t marker = *data_start; 1.419 + const uint32_t frames = (marker & 0x7) + 1; 1.420 + const uint32_t mag = ((marker >> 3) & 0x3) + 1; 1.421 + const uint32_t index_sz = 2 + mag * frames; 1.422 + 1.423 + if (data_sz >= index_sz && data_start[index_sz - 1] == marker) { 1.424 + data_start += index_sz; 1.425 + data_sz -= index_sz; 1.426 + if (data_start < data_end) 1.427 + continue; 1.428 + else 1.429 + break; 1.430 + } 1.431 + } 1.432 + 1.433 + // Use the correct size for this frame, if an index is present. 1.434 + if (frames_this_pts) { 1.435 + uint32_t this_sz = sizes[frame_count]; 1.436 + 1.437 + if (data_sz < this_sz) { 1.438 + ctx->base.err_detail = "Invalid frame size in index"; 1.439 + return VPX_CODEC_CORRUPT_FRAME; 1.440 + } 1.441 + 1.442 + data_sz = this_sz; 1.443 + frame_count++; 1.444 + } 1.445 + 1.446 + res = decode_one(ctx, &data_start, data_sz, user_priv, deadline); 1.447 + assert(data_start >= data); 1.448 + assert(data_start <= data_end); 1.449 + 1.450 + /* Early exit if there was a decode error */ 1.451 + if (res) 1.452 + break; 1.453 + 1.454 + /* Account for suboptimal termination by the encoder. */ 1.455 + while (data_start < data_end && *data_start == 0) 1.456 + data_start++; 1.457 + 1.458 + data_sz = data_end - data_start; 1.459 + } while (data_start < data_end); 1.460 + return res; 1.461 +} 1.462 + 1.463 +static vpx_image_t *vp9_get_frame(vpx_codec_alg_priv_t *ctx, 1.464 + vpx_codec_iter_t *iter) { 1.465 + vpx_image_t *img = NULL; 1.466 + 1.467 + if (ctx->img_avail) { 1.468 + /* iter acts as a flip flop, so an image is only returned on the first 1.469 + * call to get_frame. 1.470 + */ 1.471 + if (!(*iter)) { 1.472 + img = &ctx->img; 1.473 + *iter = img; 1.474 + } 1.475 + } 1.476 + ctx->img_avail = 0; 1.477 + 1.478 + return img; 1.479 +} 1.480 + 1.481 +static vpx_codec_err_t vp9_xma_get_mmap(const vpx_codec_ctx_t *ctx, 1.482 + vpx_codec_mmap_t *mmap, 1.483 + vpx_codec_iter_t *iter) { 1.484 + vpx_codec_err_t res; 1.485 + const mem_req_t *seg_iter = *iter; 1.486 + 1.487 + /* Get address of next segment request */ 1.488 + do { 1.489 + if (!seg_iter) 1.490 + seg_iter = vp9_mem_req_segs; 1.491 + else if (seg_iter->id != VP9_SEG_MAX) 1.492 + seg_iter++; 1.493 + 1.494 + *iter = (vpx_codec_iter_t)seg_iter; 1.495 + 1.496 + if (seg_iter->id != VP9_SEG_MAX) { 1.497 + mmap->id = seg_iter->id; 1.498 + mmap->sz = seg_iter->sz; 1.499 + mmap->align = seg_iter->align; 1.500 + mmap->flags = seg_iter->flags; 1.501 + 1.502 + if (!seg_iter->sz) 1.503 + mmap->sz = seg_iter->calc_sz(ctx->config.dec, ctx->init_flags); 1.504 + 1.505 + res = VPX_CODEC_OK; 1.506 + } else { 1.507 + res = VPX_CODEC_LIST_END; 1.508 + } 1.509 + } while (!mmap->sz && res != VPX_CODEC_LIST_END); 1.510 + 1.511 + return res; 1.512 +} 1.513 + 1.514 +static vpx_codec_err_t vp9_xma_set_mmap(vpx_codec_ctx_t *ctx, 1.515 + const vpx_codec_mmap_t *mmap) { 1.516 + vpx_codec_err_t res = VPX_CODEC_MEM_ERROR; 1.517 + int i, done; 1.518 + 1.519 + if (!ctx->priv) { 1.520 + if (mmap->id == VP9_SEG_ALG_PRIV) { 1.521 + if (!ctx->priv) { 1.522 + vp9_init_ctx(ctx, mmap); 1.523 + res = VPX_CODEC_OK; 1.524 + } 1.525 + } 1.526 + } 1.527 + 1.528 + done = 1; 1.529 + 1.530 + if (!res && ctx->priv->alg_priv) { 1.531 + for (i = 0; i < NELEMENTS(ctx->priv->alg_priv->mmaps); i++) { 1.532 + if (ctx->priv->alg_priv->mmaps[i].id == mmap->id) 1.533 + if (!ctx->priv->alg_priv->mmaps[i].base) { 1.534 + ctx->priv->alg_priv->mmaps[i] = *mmap; 1.535 + res = VPX_CODEC_OK; 1.536 + } 1.537 + 1.538 + done &= (ctx->priv->alg_priv->mmaps[i].base != NULL); 1.539 + } 1.540 + } 1.541 + 1.542 + if (done && !res) { 1.543 + vp9_finalize_mmaps(ctx->priv->alg_priv); 1.544 + res = ctx->iface->init(ctx, NULL); 1.545 + } 1.546 + 1.547 + return res; 1.548 +} 1.549 + 1.550 +static vpx_codec_err_t set_reference(vpx_codec_alg_priv_t *ctx, 1.551 + int ctr_id, 1.552 + va_list args) { 1.553 + vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 1.554 + 1.555 + if (data) { 1.556 + vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 1.557 + YV12_BUFFER_CONFIG sd; 1.558 + 1.559 + image2yuvconfig(&frame->img, &sd); 1.560 + 1.561 + return vp9_set_reference_dec(ctx->pbi, 1.562 + (VP9_REFFRAME)frame->frame_type, &sd); 1.563 + } else { 1.564 + return VPX_CODEC_INVALID_PARAM; 1.565 + } 1.566 +} 1.567 + 1.568 +static vpx_codec_err_t copy_reference(vpx_codec_alg_priv_t *ctx, 1.569 + int ctr_id, 1.570 + va_list args) { 1.571 + vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); 1.572 + 1.573 + if (data) { 1.574 + vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; 1.575 + YV12_BUFFER_CONFIG sd; 1.576 + 1.577 + image2yuvconfig(&frame->img, &sd); 1.578 + 1.579 + return vp9_copy_reference_dec(ctx->pbi, 1.580 + (VP9_REFFRAME)frame->frame_type, &sd); 1.581 + } else { 1.582 + return VPX_CODEC_INVALID_PARAM; 1.583 + } 1.584 +} 1.585 + 1.586 +static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx, 1.587 + int ctr_id, 1.588 + va_list args) { 1.589 + vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *); 1.590 + 1.591 + if (data) { 1.592 + YV12_BUFFER_CONFIG* fb; 1.593 + 1.594 + vp9_get_reference_dec(ctx->pbi, data->idx, &fb); 1.595 + yuvconfig2image(&data->img, fb, NULL); 1.596 + return VPX_CODEC_OK; 1.597 + } else { 1.598 + return VPX_CODEC_INVALID_PARAM; 1.599 + } 1.600 +} 1.601 + 1.602 +static vpx_codec_err_t set_postproc(vpx_codec_alg_priv_t *ctx, 1.603 + int ctr_id, 1.604 + va_list args) { 1.605 +#if CONFIG_VP9_POSTPROC 1.606 + vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *); 1.607 + 1.608 + if (data) { 1.609 + ctx->postproc_cfg_set = 1; 1.610 + ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data); 1.611 + return VPX_CODEC_OK; 1.612 + } else { 1.613 + return VPX_CODEC_INVALID_PARAM; 1.614 + } 1.615 +#else 1.616 + return VPX_CODEC_INCAPABLE; 1.617 +#endif 1.618 +} 1.619 + 1.620 +static vpx_codec_err_t set_dbg_options(vpx_codec_alg_priv_t *ctx, 1.621 + int ctrl_id, 1.622 + va_list args) { 1.623 +#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC 1.624 + int data = va_arg(args, int); 1.625 + 1.626 +#define MAP(id, var) case id: var = data; break; 1.627 + 1.628 + switch (ctrl_id) { 1.629 + MAP(VP8_SET_DBG_COLOR_REF_FRAME, ctx->dbg_color_ref_frame_flag); 1.630 + MAP(VP8_SET_DBG_COLOR_MB_MODES, ctx->dbg_color_mb_modes_flag); 1.631 + MAP(VP8_SET_DBG_COLOR_B_MODES, ctx->dbg_color_b_modes_flag); 1.632 + MAP(VP8_SET_DBG_DISPLAY_MV, ctx->dbg_display_mv_flag); 1.633 + } 1.634 + 1.635 + return VPX_CODEC_OK; 1.636 +#else 1.637 + return VPX_CODEC_INCAPABLE; 1.638 +#endif 1.639 +} 1.640 + 1.641 +static vpx_codec_err_t get_last_ref_updates(vpx_codec_alg_priv_t *ctx, 1.642 + int ctrl_id, 1.643 + va_list args) { 1.644 + int *update_info = va_arg(args, int *); 1.645 + VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi; 1.646 + 1.647 + if (update_info) { 1.648 + *update_info = pbi->refresh_frame_flags; 1.649 + 1.650 + return VPX_CODEC_OK; 1.651 + } else { 1.652 + return VPX_CODEC_INVALID_PARAM; 1.653 + } 1.654 +} 1.655 + 1.656 + 1.657 +static vpx_codec_err_t get_frame_corrupted(vpx_codec_alg_priv_t *ctx, 1.658 + int ctrl_id, 1.659 + va_list args) { 1.660 + int *corrupted = va_arg(args, int *); 1.661 + 1.662 + if (corrupted) { 1.663 + VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi; 1.664 + if (pbi) 1.665 + *corrupted = pbi->common.frame_to_show->corrupted; 1.666 + else 1.667 + return VPX_CODEC_ERROR; 1.668 + return VPX_CODEC_OK; 1.669 + } else { 1.670 + return VPX_CODEC_INVALID_PARAM; 1.671 + } 1.672 +} 1.673 + 1.674 +static vpx_codec_err_t set_invert_tile_order(vpx_codec_alg_priv_t *ctx, 1.675 + int ctr_id, 1.676 + va_list args) { 1.677 + ctx->invert_tile_order = va_arg(args, int); 1.678 + return VPX_CODEC_OK; 1.679 +} 1.680 + 1.681 +static vpx_codec_ctrl_fn_map_t ctf_maps[] = { 1.682 + {VP8_SET_REFERENCE, set_reference}, 1.683 + {VP8_COPY_REFERENCE, copy_reference}, 1.684 + {VP8_SET_POSTPROC, set_postproc}, 1.685 + {VP8_SET_DBG_COLOR_REF_FRAME, set_dbg_options}, 1.686 + {VP8_SET_DBG_COLOR_MB_MODES, set_dbg_options}, 1.687 + {VP8_SET_DBG_COLOR_B_MODES, set_dbg_options}, 1.688 + {VP8_SET_DBG_DISPLAY_MV, set_dbg_options}, 1.689 + {VP8D_GET_LAST_REF_UPDATES, get_last_ref_updates}, 1.690 + {VP8D_GET_FRAME_CORRUPTED, get_frame_corrupted}, 1.691 + {VP9_GET_REFERENCE, get_reference}, 1.692 + {VP9_INVERT_TILE_DECODE_ORDER, set_invert_tile_order}, 1.693 + { -1, NULL}, 1.694 +}; 1.695 + 1.696 + 1.697 +#ifndef VERSION_STRING 1.698 +#define VERSION_STRING 1.699 +#endif 1.700 +CODEC_INTERFACE(vpx_codec_vp9_dx) = { 1.701 + "WebM Project VP9 Decoder" VERSION_STRING, 1.702 + VPX_CODEC_INTERNAL_ABI_VERSION, 1.703 + VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC, 1.704 + /* vpx_codec_caps_t caps; */ 1.705 + vp9_init, /* vpx_codec_init_fn_t init; */ 1.706 + vp9_destroy, /* vpx_codec_destroy_fn_t destroy; */ 1.707 + ctf_maps, /* vpx_codec_ctrl_fn_map_t *ctrl_maps; */ 1.708 + vp9_xma_get_mmap, /* vpx_codec_get_mmap_fn_t get_mmap; */ 1.709 + vp9_xma_set_mmap, /* vpx_codec_set_mmap_fn_t set_mmap; */ 1.710 + { // NOLINT 1.711 + vp9_peek_si, /* vpx_codec_peek_si_fn_t peek_si; */ 1.712 + vp9_get_si, /* vpx_codec_get_si_fn_t get_si; */ 1.713 + vp9_decode, /* vpx_codec_decode_fn_t decode; */ 1.714 + vp9_get_frame, /* vpx_codec_frame_get_fn_t frame_get; */ 1.715 + }, 1.716 + { // NOLINT 1.717 + /* encoder functions */ 1.718 + NOT_IMPLEMENTED, 1.719 + NOT_IMPLEMENTED, 1.720 + NOT_IMPLEMENTED, 1.721 + NOT_IMPLEMENTED, 1.722 + NOT_IMPLEMENTED, 1.723 + NOT_IMPLEMENTED 1.724 + } 1.725 +};