/* * Copyright (c) 2010 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
struct vpx_codec_alg_priv {
vpx_codec_priv_t base;
vpx_codec_dec_cfg_t cfg;
vp8_stream_info_t si; int decoder_init; #if CONFIG_MULTITHREAD // Restart threads on next frame if set to 1. // This is set when error happens in multithreaded decoding and all threads // are shut down. int restart_threads; #endif int postproc_cfg_set;
vp8_postproc_cfg_t postproc_cfg;
vpx_decrypt_cb decrypt_cb; void *decrypt_state;
vpx_image_t img; int img_setup; struct frame_buffers yv12_frame_buffers; void *user_priv;
FRAGMENT_DATA fragments;
};
if (ctx->config.dec) { /* Update the reference to the config structure to an internal copy. */
priv->cfg = *ctx->config.dec;
ctx->config.dec = &priv->cfg;
}
/* This function only allocates space for the vpx_codec_alg_priv_t * structure. More memory may be required at the time the stream * information becomes known.
*/ if (!ctx->priv) {
vpx_codec_alg_priv_t *priv;
if (vp8_init_ctx(ctx)) return VPX_CODEC_MEM_ERROR;
priv = (vpx_codec_alg_priv_t *)ctx->priv;
/* initialize number of fragments to zero */
priv->fragments.count = 0; /* is input fragments enabled? */
priv->fragments.enabled =
(priv->base.init_flags & VPX_CODEC_USE_INPUT_FRAGMENTS);
/*post processing level initialized to do nothing */
}
if (data + data_sz <= data) {
res = VPX_CODEC_INVALID_PARAM;
} else { /* Parse uncompresssed part of key frame header. * 3 bytes:- including version, frame type and an offset * 3 bytes:- sync code (0x9d, 0x01, 0x2a) * 4 bytes:- including image width and height in the lowest 14 bits * of each 2-byte value.
*/
uint8_t clear_buffer[10]; const uint8_t *clear = data; if (decrypt_cb) { int n = VPXMIN(sizeof(clear_buffer), data_sz);
decrypt_cb(decrypt_state, data, clear_buffer, n);
clear = clear_buffer;
}
si->is_kf = 0;
if (ctx->fragments.count == 0) { /* New frame, reset fragment pointers and sizes */
memset((void *)ctx->fragments.ptrs, 0, sizeof(ctx->fragments.ptrs));
memset(ctx->fragments.sizes, 0, sizeof(ctx->fragments.sizes));
} if (ctx->fragments.enabled && !(data == NULL && data_sz == 0)) { /* Store a pointer to this fragment and return. We haven't * received the complete frame yet, so we will wait with decoding.
*/ if (ctx->fragments.count >= MAX_PARTITIONS) {
ctx->fragments.count = 0;
*res = VPX_CODEC_INVALID_PARAM; return -1;
}
ctx->fragments.ptrs[ctx->fragments.count] = data;
ctx->fragments.sizes[ctx->fragments.count] = data_sz;
ctx->fragments.count++; return 0;
}
/* Update the input fragment data */ if (update_fragments(ctx, data, data_sz, &res) <= 0) return res;
/* Determine the stream parameters. Note that we rely on peek_si to * validate that we have a buffer that does not wrap around the top * of the heap.
*/
w = ctx->si.w;
h = ctx->si.h;
res = vp8_peek_si_internal(ctx->fragments.ptrs[0], ctx->fragments.sizes[0],
&ctx->si, ctx->decrypt_cb, ctx->decrypt_state);
if ((res == VPX_CODEC_UNSUP_BITSTREAM) && !ctx->si.is_kf) { /* the peek function returns an error for non keyframes, however for
* this case, it is not an error */
res = VPX_CODEC_OK;
}
if (!ctx->decoder_init && !ctx->si.is_kf) res = VPX_CODEC_UNSUP_BITSTREAM; if (!res && ctx->decoder_init && w == 0 && h == 0 && ctx->si.h == 0 &&
ctx->si.w == 0) {
VP8D_COMP *pbi = ctx->yv12_frame_buffers.pbi[0];
assert(pbi != NULL);
assert(!pbi->common.error.setjmp);
res = VPX_CODEC_CORRUPT_FRAME;
vpx_internal_error(&pbi->common.error, res, "Keyframe / intra-only frame required to reset decoder" " state");
}
/* If postprocessing was enabled by the application and a * configuration has not been provided, default it.
*/ if (!ctx->postproc_cfg_set &&
(ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)) {
ctx->postproc_cfg.post_proc_flag =
VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE;
ctx->postproc_cfg.deblocking_level = 4;
ctx->postproc_cfg.noise_level = 0;
}
res = vp8_create_decoder_instances(&ctx->yv12_frame_buffers, &oxcf); if (res == VPX_CODEC_OK) {
ctx->decoder_init = 1;
} else { /* on failure clear the cached resolution to ensure a full
* reallocation is attempted on resync. */
ctx->si.w = 0;
ctx->si.h = 0;
}
}
/* Set these even if already initialized. The caller may have changed the * decrypt config between frames.
*/ if (ctx->decoder_init) {
ctx->yv12_frame_buffers.pbi[0]->decrypt_cb = ctx->decrypt_cb;
ctx->yv12_frame_buffers.pbi[0]->decrypt_state = ctx->decrypt_state;
}
if (!res) {
VP8D_COMP *pbi = ctx->yv12_frame_buffers.pbi[0];
VP8_COMMON *const pc = &pbi->common; if (resolution_change) {
MACROBLOCKD *const xd = &pbi->mb; #if CONFIG_MULTITHREAD int i; #endif
pc->Width = ctx->si.w;
pc->Height = ctx->si.h;
{ if (setjmp(pbi->common.error.jmp)) {
pbi->common.error.setjmp = 0; /* on failure clear the cached resolution to ensure a full
* reallocation is attempted on resync. */
ctx->si.w = 0;
ctx->si.h = 0;
vpx_clear_system_state(); /* same return value as used in vp8dx_receive_compressed_data */ return -1;
}
#if CONFIG_MULTITHREAD for (i = 0; i < pbi->allocated_decoding_thread_count; ++i) {
pbi->mb_row_di[i].mbd.dst = pc->yv12_fb[pc->new_fb_idx];
vp8_build_block_doffsets(&pbi->mb_row_di[i].mbd);
} #endif
vp8_build_block_doffsets(&pbi->mb);
/* allocate memory for last frame MODE_INFO array */ #if CONFIG_ERROR_CONCEALMENT
if (pbi->ec_enabled) { /* old prev_mip was released by vp8_de_alloc_frame_buffers()
* called in vp8_alloc_frame_buffers() */
pc->prev_mip = vpx_calloc((pc->mb_cols + 1) * (pc->mb_rows + 1), sizeof(MODE_INFO));
if (!pc->prev_mip) {
vp8_de_alloc_frame_buffers(pc);
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR, "Failed to allocate" "last frame MODE_INFO array");
}
/* required to get past the first get_free_fb() call */
pbi->common.fb_idx_ref_cnt[0] = 0;
}
if (setjmp(pbi->common.error.jmp)) {
vpx_clear_system_state(); /* We do not know if the missing frame(s) was supposed to update * any of the reference buffers, but we act conservative and * mark only the last buffer as corrupted.
*/
pc->yv12_fb[pc->lst_fb_idx].corrupted = 1;
/* iter acts as a flip flop, so an image is only returned on the first * call to get_frame.
*/ if (!(*iter) && ctx->yv12_frame_buffers.pbi[0]) {
YV12_BUFFER_CONFIG sd;
vp8_ppflags_t flags;
vp8_zero(flags);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.