annotate ac3_parser.c @ 5319:40af705cef7e libavcodec

AC-3 decoder, soc revision 69, Aug 31 07:12:56 2006 UTC by cloud9 Fix the bugs: 1. The quality of output because of incorrect windowing coefficients. New code for window generation. 2. Dynrng values were reset where dynrng value is present in the first block, but not in the subsequent block.
author jbr
date Sat, 14 Jul 2007 16:03:14 +0000
parents b42e963c8149
children b24bcdd0ae86
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)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
47 return -1;
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)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
52 return -2;
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)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
57 return -3;
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)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
61 return -4;
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);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
67 if((hdr->acmod & 1) && hdr->acmod != 1) {
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 }
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
73 if(hdr->acmod == 2) {
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;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
117 fscod = get_bits(&bits, 2);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
118 if (fscod == 3) {
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
119 fscod2 = get_bits(&bits, 2);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
120 numblkscod = 3;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
121
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
122 if(fscod2 == 3)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
123 return 0;
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 *sample_rate = ff_ac3_freqs[fscod2] / 2;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
126 } else {
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
127 numblkscod = get_bits(&bits, 2);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
128
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
129 *sample_rate = ff_ac3_freqs[fscod];
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
130 }
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 acmod = get_bits(&bits, 3);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
133 lfeon = get_bits1(&bits);
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 *samples = eac3_blocks[numblkscod] * 256;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
136 *bit_rate = frmsiz * (*sample_rate) * 16 / (*samples);
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
137 *channels = ff_ac3_channels[acmod] + lfeon;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
138
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
139 return frmsiz * 2;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
140 }
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 /* Unsupported bitstream version */
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
143 return 0;
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
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
146 static int ac3_parse_init(AVCodecParserContext *s1)
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
147 {
4942
b42e963c8149 cosmetics: rename for consistency after previous aac and ac3 parsers move
aurel
parents: 4941
diff changeset
148 AACAC3ParseContext *s = s1->priv_data;
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
149 s->inbuf_ptr = s->inbuf;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
150 s->header_size = AC3_HEADER_SIZE;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
151 s->sync = ac3_sync;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
152 return 0;
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
153 }
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
154
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
155
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
156 AVCodecParser ac3_parser = {
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
157 { CODEC_ID_AC3 },
4942
b42e963c8149 cosmetics: rename for consistency after previous aac and ac3 parsers move
aurel
parents: 4941
diff changeset
158 sizeof(AACAC3ParseContext),
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
159 ac3_parse_init,
4942
b42e963c8149 cosmetics: rename for consistency after previous aac and ac3 parsers move
aurel
parents: 4941
diff changeset
160 ff_aac_ac3_parse,
4941
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
161 NULL,
c3ee5c30c297 move aac and ac3 parsers in their own files
aurel
parents:
diff changeset
162 };