History

adx: add an ADX parser.

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.

Justin Ruggles committed 14 years ago

Commit 27360cc1 parent d8cec2d7 files · +154 −60Browse files

Unified · Split

7 files
  1. libavcodec/Makefile +1 −0
  2. libavcodec/adx.h +1 −2
  3. libavcodec/adx_parser.c +104 −0
  4. libavcodec/adxdec.c +44 −56
  5. libavcodec/allcodecs.c +1 −0
  6. libavcodec/version.h +2 −2
  7. libavformat/segafilm.c +1 −0
libavcodec/Makefile+1−0
@@ -595,6 +595,7 @@ OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ · 594 unmodified lines
595595 aacadtsdec.o mpeg4audio.o
596596 OBJS-$(CONFIG_AC3_PARSER) += ac3_parser.o ac3tab.o \
597597 aac_ac3_parser.o
598+OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o
598599 OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o
599600 OBJS-$(CONFIG_DCA_PARSER) += dca_parser.o
600601 OBJS-$(CONFIG_DIRAC_PARSER) += dirac_parser.o
libavcodec/adx.h+1−2
@@ -43,8 +43,7 @@ typedef struct { · 42 unmodified lines
4343 int channels;
4444 ADXChannelState prev[2];
4545 int header_parsed;
46− unsigned char dec_temp[18*2];
47− int in_temp;
46+ int eof;
4847 int cutoff;
4948 int coeff[2];
5049 } ADXContext;
libavcodec/adx_parser.c+104−0
@@ -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+};
libavcodec/adxdec.c+44−56
@@ -35,6 +35,19 @@ · 34 unmodified lines
3535
3636 static av_cold int adx_decode_init(AVCodecContext *avctx)
3737 {
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+
3851 avctx->sample_fmt = AV_SAMPLE_FMT_S16;
3952 return 0;
4053 }
@@ -46,7 +59,7 @@ static av_cold int adx_decode_init(AVCodecContext *avctx) · 5 unmodified lines
4659 * 2nd-order LPC filter applied to it to form the output signal for a single
4760 * channel.
4861 */
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)
5063 {
5164 ADXChannelState *prev = &c->prev[ch];
5265 GetBitContext gb;
@@ -54,6 +67,10 @@ static void adx_decode(ADXContext *c, int16_t *out, const uint8_t *in, int ch) · 1 unmodified line
5467 int i;
5568 int s0, s1, s2, d;
5669
70+ /* check if this is an EOF packet */
71+ if (scale & 0x8000)
72+ return -1;
73+
5774 init_get_bits(&gb, in + 2, (BLOCK_SIZE - 2) * 8);
5875 s1 = prev->s1;
5976 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
6784 }
6885 prev->s1 = s1;
6986 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;
7787
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;
8489 }
8590
8691 static int adx_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
8792 AVPacket *avpkt)
8893 {
89− const uint8_t *buf0 = avpkt->data;
9094 int buf_size = avpkt->size;
9195 ADXContext *c = avctx->priv_data;
9296 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;
106103 }
107104
108105 /* 18 bytes of data are expanded into 32*2 bytes of audio,
109106 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);
111108 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);
114111 }
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+ }
117118 return AVERROR_INVALIDDATA;
118119 }
119120
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−
132121 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+ }
138131 samples += BLOCK_SAMPLES * c->channels;
139132 }
140133
141− c->in_temp = rest;
142− if (rest) {
143− memcpy(c->dec_temp, buf, rest);
144− buf += rest;
145− }
146134 *data_size = (uint8_t*)samples - (uint8_t*)data;
147− return buf - buf0;
135+ return buf - avpkt->data;
148136 }
149137
150138 AVCodec ff_adpcm_adx_decoder = {
libavcodec/allcodecs.c+1−0
@@ -388,6 +388,7 @@ void avcodec_register_all(void) · 387 unmodified lines
388388 REGISTER_PARSER (AAC, aac);
389389 REGISTER_PARSER (AAC_LATM, aac_latm);
390390 REGISTER_PARSER (AC3, ac3);
391+ REGISTER_PARSER (ADX, adx);
391392 REGISTER_PARSER (CAVSVIDEO, cavsvideo);
392393 REGISTER_PARSER (DCA, dca);
393394 REGISTER_PARSER (DIRAC, dirac);
libavcodec/version.h+2−2
@@ -21,8 +21,8 @@ · 20 unmodified lines
2121 #define AVCODEC_VERSION_H
2222
2323 #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
2626
2727 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
2828 LIBAVCODEC_VERSION_MINOR, \
libavformat/segafilm.c+1−0
@@ -172,6 +172,7 @@ static int film_read_header(AVFormatContext *s, · 171 unmodified lines
172172 if (film->audio_type == CODEC_ID_ADPCM_ADX) {
173173 st->codec->bits_per_coded_sample = 18 * 8 / 32;
174174 st->codec->block_align = st->codec->channels * 18;
175+ st->need_parsing = AVSTREAM_PARSE_FULL;
175176 } else {
176177 st->codec->bits_per_coded_sample = film->audio_bits;
177178 st->codec->block_align = st->codec->channels *

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t