This simplifies the decoder so it doesn't have to process an in-packet header or handle arbitrary-sized packets. It also fixes decoding of files with large headers.
Unified · Split
| @@ -595,6 +595,7 @@ OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ · 594 unmodified lines | ||
| 595 | 595 | aacadtsdec.o mpeg4audio.o |
| 596 | 596 | OBJS-$(CONFIG_AC3_PARSER) += ac3_parser.o ac3tab.o \ |
| 597 | 597 | aac_ac3_parser.o |
| 598 | +OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o | |
| 598 | 599 | OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o |
| 599 | 600 | OBJS-$(CONFIG_DCA_PARSER) += dca_parser.o |
| 600 | 601 | OBJS-$(CONFIG_DIRAC_PARSER) += dirac_parser.o |
| @@ -43,8 +43,7 @@ typedef struct { · 42 unmodified lines | ||
| 43 | 43 | int channels; |
| 44 | 44 | ADXChannelState prev[2]; |
| 45 | 45 | int header_parsed; |
| 46 | − unsigned char dec_temp[18*2]; | |
| 47 | − int in_temp; | |
| 46 | + int eof; | |
| 48 | 47 | int cutoff; |
| 49 | 48 | int coeff[2]; |
| 50 | 49 | } ADXContext; |
| @@ -0,0 +1,104 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2011 Justin Ruggles | |
| 3 | + * | |
| 4 | + * This file is part of Libav. | |
| 5 | + * | |
| 6 | + * Libav is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU Lesser General Public | |
| 8 | + * License as published by the Free Software Foundation; either | |
| 9 | + * version 2.1 of the License, or (at your option) any later version. | |
| 10 | + * | |
| 11 | + * Libav is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 | + * Lesser General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public | |
| 17 | + * License along with Libav; if not, write to the Free Software | |
| 18 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 19 | + */ | |
| 20 | + | |
| 21 | +/** | |
| 22 | + * @file | |
| 23 | + * ADX audio parser | |
| 24 | + * | |
| 25 | + * Reads header to extradata and splits packets into individual blocks. | |
| 26 | + */ | |
| 27 | + | |
| 28 | +#include "libavutil/intreadwrite.h" | |
| 29 | +#include "parser.h" | |
| 30 | +#include "adx.h" | |
| 31 | + | |
| 32 | +typedef struct ADXParseContext { | |
| 33 | + ParseContext pc; | |
| 34 | + int header_size; | |
| 35 | + int block_size; | |
| 36 | + int buf_pos; | |
| 37 | +} ADXParseContext; | |
| 38 | + | |
| 39 | +#define MIN_HEADER_SIZE 24 | |
| 40 | + | |
| 41 | +static int adx_parse(AVCodecParserContext *s1, | |
| 42 | + AVCodecContext *avctx, | |
| 43 | + const uint8_t **poutbuf, int *poutbuf_size, | |
| 44 | + const uint8_t *buf, int buf_size) | |
| 45 | +{ | |
| 46 | + ADXParseContext *s = s1->priv_data; | |
| 47 | + ParseContext *pc = &s->pc; | |
| 48 | + int next = END_NOT_FOUND; | |
| 49 | + | |
| 50 | + if (!avctx->extradata_size) { | |
| 51 | + int ret; | |
| 52 | + | |
| 53 | + ff_combine_frame(pc, END_NOT_FOUND, &buf, &buf_size); | |
| 54 | + | |
| 55 | + if (!s->header_size && pc->index >= MIN_HEADER_SIZE) { | |
| 56 | + if (ret = ff_adx_decode_header(avctx, pc->buffer, pc->index, | |
| 57 | + &s->header_size, NULL)) | |
| 58 | + return AVERROR_INVALIDDATA; | |
| 59 | + s->block_size = BLOCK_SIZE * avctx->channels; | |
| 60 | + } | |
| 61 | + if (s->header_size && s->header_size <= pc->index) { | |
| 62 | + avctx->extradata = av_mallocz(s->header_size + FF_INPUT_BUFFER_PADDING_SIZE); | |
| 63 | + if (!avctx->extradata) | |
| 64 | + return AVERROR(ENOMEM); | |
| 65 | + avctx->extradata_size = s->header_size; | |
| 66 | + memcpy(avctx->extradata, pc->buffer, s->header_size); | |
| 67 | + memmove(pc->buffer, pc->buffer + s->header_size, s->header_size); | |
| 68 | + pc->index -= s->header_size; | |
| 69 | + } | |
| 70 | + *poutbuf = NULL; | |
| 71 | + *poutbuf_size = 0; | |
| 72 | + return buf_size; | |
| 73 | + } | |
| 74 | + | |
| 75 | + if (pc->index - s->buf_pos >= s->block_size) { | |
| 76 | + *poutbuf = &pc->buffer[s->buf_pos]; | |
| 77 | + *poutbuf_size = s->block_size; | |
| 78 | + s->buf_pos += s->block_size; | |
| 79 | + return 0; | |
| 80 | + } | |
| 81 | + if (pc->index && s->buf_pos) { | |
| 82 | + memmove(pc->buffer, &pc->buffer[s->buf_pos], pc->index - s->buf_pos); | |
| 83 | + pc->index -= s->buf_pos; | |
| 84 | + s->buf_pos = 0; | |
| 85 | + } | |
| 86 | + if (buf_size + pc->index >= s->block_size) | |
| 87 | + next = s->block_size - pc->index; | |
| 88 | + | |
| 89 | + if (ff_combine_frame(pc, next, &buf, &buf_size) < 0 || !buf_size) { | |
| 90 | + *poutbuf = NULL; | |
| 91 | + *poutbuf_size = 0; | |
| 92 | + return buf_size; | |
| 93 | + } | |
| 94 | + *poutbuf = buf; | |
| 95 | + *poutbuf_size = buf_size; | |
| 96 | + return next; | |
| 97 | +} | |
| 98 | + | |
| 99 | +AVCodecParser ff_adx_parser = { | |
| 100 | + .codec_ids = { CODEC_ID_ADPCM_ADX }, | |
| 101 | + .priv_data_size = sizeof(ADXParseContext), | |
| 102 | + .parser_parse = adx_parse, | |
| 103 | + .parser_close = ff_parse_close, | |
| 104 | +}; | |
| @@ -35,6 +35,19 @@ · 34 unmodified lines | ||
| 35 | 35 | |
| 36 | 36 | static av_cold int adx_decode_init(AVCodecContext *avctx) |
| 37 | 37 | { |
| 38 | + ADXContext *c = avctx->priv_data; | |
| 39 | + int ret, header_size; | |
| 40 | + | |
| 41 | + if (avctx->extradata_size < 24) | |
| 42 | + return AVERROR_INVALIDDATA; | |
| 43 | + | |
| 44 | + if ((ret = ff_adx_decode_header(avctx, avctx->extradata, avctx->extradata_size, | |
| 45 | + &header_size, c->coeff)) < 0) { | |
| 46 | + av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n"); | |
| 47 | + return AVERROR_INVALIDDATA; | |
| 48 | + } | |
| 49 | + c->channels = avctx->channels; | |
| 50 | + | |
| 38 | 51 | avctx->sample_fmt = AV_SAMPLE_FMT_S16; |
| 39 | 52 | return 0; |
| 40 | 53 | } |
| @@ -46,7 +59,7 @@ static av_cold int adx_decode_init(AVCodecContext *avctx) · 5 unmodified lines | ||
| 46 | 59 | * 2nd-order LPC filter applied to it to form the output signal for a single |
| 47 | 60 | * channel. |
| 48 | 61 | */ |
| 49 | −static void adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch) | |
| 62 | +static int adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch) | |
| 50 | 63 | { |
| 51 | 64 | ADXChannelState *prev = &c->prev[ch]; |
| 52 | 65 | GetBitContext gb; |
| @@ -54,6 +67,10 @@ static void adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch) · 1 unmodified line | ||
| 54 | 67 | int i; |
| 55 | 68 | int s0, s1, s2, d; |
| 56 | 69 | |
| 70 | + /* check if this is an EOF packet */ | |
| 71 | + if (scale & 0x8000) | |
| 72 | + return -1; | |
| 73 | + | |
| 57 | 74 | init_get_bits(&gb, in + 2, (BLOCK_SIZE - 2) * 8); |
| 58 | 75 | s1 = prev->s1; |
| 59 | 76 | s2 = prev->s2; |
| @@ -67,84 +84,55 @@ static void adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch) · 7 unmodified lines | ||
| 67 | 84 | } |
| 68 | 85 | prev->s1 = s1; |
| 69 | 86 | prev->s2 = s2; |
| 70 | −} | |
| 71 | − | |
| 72 | −static int adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, | |
| 73 | − int bufsize) | |
| 74 | −{ | |
| 75 | − ADXContext *c = avctx->priv_data; | |
| 76 | − int ret, header_size; | |
| 77 | 87 | |
| 78 | − if ((ret = ff_adx_decode_header(avctx, buf, bufsize, &header_size, | |
| 79 | − c->coeff)) < 0) | |
| 80 | − return ret; | |
| 81 | − | |
| 82 | − c->channels = avctx->channels; | |
| 83 | − return header_size; | |
| 88 | + return 0; | |
| 84 | 89 | } |
| 85 | 90 | |
| 86 | 91 | static int adx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
| 87 | 92 | AVPacket *avpkt) |
| 88 | 93 | { |
| 89 | − const uint8_t *buf0 = avpkt->data; | |
| 90 | 94 | int buf_size = avpkt->size; |
| 91 | 95 | ADXContext *c = avctx->priv_data; |
| 92 | 96 | int16_t *samples = data; |
| 93 | − const uint8_t *buf = buf0; | |
| 94 | − int rest = buf_size; | |
| 95 | − int num_blocks; | |
| 96 | − | |
| 97 | − if (!c->header_parsed) { | |
| 98 | − int hdrsize = adx_decode_header(avctx, buf, rest); | |
| 99 | − if (hdrsize < 0) { | |
| 100 | − av_log(avctx, AV_LOG_ERROR, "invalid stream header\n"); | |
| 101 | − return hdrsize; | |
| 102 | − } | |
| 103 | − c->header_parsed = 1; | |
| 104 | − buf += hdrsize; | |
| 105 | − rest -= hdrsize; | |
| 97 | + const uint8_t *buf = avpkt->data; | |
| 98 | + int num_blocks, ch; | |
| 99 | + | |
| 100 | + if (c->eof) { | |
| 101 | + *data_size = 0; | |
| 102 | + return buf_size; | |
| 106 | 103 | } |
| 107 | 104 | |
| 108 | 105 | /* 18 bytes of data are expanded into 32*2 bytes of audio, |
| 109 | 106 | so guard against buffer overflows */ |
| 110 | − num_blocks = (rest + c->in_temp) / (BLOCK_SIZE * c->channels); | |
| 107 | + num_blocks = buf_size / (BLOCK_SIZE * c->channels); | |
| 111 | 108 | if (num_blocks > *data_size / (BLOCK_SAMPLES * c->channels)) { |
| 112 | − rest = (*data_size / (BLOCK_SAMPLES * c->channels)) * BLOCK_SIZE; | |
| 113 | − num_blocks = (rest + c->in_temp) / (BLOCK_SIZE * c->channels); | |
| 109 | + buf_size = (*data_size / (BLOCK_SAMPLES * c->channels)) * BLOCK_SIZE; | |
| 110 | + num_blocks = buf_size / (BLOCK_SIZE * c->channels); | |
| 114 | 111 | } |
| 115 | − if (!num_blocks) { | |
| 116 | − av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); | |
| 112 | + if (!buf_size || buf_size % (BLOCK_SIZE * avctx->channels)) { | |
| 113 | + if (buf_size >= 4 && (AV_RB16(buf) & 0x8000)) { | |
| 114 | + c->eof = 1; | |
| 115 | + *data_size = 0; | |
| 116 | + return avpkt->size; | |
| 117 | + } | |
| 117 | 118 | return AVERROR_INVALIDDATA; |
| 118 | 119 | } |
| 119 | 120 | |
| 120 | − if (c->in_temp) { | |
| 121 | − int copysize = BLOCK_SIZE * avctx->channels - c->in_temp; | |
| 122 | − memcpy(c->dec_temp + c->in_temp, buf, copysize); | |
| 123 | − rest -= copysize; | |
| 124 | − buf += copysize; | |
| 125 | − adx_decode(c, samples, c->dec_temp, 0); | |
| 126 | − if (avctx->channels == 2) | |
| 127 | − adx_decode(c, samples + 1, c->dec_temp + BLOCK_SIZE, 1); | |
| 128 | − samples += BLOCK_SAMPLES * c->channels; | |
| 129 | − num_blocks--; | |
| 130 | − } | |
| 131 | − | |
| 132 | 121 | while (num_blocks--) { |
| 133 | − adx_decode(c, samples, buf, 0); | |
| 134 | − if (c->channels == 2) | |
| 135 | − adx_decode(c, samples + 1, buf + BLOCK_SIZE, 1); | |
| 136 | − rest -= BLOCK_SIZE * c->channels; | |
| 137 | − buf += BLOCK_SIZE * c->channels; | |
| 122 | + for (ch = 0; ch < c->channels; ch++) { | |
| 123 | + if (adx_decode(c, samples + ch, buf, ch)) { | |
| 124 | + c->eof = 1; | |
| 125 | + buf = avpkt->data + avpkt->size; | |
| 126 | + break; | |
| 127 | + } | |
| 128 | + buf_size -= BLOCK_SIZE; | |
| 129 | + buf += BLOCK_SIZE; | |
| 130 | + } | |
| 138 | 131 | samples += BLOCK_SAMPLES * c->channels; |
| 139 | 132 | } |
| 140 | 133 | |
| 141 | − c->in_temp = rest; | |
| 142 | − if (rest) { | |
| 143 | − memcpy(c->dec_temp, buf, rest); | |
| 144 | − buf += rest; | |
| 145 | − } | |
| 146 | 134 | *data_size = (uint8_t*)samples - (uint8_t*)data; |
| 147 | − return buf - buf0; | |
| 135 | + return buf - avpkt->data; | |
| 148 | 136 | } |
| 149 | 137 | |
| 150 | 138 | AVCodec ff_adpcm_adx_decoder = { |
| @@ -388,6 +388,7 @@ void avcodec_register_all(void) · 387 unmodified lines | ||
| 388 | 388 | REGISTER_PARSER (AAC, aac); |
| 389 | 389 | REGISTER_PARSER (AAC_LATM, aac_latm); |
| 390 | 390 | REGISTER_PARSER (AC3, ac3); |
| 391 | + REGISTER_PARSER (ADX, adx); | |
| 391 | 392 | REGISTER_PARSER (CAVSVIDEO, cavsvideo); |
| 392 | 393 | REGISTER_PARSER (DCA, dca); |
| 393 | 394 | REGISTER_PARSER (DIRAC, dirac); |
| @@ -21,8 +21,8 @@ · 20 unmodified lines | ||
| 21 | 21 | #define AVCODEC_VERSION_H |
| 22 | 22 | |
| 23 | 23 | #define LIBAVCODEC_VERSION_MAJOR 53 |
| 24 | −#define LIBAVCODEC_VERSION_MINOR 22 | |
| 25 | −#define LIBAVCODEC_VERSION_MICRO 1 | |
| 24 | +#define LIBAVCODEC_VERSION_MINOR 23 | |
| 25 | +#define LIBAVCODEC_VERSION_MICRO 0 | |
| 26 | 26 | |
| 27 | 27 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ |
| 28 | 28 | LIBAVCODEC_VERSION_MINOR, \ |
| @@ -172,6 +172,7 @@ static int film_read_header(AVFormatContext *s, · 171 unmodified lines | ||
| 172 | 172 | if (film->audio_type == CODEC_ID_ADPCM_ADX) { |
| 173 | 173 | st->codec->bits_per_coded_sample = 18 * 8 / 32; |
| 174 | 174 | st->codec->block_align = st->codec->channels * 18; |
| 175 | + st->need_parsing = AVSTREAM_PARSE_FULL; | |
| 175 | 176 | } else { |
| 176 | 177 | st->codec->bits_per_coded_sample = film->audio_bits; |
| 177 | 178 | st->codec->block_align = st->codec->channels * |