Mercurial > libavcodec.hg
annotate faad.c @ 3014:959b8ad880dc libavcodec
Dual mono stereo strems sound ok now, added sanity checks and removed
some unused variables and redundant memsets.
Patch by Benjamin Larsson
author | rtognimp |
---|---|
date | Fri, 06 Jan 2006 12:41:57 +0000 |
parents | bfabfdf9ce55 |
children | 0b546eab515d |
rev | line source |
---|---|
1245 | 1 /* |
2 * Faad decoder | |
3 * Copyright (c) 2003 Zdenek Kabelac. | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
4 * Copyright (c) 2004 Thomas Raivio. |
1245 | 5 * |
6 * This library 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 of the License, or (at your option) any later version. | |
10 * | |
11 * This library 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 this library; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 */ | |
20 | |
21 /** | |
22 * @file faad.c | |
23 * AAC decoder. | |
24 * | |
25 * still a bit unfinished - but it plays something | |
26 */ | |
27 | |
28 #include "avcodec.h" | |
29 #include "faad.h" | |
30 | |
2061
c28b03fea50f
Building with faad2-cvs fix by ("Steven M. Schultz" <sms at 2bsd dot com>)
michael
parents:
2059
diff
changeset
|
31 #ifndef FAADAPI |
c28b03fea50f
Building with faad2-cvs fix by ("Steven M. Schultz" <sms at 2bsd dot com>)
michael
parents:
2059
diff
changeset
|
32 #define FAADAPI |
c28b03fea50f
Building with faad2-cvs fix by ("Steven M. Schultz" <sms at 2bsd dot com>)
michael
parents:
2059
diff
changeset
|
33 #endif |
c28b03fea50f
Building with faad2-cvs fix by ("Steven M. Schultz" <sms at 2bsd dot com>)
michael
parents:
2059
diff
changeset
|
34 |
1245 | 35 /* |
36 * when CONFIG_FAADBIN is defined the libfaad will be opened at runtime | |
37 */ | |
38 //#undef CONFIG_FAADBIN | |
39 //#define CONFIG_FAADBIN | |
40 | |
41 #ifdef CONFIG_FAADBIN | |
42 #include <dlfcn.h> | |
43 static const char* libfaadname = "libfaad.so.0"; | |
44 #else | |
45 #define dlopen(a) | |
46 #define dlclose(a) | |
47 #endif | |
48 | |
49 typedef struct { | |
2979 | 50 void* handle; /* dlopen handle */ |
51 void* faac_handle; /* FAAD library handle */ | |
1245 | 52 int frame_size; |
53 int sample_size; | |
54 int flags; | |
55 | |
56 /* faad calls */ | |
57 faacDecHandle FAADAPI (*faacDecOpen)(void); | |
58 faacDecConfigurationPtr FAADAPI (*faacDecGetCurrentConfiguration)(faacDecHandle hDecoder); | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
59 #ifndef FAAD2_VERSION |
2979 | 60 int FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder, |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
61 faacDecConfigurationPtr config); |
2979 | 62 int FAADAPI (*faacDecInit)(faacDecHandle hDecoder, |
63 unsigned char *buffer, | |
64 unsigned long *samplerate, | |
65 unsigned long *channels); | |
66 int FAADAPI (*faacDecInit2)(faacDecHandle hDecoder, unsigned char *pBuffer, | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
67 unsigned long SizeOfDecoderSpecificInfo, |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
68 unsigned long *samplerate, unsigned long *channels); |
2979 | 69 int FAADAPI (*faacDecDecode)(faacDecHandle hDecoder, |
70 unsigned char *buffer, | |
71 unsigned long *bytesconsumed, | |
72 short *sample_buffer, | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
73 unsigned long *samples); |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
74 #else |
2979 | 75 unsigned char FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder, |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
76 faacDecConfigurationPtr config); |
2979 | 77 long FAADAPI (*faacDecInit)(faacDecHandle hDecoder, |
78 unsigned char *buffer, | |
79 unsigned long buffer_size, | |
80 unsigned long *samplerate, | |
81 unsigned char *channels); | |
82 char FAADAPI (*faacDecInit2)(faacDecHandle hDecoder, unsigned char *pBuffer, | |
1245 | 83 unsigned long SizeOfDecoderSpecificInfo, |
84 unsigned long *samplerate, unsigned char *channels); | |
2979 | 85 void *FAADAPI (*faacDecDecode)(faacDecHandle hDecoder, |
86 faacDecFrameInfo *hInfo, | |
87 unsigned char *buffer, | |
88 unsigned long buffer_size); | |
89 char* FAADAPI (*faacDecGetErrorMessage)(unsigned char errcode); | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
90 #endif |
2967 | 91 |
1245 | 92 void FAADAPI (*faacDecClose)(faacDecHandle hDecoder); |
2967 | 93 |
94 | |
1245 | 95 } FAACContext; |
96 | |
97 static const unsigned long faac_srates[] = | |
98 { | |
99 96000, 88200, 64000, 48000, 44100, 32000, | |
100 24000, 22050, 16000, 12000, 11025, 8000 | |
101 }; | |
102 | |
103 static int faac_init_mp4(AVCodecContext *avctx) | |
104 { | |
105 FAACContext *s = (FAACContext *) avctx->priv_data; | |
106 unsigned long samplerate; | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
107 #ifndef FAAD2_VERSION |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
108 unsigned long channels; |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
109 #else |
1245 | 110 unsigned char channels; |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
111 #endif |
1245 | 112 int r = 0; |
113 | |
114 if (avctx->extradata) | |
2979 | 115 r = s->faacDecInit2(s->faac_handle, (uint8_t*) avctx->extradata, |
116 avctx->extradata_size, | |
117 &samplerate, &channels); | |
1245 | 118 // else r = s->faacDecInit(s->faac_handle ... ); |
119 | |
120 if (r < 0) | |
2979 | 121 av_log(avctx, AV_LOG_ERROR, "faacDecInit2 failed r:%d sr:%ld ch:%ld s:%d\n", |
122 r, samplerate, (long)channels, avctx->extradata_size); | |
2059
ad972ab280bc
sample_rate and channels in aac audio patch by (Luca Abeni <lucabe72 at email dot it>)
michael
parents:
1929
diff
changeset
|
123 avctx->sample_rate = samplerate; |
ad972ab280bc
sample_rate and channels in aac audio patch by (Luca Abeni <lucabe72 at email dot it>)
michael
parents:
1929
diff
changeset
|
124 avctx->channels = channels; |
ad972ab280bc
sample_rate and channels in aac audio patch by (Luca Abeni <lucabe72 at email dot it>)
michael
parents:
1929
diff
changeset
|
125 |
1245 | 126 return r; |
127 } | |
128 | |
129 static int faac_decode_frame(AVCodecContext *avctx, | |
130 void *data, int *data_size, | |
131 uint8_t *buf, int buf_size) | |
132 { | |
133 FAACContext *s = (FAACContext *) avctx->priv_data; | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
134 #ifndef FAAD2_VERSION |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
135 unsigned long bytesconsumed; |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
136 short *sample_buffer = NULL; |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
137 unsigned long samples; |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
138 int out; |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
139 #else |
1245 | 140 faacDecFrameInfo frame_info; |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
141 void *out; |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
142 #endif |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
143 if(buf_size == 0) |
2979 | 144 return 0; |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
145 #ifndef FAAD2_VERSION |
2967 | 146 out = s->faacDecDecode(s->faac_handle, |
147 (unsigned char*)buf, | |
148 &bytesconsumed, | |
149 data, | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
150 &samples); |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
151 samples *= s->sample_size; |
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
152 if (data_size) |
2979 | 153 *data_size = samples; |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
154 return (buf_size < (int)bytesconsumed) |
2979 | 155 ? buf_size : (int)bytesconsumed; |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
156 #else |
2967 | 157 |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
158 out = s->faacDecDecode(s->faac_handle, &frame_info, (unsigned char*)buf, (unsigned long)buf_size); |
1245 | 159 |
160 if (frame_info.error > 0) { | |
2979 | 161 av_log(avctx, AV_LOG_ERROR, "faac: frame decoding failed: %s\n", |
162 s->faacDecGetErrorMessage(frame_info.error)); | |
1245 | 163 return 0; |
164 } | |
165 | |
166 frame_info.samples *= s->sample_size; | |
167 memcpy(data, out, frame_info.samples); // CHECKME - can we cheat this one | |
168 | |
169 if (data_size) | |
2979 | 170 *data_size = frame_info.samples; |
1245 | 171 |
172 return (buf_size < (int)frame_info.bytesconsumed) | |
2979 | 173 ? buf_size : (int)frame_info.bytesconsumed; |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
174 #endif |
1245 | 175 } |
176 | |
177 static int faac_decode_end(AVCodecContext *avctx) | |
178 { | |
179 FAACContext *s = (FAACContext *) avctx->priv_data; | |
180 | |
181 if (s->faacDecClose) | |
182 s->faacDecClose(s->faac_handle); | |
183 | |
184 dlclose(s->handle); | |
185 return 0; | |
186 } | |
187 | |
188 static int faac_decode_init(AVCodecContext *avctx) | |
189 { | |
190 FAACContext *s = (FAACContext *) avctx->priv_data; | |
191 faacDecConfigurationPtr faac_cfg; | |
192 | |
193 #ifdef CONFIG_FAADBIN | |
194 const char* err = 0; | |
195 | |
196 s->handle = dlopen(libfaadname, RTLD_LAZY); | |
197 if (!s->handle) | |
198 { | |
2979 | 199 av_log(avctx, AV_LOG_ERROR, "FAAD library: %s could not be opened! \n%s\n", |
200 libfaadname, dlerror()); | |
1245 | 201 return -1; |
202 } | |
203 #define dfaac(a, b) \ | |
204 do { static const char* n = "faacDec" #a; \ | |
205 if ((s->faacDec ## a = b dlsym( s->handle, n )) == NULL) { err = n; break; } } while(0) | |
206 for(;;) { | |
207 #else /* !CONFIG_FAADBIN */ | |
208 #define dfaac(a, b) s->faacDec ## a = faacDec ## a | |
209 #endif /* CONFIG_FAADBIN */ | |
210 | |
211 // resolve all needed function calls | |
2979 | 212 dfaac(Open, (faacDecHandle FAADAPI (*)(void))); |
213 dfaac(GetCurrentConfiguration, (faacDecConfigurationPtr | |
214 FAADAPI (*)(faacDecHandle))); | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
215 #ifndef FAAD2_VERSION |
2979 | 216 dfaac(SetConfiguration, (int FAADAPI (*)(faacDecHandle, |
217 faacDecConfigurationPtr))); | |
1245 | 218 |
2979 | 219 dfaac(Init, (int FAADAPI (*)(faacDecHandle, unsigned char*, |
220 unsigned long*, unsigned long*))); | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
221 dfaac(Init2, (int FAADAPI (*)(faacDecHandle, unsigned char*, |
2979 | 222 unsigned long, unsigned long*, |
223 unsigned long*))); | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
224 dfaac(Close, (void FAADAPI (*)(faacDecHandle hDecoder))); |
2979 | 225 dfaac(Decode, (int FAADAPI (*)(faacDecHandle, unsigned char*, |
226 unsigned long*, short*, unsigned long*))); | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
227 #else |
2979 | 228 dfaac(SetConfiguration, (unsigned char FAADAPI (*)(faacDecHandle, |
229 faacDecConfigurationPtr))); | |
230 dfaac(Init, (long FAADAPI (*)(faacDecHandle, unsigned char*, | |
231 unsigned long, unsigned long*, unsigned char*))); | |
232 dfaac(Init2, (char FAADAPI (*)(faacDecHandle, unsigned char*, | |
233 unsigned long, unsigned long*, | |
234 unsigned char*))); | |
235 dfaac(Decode, (void *FAADAPI (*)(faacDecHandle, faacDecFrameInfo*, | |
236 unsigned char*, unsigned long))); | |
237 dfaac(GetErrorMessage, (char* FAADAPI (*)(unsigned char))); | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
238 #endif |
1245 | 239 #undef dfacc |
240 | |
241 #ifdef CONFIG_FAADBIN | |
242 break; | |
243 } | |
244 if (err) { | |
245 dlclose(s->handle); | |
2979 | 246 av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot resolve %s in %s!\n", |
247 err, libfaadname); | |
1245 | 248 return -1; |
249 } | |
250 #endif | |
251 | |
252 s->faac_handle = s->faacDecOpen(); | |
253 if (!s->faac_handle) { | |
1602
fdb8244da1e5
av_log patch(2 of ?) by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1245
diff
changeset
|
254 av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot create handler!\n"); |
1245 | 255 faac_decode_end(avctx); |
256 return -1; | |
257 } | |
258 | |
259 | |
260 faac_cfg = s->faacDecGetCurrentConfiguration(s->faac_handle); | |
261 | |
262 if (faac_cfg) { | |
2979 | 263 switch (avctx->bits_per_sample) { |
264 case 8: av_log(avctx, AV_LOG_ERROR, "FAADlib unsupported bps %d\n", avctx->bits_per_sample); break; | |
265 default: | |
266 case 16: | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
267 #ifdef FAAD2_VERSION |
2979 | 268 faac_cfg->outputFormat = FAAD_FMT_16BIT; |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
269 #endif |
2979 | 270 s->sample_size = 2; |
271 break; | |
272 case 24: | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
273 #ifdef FAAD2_VERSION |
2979 | 274 faac_cfg->outputFormat = FAAD_FMT_24BIT; |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
275 #endif |
2979 | 276 s->sample_size = 3; |
277 break; | |
278 case 32: | |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
279 #ifdef FAAD2_VERSION |
2979 | 280 faac_cfg->outputFormat = FAAD_FMT_32BIT; |
1929
d4525c3065d0
aac decoding patch by ("Thomas Raivio" <tjraivio at cc dot hut dot fi>)
michael
parents:
1602
diff
changeset
|
281 #endif |
2979 | 282 s->sample_size = 4; |
283 break; | |
284 } | |
1245 | 285 |
2979 | 286 faac_cfg->defSampleRate = (!avctx->sample_rate) ? 44100 : avctx->sample_rate; |
287 faac_cfg->defObjectType = LC; | |
1245 | 288 } |
289 | |
290 s->faacDecSetConfiguration(s->faac_handle, faac_cfg); | |
291 | |
292 faac_init_mp4(avctx); | |
293 | |
294 return 0; | |
295 } | |
296 | |
297 #define AAC_CODEC(id, name) \ | |
298 AVCodec name ## _decoder = { \ | |
299 #name, \ | |
300 CODEC_TYPE_AUDIO, \ | |
301 id, \ | |
302 sizeof(FAACContext), \ | |
303 faac_decode_init, \ | |
304 NULL, \ | |
305 faac_decode_end, \ | |
306 faac_decode_frame, \ | |
307 } | |
308 | |
309 // FIXME - raw AAC files - maybe just one entry will be enough | |
310 AAC_CODEC(CODEC_ID_AAC, aac); | |
311 // If it's mp4 file - usually embeded into Qt Mov | |
312 AAC_CODEC(CODEC_ID_MPEG4AAC, mpeg4aac); | |
313 | |
314 #undef AAC_CODEC |