diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2011-12-18 18:57:56 +0100 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2012-01-03 16:28:17 -0500 |
commit | b024209b1fe57b7902d30a8e0d38f5ecb628e6f3 (patch) | |
tree | f3c2839c916f5e4bc0b261cfc7e02cb9ec91ea2b /libavcodec | |
parent | 6fd075f1806e375f66ce436cca15e085f0088118 (diff) | |
download | ffmpeg-b024209b1fe57b7902d30a8e0d38f5ecb628e6f3.tar.gz |
adx_parser: rewrite.
The previous code ended in multiple different infinite
loops. See stl_ten_1_big.sfd as example with and without zzuf
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Signed-off-by: Justin Ruggles <justin.ruggles@gmail.com>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/adx_parser.c | 65 |
1 files changed, 27 insertions, 38 deletions
diff --git a/libavcodec/adx_parser.c b/libavcodec/adx_parser.c index ebcb1370e5..de3b1b073f 100644 --- a/libavcodec/adx_parser.c +++ b/libavcodec/adx_parser.c @@ -22,7 +22,7 @@ * @file * ADX audio parser * - * Reads header to extradata and splits packets into individual blocks. + * Splits packets into individual blocks. */ #include "libavutil/intreadwrite.h" @@ -33,11 +33,9 @@ typedef struct ADXParseContext { ParseContext pc; int header_size; int block_size; - int buf_pos; + int remaining; } ADXParseContext; -#define MIN_HEADER_SIZE 24 - static int adx_parse(AVCodecParserContext *s1, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, @@ -46,45 +44,36 @@ static int adx_parse(AVCodecParserContext *s1, ADXParseContext *s = s1->priv_data; ParseContext *pc = &s->pc; int next = END_NOT_FOUND; + int i; + uint64_t state = pc->state64; - if (!avctx->extradata_size) { - int ret; - - ff_combine_frame(pc, END_NOT_FOUND, &buf, &buf_size); - - if (!s->header_size && pc->index >= MIN_HEADER_SIZE) { - if (ret = avpriv_adx_decode_header(avctx, pc->buffer, pc->index, - &s->header_size, NULL)) - return AVERROR_INVALIDDATA; - s->block_size = BLOCK_SIZE * avctx->channels; - } - if (s->header_size && s->header_size <= pc->index) { - avctx->extradata = av_mallocz(s->header_size + FF_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) - return AVERROR(ENOMEM); - avctx->extradata_size = s->header_size; - memcpy(avctx->extradata, pc->buffer, s->header_size); - memmove(pc->buffer, pc->buffer + s->header_size, s->header_size); - pc->index -= s->header_size; + if (!s->header_size) { + for (i = 0; i < buf_size; i++) { + state = (state << 8) | buf[i]; + /* check for fixed fields in ADX header for possible match */ + if ((state & 0xFFFF0000FFFFFF00) == 0x8000000003120400ULL) { + int channels = state & 0xFF; + int header_size = ((state >> 32) & 0xFFFF) + 4; + if (channels > 0 && header_size >= 8) { + s->header_size = header_size; + s->block_size = BLOCK_SIZE * channels; + s->remaining = i - 7 + s->header_size + s->block_size; + break; + } + } } - *poutbuf = NULL; - *poutbuf_size = 0; - return buf_size; + pc->state64 = state; } - if (pc->index - s->buf_pos >= s->block_size) { - *poutbuf = &pc->buffer[s->buf_pos]; - *poutbuf_size = s->block_size; - s->buf_pos += s->block_size; - return 0; - } - if (pc->index && s->buf_pos) { - memmove(pc->buffer, &pc->buffer[s->buf_pos], pc->index - s->buf_pos); - pc->index -= s->buf_pos; - s->buf_pos = 0; + if (s->header_size) { + if (!s->remaining) + s->remaining = s->block_size; + if (s->remaining <= buf_size) { + next = s->remaining; + s->remaining = 0; + } else + s->remaining -= buf_size; } - if (buf_size + pc->index >= s->block_size) - next = s->block_size - pc->index; if (ff_combine_frame(pc, next, &buf, &buf_size) < 0 || !buf_size) { *poutbuf = NULL; |