Mercurial > libavcodec.hg
annotate liba52.c @ 5310:9aa9197034d7 libavcodec
AC-3 decoder, soc revision 40, Aug 9 00:10:14 2006 UTC by cloud9
More code cleanup.
Window is now runtime generated.
Fixed the bugs in rematrixing routine and
in Decoding AC3 Bitstreams when coupling is in use.
Still struggling to find out what affects the quality of
the produced sound. Can anybody have a look at the
imdct routines do_imdct_256 and do_imdct_512 and tell me
whether it is the correctly implemented as described in
standard.
author | jbr |
---|---|
date | Sat, 14 Jul 2007 15:57:51 +0000 |
parents | 4323e587708d |
children | c2ab2ac31edb |
rev | line source |
---|---|
332 | 1 /* |
4617 | 2 * A52 decoder using liba52 |
429 | 3 * Copyright (c) 2001 Fabrice Bellard. |
332 | 4 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
429 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
332 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
332 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
429 | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 * Lesser General Public License for more details. | |
332 | 16 * |
429 | 17 * You should have received a copy of the GNU Lesser General Public |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3059
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2979
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
332 | 20 */ |
1106 | 21 |
22 /** | |
23 * @file a52dec.c | |
4617 | 24 * A52 decoder using liba52 |
1106 | 25 */ |
26 | |
332 | 27 #include "avcodec.h" |
4511
91872ae737b2
Remove internal liba52; external lib still works, native decoder coming up.
diego
parents:
4356
diff
changeset
|
28 #include <a52dec/a52.h> |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
29 |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
30 #ifdef CONFIG_LIBA52BIN |
332 | 31 #include <dlfcn.h> |
32 static const char* liba52name = "liba52.so.0"; | |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
33 #endif |
332 | 34 |
35 /** | |
36 * liba52 - Copyright (C) Aaron Holtzman | |
37 * released under the GPL license. | |
38 */ | |
39 typedef struct AC3DecodeState { | |
1064 | 40 uint8_t inbuf[4096]; /* input buffer */ |
41 uint8_t *inbuf_ptr; | |
332 | 42 int frame_size; |
43 int flags; | |
44 int channels; | |
45 a52_state_t* state; | |
46 sample_t* samples; | |
47 | |
48 /* | |
49 * virtual method table | |
50 * | |
51 * using this function table so the liba52 doesn't | |
52 * have to be really linked together with ffmpeg | |
53 * and might be linked in runtime - this allows binary | |
54 * distribution of ffmpeg library which doens't depend | |
55 * on liba52 library - but if user has it installed | |
56 * it will be used - user might install such library | |
57 * separately | |
58 */ | |
59 void* handle; | |
60 a52_state_t* (*a52_init)(uint32_t mm_accel); | |
61 sample_t* (*a52_samples)(a52_state_t * state); | |
62 int (*a52_syncinfo)(uint8_t * buf, int * flags, | |
2979 | 63 int * sample_rate, int * bit_rate); |
332 | 64 int (*a52_frame)(a52_state_t * state, uint8_t * buf, int * flags, |
2979 | 65 sample_t * level, sample_t bias); |
332 | 66 void (*a52_dynrng)(a52_state_t * state, |
2979 | 67 sample_t (* call) (sample_t, void *), void * data); |
332 | 68 int (*a52_block)(a52_state_t * state); |
69 void (*a52_free)(a52_state_t * state); | |
70 | |
71 } AC3DecodeState; | |
72 | |
4618
bb06df70f857
Add proper #idef to dlsymm call, also fixes an unresolved symbol on OS X 10.2.
diego
parents:
4617
diff
changeset
|
73 #ifdef CONFIG_LIBA52BIN |
332 | 74 static void* dlsymm(void* handle, const char* symbol) |
75 { | |
76 void* f = dlsym(handle, symbol); | |
77 if (!f) | |
2846
40765c51a7a9
Compilation fixes part 1 patch by (Arvind R. and Burkhard Plaum, plaum, ipf uni-stuttgart de)
michael
parents:
2028
diff
changeset
|
78 av_log( NULL, AV_LOG_ERROR, "A52 Decoder - function '%s' can't be resolved\n", symbol); |
332 | 79 return f; |
80 } | |
4618
bb06df70f857
Add proper #idef to dlsymm call, also fixes an unresolved symbol on OS X 10.2.
diego
parents:
4617
diff
changeset
|
81 #endif |
332 | 82 |
83 static int a52_decode_init(AVCodecContext *avctx) | |
84 { | |
85 AC3DecodeState *s = avctx->priv_data; | |
86 | |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
87 #ifdef CONFIG_LIBA52BIN |
332 | 88 s->handle = dlopen(liba52name, RTLD_LAZY); |
89 if (!s->handle) | |
90 { | |
2846
40765c51a7a9
Compilation fixes part 1 patch by (Arvind R. and Burkhard Plaum, plaum, ipf uni-stuttgart de)
michael
parents:
2028
diff
changeset
|
91 av_log( avctx, AV_LOG_ERROR, "A52 library %s could not be opened! \n%s\n", liba52name, dlerror()); |
332 | 92 return -1; |
93 } | |
94 s->a52_init = (a52_state_t* (*)(uint32_t)) dlsymm(s->handle, "a52_init"); | |
95 s->a52_samples = (sample_t* (*)(a52_state_t*)) dlsymm(s->handle, "a52_samples"); | |
96 s->a52_syncinfo = (int (*)(uint8_t*, int*, int*, int*)) dlsymm(s->handle, "a52_syncinfo"); | |
97 s->a52_frame = (int (*)(a52_state_t*, uint8_t*, int*, sample_t*, sample_t)) dlsymm(s->handle, "a52_frame"); | |
98 s->a52_block = (int (*)(a52_state_t*)) dlsymm(s->handle, "a52_block"); | |
99 s->a52_free = (void (*)(a52_state_t*)) dlsymm(s->handle, "a52_free"); | |
100 if (!s->a52_init || !s->a52_samples || !s->a52_syncinfo | |
101 || !s->a52_frame || !s->a52_block || !s->a52_free) | |
102 { | |
2979 | 103 dlclose(s->handle); |
332 | 104 return -1; |
105 } | |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
106 #else |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
107 s->handle = 0; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
108 s->a52_init = a52_init; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
109 s->a52_samples = a52_samples; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
110 s->a52_syncinfo = a52_syncinfo; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
111 s->a52_frame = a52_frame; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
112 s->a52_block = a52_block; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
113 s->a52_free = a52_free; |
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
114 #endif |
332 | 115 s->state = s->a52_init(0); /* later use CPU flags */ |
116 s->samples = s->a52_samples(s->state); | |
117 s->inbuf_ptr = s->inbuf; | |
118 s->frame_size = 0; | |
119 | |
120 return 0; | |
121 } | |
122 | |
123 /**** the following two functions comes from a52dec */ | |
124 static inline int blah (int32_t i) | |
125 { | |
126 if (i > 0x43c07fff) | |
2979 | 127 return 32767; |
332 | 128 else if (i < 0x43bf8000) |
2979 | 129 return -32768; |
332 | 130 return i - 0x43c00000; |
131 } | |
132 | |
1064 | 133 static inline void float_to_int (float * _f, int16_t * s16, int nchannels) |
332 | 134 { |
135 int i, j, c; | |
2979 | 136 int32_t * f = (int32_t *) _f; // XXX assumes IEEE float format |
332 | 137 |
138 j = 0; | |
139 nchannels *= 256; | |
140 for (i = 0; i < 256; i++) { | |
2979 | 141 for (c = 0; c < nchannels; c += 256) |
142 s16[j++] = blah (f[i + c]); | |
332 | 143 } |
144 } | |
145 | |
146 /**** end */ | |
147 | |
148 #define HEADER_SIZE 7 | |
149 | |
150 static int a52_decode_frame(AVCodecContext *avctx, | |
151 void *data, int *data_size, | |
1064 | 152 uint8_t *buf, int buf_size) |
332 | 153 { |
154 AC3DecodeState *s = avctx->priv_data; | |
1064 | 155 uint8_t *buf_ptr; |
332 | 156 int flags, i, len; |
157 int sample_rate, bit_rate; | |
158 short *out_samples = data; | |
159 float level; | |
160 static const int ac3_channels[8] = { | |
2979 | 161 2, 1, 2, 3, 3, 4, 4, 5 |
332 | 162 }; |
163 | |
4356
c8bc01fee409
set data_size to 0 so that in case we return without setting it nothing funny can happen
michael
parents:
4343
diff
changeset
|
164 *data_size= 0; |
c8bc01fee409
set data_size to 0 so that in case we return without setting it nothing funny can happen
michael
parents:
4343
diff
changeset
|
165 |
332 | 166 buf_ptr = buf; |
167 while (buf_size > 0) { | |
168 len = s->inbuf_ptr - s->inbuf; | |
169 if (s->frame_size == 0) { | |
170 /* no header seen : find one. We need at least 7 bytes to parse it */ | |
171 len = HEADER_SIZE - len; | |
172 if (len > buf_size) | |
173 len = buf_size; | |
174 memcpy(s->inbuf_ptr, buf_ptr, len); | |
175 buf_ptr += len; | |
176 s->inbuf_ptr += len; | |
177 buf_size -= len; | |
178 if ((s->inbuf_ptr - s->inbuf) == HEADER_SIZE) { | |
179 len = s->a52_syncinfo(s->inbuf, &s->flags, &sample_rate, &bit_rate); | |
180 if (len == 0) { | |
181 /* no sync found : move by one byte (inefficient, but simple!) */ | |
182 memcpy(s->inbuf, s->inbuf + 1, HEADER_SIZE - 1); | |
183 s->inbuf_ptr--; | |
184 } else { | |
2979 | 185 s->frame_size = len; |
332 | 186 /* update codec info */ |
187 avctx->sample_rate = sample_rate; | |
188 s->channels = ac3_channels[s->flags & 7]; | |
189 if (s->flags & A52_LFE) | |
2979 | 190 s->channels++; |
191 if (avctx->channels == 0) | |
192 /* No specific number of channel requested */ | |
193 avctx->channels = s->channels; | |
194 else if (s->channels < avctx->channels) { | |
195 av_log(avctx, AV_LOG_ERROR, "ac3dec: AC3 Source channels are less than specified: output to %d channels.. (frmsize: %d)\n", s->channels, len); | |
196 avctx->channels = s->channels; | |
197 } | |
198 avctx->bit_rate = bit_rate; | |
332 | 199 } |
200 } | |
201 } else if (len < s->frame_size) { | |
202 len = s->frame_size - len; | |
203 if (len > buf_size) | |
204 len = buf_size; | |
205 | |
206 memcpy(s->inbuf_ptr, buf_ptr, len); | |
207 buf_ptr += len; | |
208 s->inbuf_ptr += len; | |
209 buf_size -= len; | |
210 } else { | |
211 flags = s->flags; | |
212 if (avctx->channels == 1) | |
213 flags = A52_MONO; | |
214 else if (avctx->channels == 2) | |
215 flags = A52_STEREO; | |
216 else | |
217 flags |= A52_ADJUST_LEVEL; | |
218 level = 1; | |
219 if (s->a52_frame(s->state, s->inbuf, &flags, &level, 384)) { | |
220 fail: | |
4343 | 221 av_log(avctx, AV_LOG_ERROR, "Error decoding frame\n"); |
332 | 222 s->inbuf_ptr = s->inbuf; |
223 s->frame_size = 0; | |
224 continue; | |
225 } | |
226 for (i = 0; i < 6; i++) { | |
227 if (s->a52_block(s->state)) | |
228 goto fail; | |
229 float_to_int(s->samples, out_samples + i * 256 * avctx->channels, avctx->channels); | |
230 } | |
231 s->inbuf_ptr = s->inbuf; | |
232 s->frame_size = 0; | |
1064 | 233 *data_size = 6 * avctx->channels * 256 * sizeof(int16_t); |
332 | 234 break; |
235 } | |
236 } | |
237 return buf_ptr - buf; | |
238 } | |
239 | |
240 static int a52_decode_end(AVCodecContext *avctx) | |
241 { | |
242 AC3DecodeState *s = avctx->priv_data; | |
243 s->a52_free(s->state); | |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
244 #ifdef CONFIG_LIBA52BIN |
332 | 245 dlclose(s->handle); |
4514
790d1cb93686
Restore the possibility to link liba52 instead of dlopening.
diego
parents:
4513
diff
changeset
|
246 #endif |
332 | 247 return 0; |
248 } | |
249 | |
4513
3367310f8460
Rename ac3 decoder to liba52 to prepare for native decoder.
diego
parents:
4511
diff
changeset
|
250 AVCodec liba52_decoder = { |
5102
4323e587708d
Give names of external library decoders/encoders a lib prefix
diego
parents:
5101
diff
changeset
|
251 "liba52", |
332 | 252 CODEC_TYPE_AUDIO, |
253 CODEC_ID_AC3, | |
254 sizeof(AC3DecodeState), | |
255 a52_decode_init, | |
256 NULL, | |
257 a52_decode_end, | |
258 a52_decode_frame, | |
259 }; |