1 | /*
|
---|
2 | * Faad decoder
|
---|
3 | * Copyright (c) 2003 Zdenek Kabelac.
|
---|
4 | * Copyright (c) 2004 Thomas Raivio.
|
---|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 |
|
---|
31 | #ifndef FAADAPI
|
---|
32 | #define FAADAPI
|
---|
33 | #endif
|
---|
34 |
|
---|
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 {
|
---|
50 | void* handle; /* dlopen handle */
|
---|
51 | void* faac_handle; /* FAAD library handle */
|
---|
52 | int sample_size;
|
---|
53 | int init;
|
---|
54 |
|
---|
55 | /* faad calls */
|
---|
56 | faacDecHandle FAADAPI (*faacDecOpen)(void);
|
---|
57 | faacDecConfigurationPtr FAADAPI (*faacDecGetCurrentConfiguration)(faacDecHandle hDecoder);
|
---|
58 | #ifndef FAAD2_VERSION
|
---|
59 | int FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder,
|
---|
60 | faacDecConfigurationPtr config);
|
---|
61 | int FAADAPI (*faacDecInit)(faacDecHandle hDecoder,
|
---|
62 | unsigned char *buffer,
|
---|
63 | unsigned long *samplerate,
|
---|
64 | unsigned long *channels);
|
---|
65 | int FAADAPI (*faacDecInit2)(faacDecHandle hDecoder, unsigned char *pBuffer,
|
---|
66 | unsigned long SizeOfDecoderSpecificInfo,
|
---|
67 | unsigned long *samplerate, unsigned long *channels);
|
---|
68 | int FAADAPI (*faacDecDecode)(faacDecHandle hDecoder,
|
---|
69 | unsigned char *buffer,
|
---|
70 | unsigned long *bytesconsumed,
|
---|
71 | short *sample_buffer,
|
---|
72 | unsigned long *samples);
|
---|
73 | #else
|
---|
74 | unsigned char FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder,
|
---|
75 | faacDecConfigurationPtr config);
|
---|
76 | long FAADAPI (*faacDecInit)(faacDecHandle hDecoder,
|
---|
77 | unsigned char *buffer,
|
---|
78 | unsigned long buffer_size,
|
---|
79 | unsigned long *samplerate,
|
---|
80 | unsigned char *channels);
|
---|
81 | char FAADAPI (*faacDecInit2)(faacDecHandle hDecoder, unsigned char *pBuffer,
|
---|
82 | unsigned long SizeOfDecoderSpecificInfo,
|
---|
83 | unsigned long *samplerate, unsigned char *channels);
|
---|
84 | void *FAADAPI (*faacDecDecode)(faacDecHandle hDecoder,
|
---|
85 | faacDecFrameInfo *hInfo,
|
---|
86 | unsigned char *buffer,
|
---|
87 | unsigned long buffer_size);
|
---|
88 | char* FAADAPI (*faacDecGetErrorMessage)(unsigned char errcode);
|
---|
89 | #endif
|
---|
90 |
|
---|
91 | void FAADAPI (*faacDecClose)(faacDecHandle hDecoder);
|
---|
92 |
|
---|
93 |
|
---|
94 | } FAACContext;
|
---|
95 |
|
---|
96 | static const unsigned long faac_srates[] =
|
---|
97 | {
|
---|
98 | 96000, 88200, 64000, 48000, 44100, 32000,
|
---|
99 | 24000, 22050, 16000, 12000, 11025, 8000
|
---|
100 | };
|
---|
101 |
|
---|
102 | static int faac_init_mp4(AVCodecContext *avctx)
|
---|
103 | {
|
---|
104 | FAACContext *s = (FAACContext *) avctx->priv_data;
|
---|
105 | unsigned long samplerate;
|
---|
106 | #ifndef FAAD2_VERSION
|
---|
107 | unsigned long channels;
|
---|
108 | #else
|
---|
109 | unsigned char channels;
|
---|
110 | #endif
|
---|
111 | int r = 0;
|
---|
112 |
|
---|
113 | if (avctx->extradata){
|
---|
114 | r = s->faacDecInit2(s->faac_handle, (uint8_t*) avctx->extradata,
|
---|
115 | avctx->extradata_size,
|
---|
116 | &samplerate, &channels);
|
---|
117 | if (r < 0){
|
---|
118 | av_log(avctx, AV_LOG_ERROR,
|
---|
119 | "faacDecInit2 failed r:%d sr:%ld ch:%ld s:%d\n",
|
---|
120 | r, samplerate, (long)channels, avctx->extradata_size);
|
---|
121 | } else {
|
---|
122 | avctx->sample_rate = samplerate;
|
---|
123 | avctx->channels = channels;
|
---|
124 | s->init = 1;
|
---|
125 | }
|
---|
126 | }
|
---|
127 |
|
---|
128 | return r;
|
---|
129 | }
|
---|
130 |
|
---|
131 | static int faac_decode_frame(AVCodecContext *avctx,
|
---|
132 | void *data, int *data_size,
|
---|
133 | uint8_t *buf, int buf_size)
|
---|
134 | {
|
---|
135 | FAACContext *s = (FAACContext *) avctx->priv_data;
|
---|
136 | #ifndef FAAD2_VERSION
|
---|
137 | unsigned long bytesconsumed;
|
---|
138 | short *sample_buffer = NULL;
|
---|
139 | unsigned long samples;
|
---|
140 | int out;
|
---|
141 | #else
|
---|
142 | faacDecFrameInfo frame_info;
|
---|
143 | void *out;
|
---|
144 | #endif
|
---|
145 | if(buf_size == 0)
|
---|
146 | return 0;
|
---|
147 | #ifndef FAAD2_VERSION
|
---|
148 | out = s->faacDecDecode(s->faac_handle,
|
---|
149 | (unsigned char*)buf,
|
---|
150 | &bytesconsumed,
|
---|
151 | data,
|
---|
152 | &samples);
|
---|
153 | samples *= s->sample_size;
|
---|
154 | if (data_size)
|
---|
155 | *data_size = samples;
|
---|
156 | return (buf_size < (int)bytesconsumed)
|
---|
157 | ? buf_size : (int)bytesconsumed;
|
---|
158 | #else
|
---|
159 |
|
---|
160 | if(!s->init){
|
---|
161 | unsigned long srate;
|
---|
162 | unsigned char channels;
|
---|
163 | int r = s->faacDecInit(s->faac_handle, buf, buf_size, &srate, &channels);
|
---|
164 | if(r < 0){
|
---|
165 | av_log(avctx, AV_LOG_ERROR, "faac: codec init failed: %s\n",
|
---|
166 | s->faacDecGetErrorMessage(frame_info.error));
|
---|
167 | return -1;
|
---|
168 | }
|
---|
169 | avctx->sample_rate = srate;
|
---|
170 | avctx->channels = channels;
|
---|
171 | s->init = 1;
|
---|
172 | }
|
---|
173 |
|
---|
174 | out = s->faacDecDecode(s->faac_handle, &frame_info, (unsigned char*)buf, (unsigned long)buf_size);
|
---|
175 |
|
---|
176 | if (frame_info.error > 0) {
|
---|
177 | av_log(avctx, AV_LOG_ERROR, "faac: frame decoding failed: %s\n",
|
---|
178 | s->faacDecGetErrorMessage(frame_info.error));
|
---|
179 | return -1;
|
---|
180 | }
|
---|
181 |
|
---|
182 | frame_info.samples *= s->sample_size;
|
---|
183 | memcpy(data, out, frame_info.samples); // CHECKME - can we cheat this one
|
---|
184 |
|
---|
185 | if (data_size)
|
---|
186 | *data_size = frame_info.samples;
|
---|
187 |
|
---|
188 | return (buf_size < (int)frame_info.bytesconsumed)
|
---|
189 | ? buf_size : (int)frame_info.bytesconsumed;
|
---|
190 | #endif
|
---|
191 | }
|
---|
192 |
|
---|
193 | static int faac_decode_end(AVCodecContext *avctx)
|
---|
194 | {
|
---|
195 | FAACContext *s = (FAACContext *) avctx->priv_data;
|
---|
196 |
|
---|
197 | if (s->faacDecClose)
|
---|
198 | s->faacDecClose(s->faac_handle);
|
---|
199 |
|
---|
200 | dlclose(s->handle);
|
---|
201 | return 0;
|
---|
202 | }
|
---|
203 |
|
---|
204 | static int faac_decode_init(AVCodecContext *avctx)
|
---|
205 | {
|
---|
206 | FAACContext *s = (FAACContext *) avctx->priv_data;
|
---|
207 | faacDecConfigurationPtr faac_cfg;
|
---|
208 |
|
---|
209 | #ifdef CONFIG_FAADBIN
|
---|
210 | const char* err = 0;
|
---|
211 |
|
---|
212 | s->handle = dlopen(libfaadname, RTLD_LAZY);
|
---|
213 | if (!s->handle)
|
---|
214 | {
|
---|
215 | av_log(avctx, AV_LOG_ERROR, "FAAD library: %s could not be opened! \n%s\n",
|
---|
216 | libfaadname, dlerror());
|
---|
217 | return -1;
|
---|
218 | }
|
---|
219 | #define dfaac(a, b) \
|
---|
220 | do { static const char* n = "faacDec" #a; \
|
---|
221 | if ((s->faacDec ## a = b dlsym( s->handle, n )) == NULL) { err = n; break; } } while(0)
|
---|
222 | for(;;) {
|
---|
223 | #else /* !CONFIG_FAADBIN */
|
---|
224 | #define dfaac(a, b) s->faacDec ## a = faacDec ## a
|
---|
225 | #endif /* CONFIG_FAADBIN */
|
---|
226 |
|
---|
227 | // resolve all needed function calls
|
---|
228 | dfaac(Open, (faacDecHandle FAADAPI (*)(void)));
|
---|
229 | dfaac(GetCurrentConfiguration, (faacDecConfigurationPtr
|
---|
230 | FAADAPI (*)(faacDecHandle)));
|
---|
231 | #ifndef FAAD2_VERSION
|
---|
232 | dfaac(SetConfiguration, (int FAADAPI (*)(faacDecHandle,
|
---|
233 | faacDecConfigurationPtr)));
|
---|
234 |
|
---|
235 | dfaac(Init, (int FAADAPI (*)(faacDecHandle, unsigned char*,
|
---|
236 | unsigned long*, unsigned long*)));
|
---|
237 | dfaac(Init2, (int FAADAPI (*)(faacDecHandle, unsigned char*,
|
---|
238 | unsigned long, unsigned long*,
|
---|
239 | unsigned long*)));
|
---|
240 | dfaac(Close, (void FAADAPI (*)(faacDecHandle hDecoder)));
|
---|
241 | dfaac(Decode, (int FAADAPI (*)(faacDecHandle, unsigned char*,
|
---|
242 | unsigned long*, short*, unsigned long*)));
|
---|
243 | #else
|
---|
244 | dfaac(SetConfiguration, (unsigned char FAADAPI (*)(faacDecHandle,
|
---|
245 | faacDecConfigurationPtr)));
|
---|
246 | dfaac(Init, (long FAADAPI (*)(faacDecHandle, unsigned char*,
|
---|
247 | unsigned long, unsigned long*, unsigned char*)));
|
---|
248 | dfaac(Init2, (char FAADAPI (*)(faacDecHandle, unsigned char*,
|
---|
249 | unsigned long, unsigned long*,
|
---|
250 | unsigned char*)));
|
---|
251 | dfaac(Decode, (void *FAADAPI (*)(faacDecHandle, faacDecFrameInfo*,
|
---|
252 | unsigned char*, unsigned long)));
|
---|
253 | dfaac(GetErrorMessage, (char* FAADAPI (*)(unsigned char)));
|
---|
254 | #endif
|
---|
255 | #undef dfacc
|
---|
256 |
|
---|
257 | #ifdef CONFIG_FAADBIN
|
---|
258 | break;
|
---|
259 | }
|
---|
260 | if (err) {
|
---|
261 | dlclose(s->handle);
|
---|
262 | av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot resolve %s in %s!\n",
|
---|
263 | err, libfaadname);
|
---|
264 | return -1;
|
---|
265 | }
|
---|
266 | #endif
|
---|
267 |
|
---|
268 | s->faac_handle = s->faacDecOpen();
|
---|
269 | if (!s->faac_handle) {
|
---|
270 | av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot create handler!\n");
|
---|
271 | faac_decode_end(avctx);
|
---|
272 | return -1;
|
---|
273 | }
|
---|
274 |
|
---|
275 |
|
---|
276 | faac_cfg = s->faacDecGetCurrentConfiguration(s->faac_handle);
|
---|
277 |
|
---|
278 | if (faac_cfg) {
|
---|
279 | switch (avctx->bits_per_sample) {
|
---|
280 | case 8: av_log(avctx, AV_LOG_ERROR, "FAADlib unsupported bps %d\n", avctx->bits_per_sample); break;
|
---|
281 | default:
|
---|
282 | case 16:
|
---|
283 | #ifdef FAAD2_VERSION
|
---|
284 | faac_cfg->outputFormat = FAAD_FMT_16BIT;
|
---|
285 | #endif
|
---|
286 | s->sample_size = 2;
|
---|
287 | break;
|
---|
288 | case 24:
|
---|
289 | #ifdef FAAD2_VERSION
|
---|
290 | faac_cfg->outputFormat = FAAD_FMT_24BIT;
|
---|
291 | #endif
|
---|
292 | s->sample_size = 3;
|
---|
293 | break;
|
---|
294 | case 32:
|
---|
295 | #ifdef FAAD2_VERSION
|
---|
296 | faac_cfg->outputFormat = FAAD_FMT_32BIT;
|
---|
297 | #endif
|
---|
298 | s->sample_size = 4;
|
---|
299 | break;
|
---|
300 | }
|
---|
301 |
|
---|
302 | faac_cfg->defSampleRate = (!avctx->sample_rate) ? 44100 : avctx->sample_rate;
|
---|
303 | faac_cfg->defObjectType = LC;
|
---|
304 | }
|
---|
305 |
|
---|
306 | s->faacDecSetConfiguration(s->faac_handle, faac_cfg);
|
---|
307 |
|
---|
308 | faac_init_mp4(avctx);
|
---|
309 |
|
---|
310 | return 0;
|
---|
311 | }
|
---|
312 |
|
---|
313 | #define AAC_CODEC(id, name) \
|
---|
314 | AVCodec name ## _decoder = { \
|
---|
315 | #name, \
|
---|
316 | CODEC_TYPE_AUDIO, \
|
---|
317 | id, \
|
---|
318 | sizeof(FAACContext), \
|
---|
319 | faac_decode_init, \
|
---|
320 | NULL, \
|
---|
321 | faac_decode_end, \
|
---|
322 | faac_decode_frame, \
|
---|
323 | }
|
---|
324 |
|
---|
325 | // FIXME - raw AAC files - maybe just one entry will be enough
|
---|
326 | AAC_CODEC(CODEC_ID_AAC, aac);
|
---|
327 | // If it's mp4 file - usually embeded into Qt Mov
|
---|
328 | AAC_CODEC(CODEC_ID_MPEG4AAC, mpeg4aac);
|
---|
329 |
|
---|
330 | #undef AAC_CODEC
|
---|