summaryrefslogtreecommitdiff
path: root/libavcodec/parser.c
diff options
context:
space:
mode:
authorMåns Rullgård <mans@mansr.com>2006-01-21 18:19:47 +0000
committerMåns Rullgård <mans@mansr.com>2006-01-21 18:19:47 +0000
commit62327e2852ffe1c3088feafa0dfbd4ddb6632064 (patch)
treed49effc534403cb70b3728155da8f3aae0116ac6 /libavcodec/parser.c
parent13c71451350071888b5d690f9d48cd316e0d4aed (diff)
native ac3 parser
Originally committed as revision 4878 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/parser.c')
-rw-r--r--libavcodec/parser.c122
1 files changed, 96 insertions, 26 deletions
diff --git a/libavcodec/parser.c b/libavcodec/parser.c
index a21c6cfe30..9d424e9438 100644
--- a/libavcodec/parser.c
+++ b/libavcodec/parser.c
@@ -748,24 +748,106 @@ static int mpegaudio_parse(AVCodecParserContext *s1,
return buf_ptr - buf;
}
-#ifdef CONFIG_AC3
-#ifdef CONFIG_A52BIN
-extern int ff_a52_syncinfo (AVCodecContext * avctx, const uint8_t * buf,
- int * flags, int * sample_rate, int * bit_rate);
-#else
-extern int a52_syncinfo (const uint8_t * buf, int * flags,
- int * sample_rate, int * bit_rate);
-#endif
-
typedef struct AC3ParseContext {
uint8_t inbuf[4096]; /* input buffer */
uint8_t *inbuf_ptr;
int frame_size;
- int flags;
} AC3ParseContext;
#define AC3_HEADER_SIZE 7
-#define A52_LFE 16
+
+static const int ac3_sample_rates[4] = {
+ 48000, 44100, 32000, 0
+};
+
+static const int ac3_frame_sizes[64][3] = {
+ { 64, 69, 96 },
+ { 64, 70, 96 },
+ { 80, 87, 120 },
+ { 80, 88, 120 },
+ { 96, 104, 144 },
+ { 96, 105, 144 },
+ { 112, 121, 168 },
+ { 112, 122, 168 },
+ { 128, 139, 192 },
+ { 128, 140, 192 },
+ { 160, 174, 240 },
+ { 160, 175, 240 },
+ { 192, 208, 288 },
+ { 192, 209, 288 },
+ { 224, 243, 336 },
+ { 224, 244, 336 },
+ { 256, 278, 384 },
+ { 256, 279, 384 },
+ { 320, 348, 480 },
+ { 320, 349, 480 },
+ { 384, 417, 576 },
+ { 384, 418, 576 },
+ { 448, 487, 672 },
+ { 448, 488, 672 },
+ { 512, 557, 768 },
+ { 512, 558, 768 },
+ { 640, 696, 960 },
+ { 640, 697, 960 },
+ { 768, 835, 1152 },
+ { 768, 836, 1152 },
+ { 896, 975, 1344 },
+ { 896, 976, 1344 },
+ { 1024, 1114, 1536 },
+ { 1024, 1115, 1536 },
+ { 1152, 1253, 1728 },
+ { 1152, 1254, 1728 },
+ { 1280, 1393, 1920 },
+ { 1280, 1394, 1920 },
+};
+
+static const int ac3_bitrates[64] = {
+ 32, 32, 40, 40, 48, 48, 56, 56, 64, 64, 80, 80, 96, 96, 112, 112,
+ 128, 128, 160, 160, 192, 192, 224, 224, 256, 256, 320, 320, 384,
+ 384, 448, 448, 512, 512, 576, 576, 640, 640,
+};
+
+static const int ac3_channels[8] = {
+ 2, 1, 2, 3, 3, 4, 4, 5
+};
+
+static int ac3_sync(const uint8_t *buf, int *channels, int *sample_rate,
+ int *bit_rate)
+{
+ unsigned int fscod, frmsizecod, acmod, bsid, lfeon;
+ GetBitContext bits;
+
+ init_get_bits(&bits, buf, AC3_HEADER_SIZE * 8);
+
+ if(get_bits(&bits, 16) != 0x0b77)
+ return 0;
+
+ get_bits(&bits, 16); /* crc */
+ fscod = get_bits(&bits, 2);
+ frmsizecod = get_bits(&bits, 6);
+
+ if(!ac3_sample_rates[fscod])
+ return 0;
+
+ bsid = get_bits(&bits, 5);
+ if(bsid > 8)
+ return 0;
+ get_bits(&bits, 3); /* bsmod */
+ acmod = get_bits(&bits, 3);
+ if(acmod & 1 && acmod != 1)
+ get_bits(&bits, 2); /* cmixlev */
+ if(acmod & 4)
+ get_bits(&bits, 2); /* surmixlev */
+ if(acmod & 2)
+ get_bits(&bits, 2); /* dsurmod */
+ lfeon = get_bits(&bits, 1);
+
+ *sample_rate = ac3_sample_rates[fscod];
+ *bit_rate = ac3_bitrates[frmsizecod] * 1000;
+ *channels = ac3_channels[acmod] + lfeon;
+
+ return ac3_frame_sizes[frmsizecod][fscod] * 2;
+}
static int ac3_parse_init(AVCodecParserContext *s1)
{
@@ -781,10 +863,7 @@ static int ac3_parse(AVCodecParserContext *s1,
{
AC3ParseContext *s = s1->priv_data;
const uint8_t *buf_ptr;
- int len, sample_rate, bit_rate;
- static const int ac3_channels[8] = {
- 2, 1, 2, 3, 3, 4, 4, 5
- };
+ int len, sample_rate, bit_rate, channels;
*poutbuf = NULL;
*poutbuf_size = 0;
@@ -802,11 +881,7 @@ static int ac3_parse(AVCodecParserContext *s1,
s->inbuf_ptr += len;
buf_size -= len;
if ((s->inbuf_ptr - s->inbuf) == AC3_HEADER_SIZE) {
-#ifdef CONFIG_A52BIN
- len = ff_a52_syncinfo(avctx, s->inbuf, &s->flags, &sample_rate, &bit_rate);
-#else
- len = a52_syncinfo(s->inbuf, &s->flags, &sample_rate, &bit_rate);
-#endif
+ len = ac3_sync(s->inbuf, &channels, &sample_rate, &bit_rate);
if (len == 0) {
/* no sync found : move by one byte (inefficient, but simple!) */
memmove(s->inbuf, s->inbuf + 1, AC3_HEADER_SIZE - 1);
@@ -817,9 +892,7 @@ static int ac3_parse(AVCodecParserContext *s1,
avctx->sample_rate = sample_rate;
/* set channels,except if the user explicitly requests 1 or 2 channels, XXX/FIXME this is a bit ugly */
if(avctx->channels!=1 && avctx->channels!=2){
- avctx->channels = ac3_channels[s->flags & 7];
- if (s->flags & A52_LFE)
- avctx->channels++;
+ avctx->channels = channels;
}
avctx->bit_rate = bit_rate;
avctx->frame_size = 6 * 256;
@@ -844,7 +917,6 @@ static int ac3_parse(AVCodecParserContext *s1,
}
return buf_ptr - buf;
}
-#endif
AVCodecParser mpegvideo_parser = {
{ CODEC_ID_MPEG1VIDEO, CODEC_ID_MPEG2VIDEO },
@@ -872,7 +944,6 @@ AVCodecParser mpegaudio_parser = {
NULL,
};
-#ifdef CONFIG_AC3
AVCodecParser ac3_parser = {
{ CODEC_ID_AC3 },
sizeof(AC3ParseContext),
@@ -880,4 +951,3 @@ AVCodecParser ac3_parser = {
ac3_parse,
NULL,
};
-#endif