Commit d6a4a5d9 authored by Scott LaVarnway's avatar Scott LaVarnway
Browse files

Bug fix: Handle input data ptr = NULL and size = 0 correctly

Issue 517:	Issues decoding VPX_CODEC_USE_INPUT_FRAGMENTS
http://code.google.com/p/webm/issues/detail?id=517

Change-Id: I030c4cf15b1e1b993433571b6ee77c959a368ff2
parent b9ce4302
......@@ -34,7 +34,6 @@ extern "C"
int postprocess;
int max_threads;
int error_concealment;
int input_fragments;
} VP8D_CONFIG;
typedef enum
......
......@@ -91,9 +91,6 @@ struct VP8D_COMP * vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
pbi->decoded_key_frame = 0;
pbi->input_fragments = oxcf->input_fragments;
pbi->num_fragments = 0;
/* Independent partitions is activated when a frame updates the
* token probability table to have equal probabilities over the
* PREV_COEF context.
......@@ -281,60 +278,13 @@ static int swap_frame_buffers (VP8_COMMON *cm)
return err;
}
int vp8dx_receive_compressed_data(VP8D_COMP *pbi, size_t size,
const uint8_t *source,
int64_t time_stamp)
int check_fragments_for_errors(VP8D_COMP *pbi)
{
#if HAVE_NEON
int64_t dx_store_reg[8];
#endif
VP8_COMMON *cm = &pbi->common;
int retcode = -1;
pbi->common.error.error_code = VPX_CODEC_OK;
if (pbi->num_fragments == 0)
{
/* New frame, reset fragment pointers and sizes */
vpx_memset((void*)pbi->fragments, 0, sizeof(pbi->fragments));
vpx_memset(pbi->fragment_sizes, 0, sizeof(pbi->fragment_sizes));
}
if (pbi->input_fragments && !(source == NULL && size == 0))
{
/* Store a pointer to this fragment and return. We haven't
* received the complete frame yet, so we will wait with decoding.
*/
assert(pbi->num_fragments < MAX_PARTITIONS);
pbi->fragments[pbi->num_fragments] = source;
pbi->fragment_sizes[pbi->num_fragments] = size;
pbi->num_fragments++;
if (pbi->num_fragments > (1 << EIGHT_PARTITION) + 1)
{
pbi->common.error.error_code = VPX_CODEC_UNSUP_BITSTREAM;
pbi->common.error.setjmp = 0;
pbi->num_fragments = 0;
return -1;
}
return 0;
}
if (!pbi->input_fragments)
{
pbi->fragments[0] = source;
pbi->fragment_sizes[0] = size;
pbi->num_fragments = 1;
}
assert(pbi->common.multi_token_partition <= EIGHT_PARTITION);
if (pbi->num_fragments == 0)
{
pbi->num_fragments = 1;
pbi->fragments[0] = NULL;
pbi->fragment_sizes[0] = 0;
}
if (!pbi->ec_active &&
pbi->num_fragments <= 1 && pbi->fragment_sizes[0] == 0)
{
VP8_COMMON *cm = &pbi->common;
/* If error concealment is disabled we won't signal missing frames
* to the decoder.
*/
......@@ -360,12 +310,29 @@ int vp8dx_receive_compressed_data(VP8D_COMP *pbi, size_t size,
/* Signal that we have no frame to show. */
cm->show_frame = 0;
pbi->num_fragments = 0;
/* Nothing more to do. */
return 0;
}
return 1;
}
int vp8dx_receive_compressed_data(VP8D_COMP *pbi, size_t size,
const uint8_t *source,
int64_t time_stamp)
{
#if HAVE_NEON
int64_t dx_store_reg[8];
#endif
VP8_COMMON *cm = &pbi->common;
int retcode = -1;
pbi->common.error.error_code = VPX_CODEC_OK;
retcode = check_fragments_for_errors(pbi);
if(retcode <= 0)
return retcode;
#if HAVE_NEON
#if CONFIG_RUNTIME_CPU_DETECT
if (cm->cpu_caps & HAS_NEON)
......@@ -457,7 +424,6 @@ decode_exit:
#endif
pbi->common.error.setjmp = 0;
pbi->num_fragments = 0;
return retcode;
}
int vp8dx_get_raw_frame(VP8D_COMP *pbi, YV12_BUFFER_CONFIG *sd, int64_t *time_stamp, int64_t *time_end_stamp, vp8_ppflags_t *flags)
......
......@@ -33,6 +33,14 @@ typedef struct
MACROBLOCKD mbd;
} MB_ROW_DEC;
typedef struct
{
int enabled;
unsigned int count;
const unsigned char *ptrs[MAX_PARTITIONS];
unsigned int sizes[MAX_PARTITIONS];
} FRAGMENT_DATA;
typedef struct VP8D_COMP
{
DECLARE_ALIGNED(16, MACROBLOCKD, mb);
......
......@@ -77,6 +77,7 @@ struct vpx_codec_alg_priv
vpx_image_t img;
int img_setup;
void *user_priv;
FRAGMENT_DATA fragments;
};
static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t flags)
......@@ -215,6 +216,13 @@ static vpx_codec_err_t vp8_init(vpx_codec_ctx_t *ctx,
{
vp8_init_ctx(ctx, &mmap);
/* initialize number of fragments to zero */
ctx->priv->alg_priv->fragments.count = 0;
/* is input fragments enabled? */
ctx->priv->alg_priv->fragments.enabled =
(ctx->priv->alg_priv->base.init_flags &
VPX_CODEC_USE_INPUT_FRAGMENTS);
ctx->priv->alg_priv->defer_alloc = 1;
/*post processing level initialized to do nothing */
}
......@@ -343,6 +351,47 @@ static void yuvconfig2image(vpx_image_t *img,
img->self_allocd = 0;
}
static int
update_fragments(vpx_codec_alg_priv_t *ctx,
const uint8_t *data,
unsigned int data_sz,
vpx_codec_err_t *res)
{
*res = VPX_CODEC_OK;
if (ctx->fragments.count == 0)
{
/* New frame, reset fragment pointers and sizes */
vpx_memset((void*)ctx->fragments.ptrs, 0, sizeof(ctx->fragments.ptrs));
vpx_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.
*/
ctx->fragments.ptrs[ctx->fragments.count] = data;
ctx->fragments.sizes[ctx->fragments.count] = data_sz;
ctx->fragments.count++;
if (ctx->fragments.count > (1 << EIGHT_PARTITION) + 1)
{
ctx->fragments.count = 0;
*res = VPX_CODEC_INVALID_PARAM;
return -1;
}
return 0;
}
if (!ctx->fragments.enabled)
{
ctx->fragments.ptrs[0] = data;
ctx->fragments.sizes[0] = data_sz;
ctx->fragments.count = 1;
}
return 1;
}
static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
const uint8_t *data,
unsigned int data_sz,
......@@ -353,6 +402,11 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
unsigned int resolution_change = 0;
unsigned int w, h;
/* 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.
......@@ -360,7 +414,8 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
w = ctx->si.w;
h = ctx->si.h;
res = ctx->base.iface->dec.peek_si(data, data_sz, &ctx->si);
res = ctx->base.iface->dec.peek_si(ctx->fragments.ptrs[0],
ctx->fragments.sizes[0], &ctx->si);
if((res == VPX_CODEC_UNSUP_BITSTREAM) && !ctx->si.is_kf)
{
......@@ -421,8 +476,6 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
oxcf.max_threads = ctx->cfg.threads;
oxcf.error_concealment =
(ctx->base.init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT);
oxcf.input_fragments =
(ctx->base.init_flags & VPX_CODEC_USE_INPUT_FRAGMENTS);
optr = vp8dx_create_decompressor(&oxcf);
......@@ -544,12 +597,24 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
ctx->pbi->common.fb_idx_ref_cnt[0] = 0;
}
/* update the pbi fragment data */
ctx->pbi->num_fragments = ctx->fragments.count;
ctx->pbi->input_fragments = ctx->fragments.enabled;
vpx_memcpy(ctx->pbi->fragments, ctx->fragments.ptrs,
sizeof(ctx->fragments.ptrs));
vpx_memcpy(ctx->pbi->fragment_sizes, ctx->fragments.sizes,
sizeof(ctx->fragments.sizes));
ctx->user_priv = user_priv;
if (vp8dx_receive_compressed_data(ctx->pbi, data_sz, data, deadline))
{
VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi;
res = update_error_state(ctx, &pbi->common.error);
}
/* get ready for the next series of fragments */
ctx->fragments.count = 0;
}
return res;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment