annotate ac3_parser.c @ 5875:5a61e8e2f65c libavcodec

Remove libvorbis Vorbis decoding support. Our native decoder is complete and has no known bugs, any remaining issues will hopefully be uncovered now.
author diego
date Sun, 04 Nov 2007 12:55:32 +0000
parents ced30500e2b1
children 29635f7c3d9c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
1 /*
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
2 * AC3 parser
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
3 * Copyright (c) 2003 Fabrice Bellard.
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
4 * Copyright (c) 2003 Michael Niedermayer.
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
5 *
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
6 * This file is part of FFmpeg.
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
7 *
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
8 * FFmpeg is free software; you can redistribute it and/or
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
9 * modify it under the terms of the GNU Lesser General Public
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
10 * License as published by the Free Software Foundation; either
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
11 * version 2.1 of the License, or (at your option) any later version.
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
12 *
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
13 * FFmpeg is distributed in the hope that it will be useful,
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
16 * Lesser General Public License for more details.
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
17 *
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
18 * You should have received a copy of the GNU Lesser General Public
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
19 * License along with FFmpeg; if not, write to the Free Software
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
21 */
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
22
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
23 #include "parser.h"
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
24 #include "ac3_parser.h"
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
25 #include "aac_ac3_parser.h"
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
26 #include "bitstream.h"
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
27
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
28
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
29 #define AC3_HEADER_SIZE 7
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
30
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
31
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
32 static const uint8_t eac3_blocks[4] = {
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
33 1, 2, 3, 6
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
34 };
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
35
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
36
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
37 int ff_ac3_parse_header(const uint8_t buf[7], AC3HeaderInfo *hdr)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
38 {
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
39 GetBitContext gbc;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
40
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
41 memset(hdr, 0, sizeof(*hdr));
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
42
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
43 init_get_bits(&gbc, buf, 54);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
44
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
45 hdr->sync_word = get_bits(&gbc, 16);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
46 if(hdr->sync_word != 0x0B77)
5680
5ae5a74b0e4b better AC3 header error reporting
jbr
parents: 5331
diff changeset
47 return AC3_PARSE_ERROR_SYNC;
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
48
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
49 /* read ahead to bsid to make sure this is AC-3, not E-AC-3 */
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
50 hdr->bsid = show_bits_long(&gbc, 29) & 0x1F;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
51 if(hdr->bsid > 10)
5680
5ae5a74b0e4b better AC3 header error reporting
jbr
parents: 5331
diff changeset
52 return AC3_PARSE_ERROR_BSID;
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
53
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
54 hdr->crc1 = get_bits(&gbc, 16);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
55 hdr->fscod = get_bits(&gbc, 2);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
56 if(hdr->fscod == 3)
5680
5ae5a74b0e4b better AC3 header error reporting
jbr
parents: 5331
diff changeset
57 return AC3_PARSE_ERROR_SAMPLE_RATE;
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
58
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
59 hdr->frmsizecod = get_bits(&gbc, 6);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
60 if(hdr->frmsizecod > 37)
5680
5ae5a74b0e4b better AC3 header error reporting
jbr
parents: 5331
diff changeset
61 return AC3_PARSE_ERROR_FRAME_SIZE;
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
62
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
63 skip_bits(&gbc, 5); // skip bsid, already got it
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
64
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
65 hdr->bsmod = get_bits(&gbc, 3);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
66 hdr->acmod = get_bits(&gbc, 3);
5331
b24bcdd0ae86 move some common values to ac3.h and utilize them
jbr
parents: 4942
diff changeset
67 if((hdr->acmod & 1) && hdr->acmod != AC3_ACMOD_MONO) {
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
68 hdr->cmixlev = get_bits(&gbc, 2);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
69 }
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
70 if(hdr->acmod & 4) {
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
71 hdr->surmixlev = get_bits(&gbc, 2);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
72 }
5331
b24bcdd0ae86 move some common values to ac3.h and utilize them
jbr
parents: 4942
diff changeset
73 if(hdr->acmod == AC3_ACMOD_STEREO) {
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
74 hdr->dsurmod = get_bits(&gbc, 2);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
75 }
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
76 hdr->lfeon = get_bits1(&gbc);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
77
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
78 hdr->halfratecod = FFMAX(hdr->bsid, 8) - 8;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
79 hdr->sample_rate = ff_ac3_freqs[hdr->fscod] >> hdr->halfratecod;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
80 hdr->bit_rate = (ff_ac3_bitratetab[hdr->frmsizecod>>1] * 1000) >> hdr->halfratecod;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
81 hdr->channels = ff_ac3_channels[hdr->acmod] + hdr->lfeon;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
82 hdr->frame_size = ff_ac3_frame_sizes[hdr->frmsizecod][hdr->fscod] * 2;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
83
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
84 return 0;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
85 }
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
86
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
87 static int ac3_sync(const uint8_t *buf, int *channels, int *sample_rate,
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
88 int *bit_rate, int *samples)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
89 {
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
90 int err;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
91 unsigned int fscod, acmod, bsid, lfeon;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
92 unsigned int strmtyp, substreamid, frmsiz, fscod2, numblkscod;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
93 GetBitContext bits;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
94 AC3HeaderInfo hdr;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
95
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
96 err = ff_ac3_parse_header(buf, &hdr);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
97
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
98 if(err < 0 && err != -2)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
99 return 0;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
100
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
101 bsid = hdr.bsid;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
102 if(bsid <= 10) { /* Normal AC-3 */
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
103 *sample_rate = hdr.sample_rate;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
104 *bit_rate = hdr.bit_rate;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
105 *channels = hdr.channels;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
106 *samples = AC3_FRAME_SIZE;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
107 return hdr.frame_size;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
108 } else if (bsid > 10 && bsid <= 16) { /* Enhanced AC-3 */
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
109 init_get_bits(&bits, &buf[2], (AC3_HEADER_SIZE-2) * 8);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
110 strmtyp = get_bits(&bits, 2);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
111 substreamid = get_bits(&bits, 3);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
112
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
113 if (strmtyp != 0 || substreamid != 0)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
114 return 0; /* Currently don't support additional streams */
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
115
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
116 frmsiz = get_bits(&bits, 11) + 1;
5817
ced30500e2b1 prevent infinite loop and memcpy of negative amounts
michael
parents: 5680
diff changeset
117 if(frmsiz*2 < AC3_HEADER_SIZE)
ced30500e2b1 prevent infinite loop and memcpy of negative amounts
michael
parents: 5680
diff changeset
118 return 0;
ced30500e2b1 prevent infinite loop and memcpy of negative amounts
michael
parents: 5680
diff changeset
119
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
120 fscod = get_bits(&bits, 2);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
121 if (fscod == 3) {
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
122 fscod2 = get_bits(&bits, 2);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
123 numblkscod = 3;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
124
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
125 if(fscod2 == 3)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
126 return 0;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
127
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
128 *sample_rate = ff_ac3_freqs[fscod2] / 2;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
129 } else {
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
130 numblkscod = get_bits(&bits, 2);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
131
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
132 *sample_rate = ff_ac3_freqs[fscod];
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
133 }
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
134
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
135 acmod = get_bits(&bits, 3);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
136 lfeon = get_bits1(&bits);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
137
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
138 *samples = eac3_blocks[numblkscod] * 256;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
139 *bit_rate = frmsiz * (*sample_rate) * 16 / (*samples);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
140 *channels = ff_ac3_channels[acmod] + lfeon;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
141
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
142 return frmsiz * 2;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
143 }
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
144
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
145 /* Unsupported bitstream version */
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
146 return 0;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
147 }
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
148
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
149 static int ac3_parse_init(AVCodecParserContext *s1)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
150 {
4942
b42e963c8149 cosmetics: rename for consistency after previous aac and ac3 parsers move
aurel
parents: 4941
diff changeset
151 AACAC3ParseContext *s = s1->priv_data;
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
152 s->inbuf_ptr = s->inbuf;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
153 s->header_size = AC3_HEADER_SIZE;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
154 s->sync = ac3_sync;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
155 return 0;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
156 }
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
157
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
158
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
159 AVCodecParser ac3_parser = {
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
160 { CODEC_ID_AC3 },
4942
b42e963c8149 cosmetics: rename for consistency after previous aac and ac3 parsers move
aurel
parents: 4941
diff changeset
161 sizeof(AACAC3ParseContext),
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
162 ac3_parse_init,
4942
b42e963c8149 cosmetics: rename for consistency after previous aac and ac3 parsers move
aurel
parents: 4941
diff changeset
163 ff_aac_ac3_parse,
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
164 NULL,
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
165 };