Statistics
| Branch: | Revision:

ffmpeg / libavcodec / faad.c @ 08842d13

History | View | Annotate | Download (10.8 KB)

1 280bd7b7 Zdenek Kabelac
/*
2
 * Faad decoder
3
 * Copyright (c) 2003 Zdenek Kabelac.
4 931c85d0 Thomas Raivio
 * Copyright (c) 2004 Thomas Raivio.
5 280bd7b7 Zdenek Kabelac
 *
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 5509bffa Diego Biurrun
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 280bd7b7 Zdenek Kabelac
 */
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 305fa264 Michael Niedermayer
#ifndef FAADAPI
32
#define FAADAPI
33
#endif
34
35 280bd7b7 Zdenek Kabelac
/*
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 bb270c08 Diego Biurrun
    void* handle;               /* dlopen handle */
51
    void* faac_handle;          /* FAAD library handle */
52 280bd7b7 Zdenek Kabelac
    int sample_size;
53 79b0b66b Måns Rullgård
    int init;
54 280bd7b7 Zdenek Kabelac
55
    /* faad calls */
56
    faacDecHandle FAADAPI (*faacDecOpen)(void);
57
    faacDecConfigurationPtr FAADAPI (*faacDecGetCurrentConfiguration)(faacDecHandle hDecoder);
58 931c85d0 Thomas Raivio
#ifndef FAAD2_VERSION
59 bb270c08 Diego Biurrun
        int FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder,
60 931c85d0 Thomas Raivio
                                           faacDecConfigurationPtr config);
61 bb270c08 Diego Biurrun
        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 931c85d0 Thomas Raivio
                                unsigned long SizeOfDecoderSpecificInfo,
67
                                unsigned long *samplerate, unsigned long *channels);
68 bb270c08 Diego Biurrun
        int FAADAPI (*faacDecDecode)(faacDecHandle hDecoder,
69
                                unsigned char *buffer,
70
                                unsigned long *bytesconsumed,
71
                                short *sample_buffer,
72 931c85d0 Thomas Raivio
                                unsigned long *samples);
73
#else
74 bb270c08 Diego Biurrun
        unsigned char FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder,
75 931c85d0 Thomas Raivio
                                                     faacDecConfigurationPtr config);
76 bb270c08 Diego Biurrun
        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 280bd7b7 Zdenek Kabelac
                                 unsigned long SizeOfDecoderSpecificInfo,
83
                                 unsigned long *samplerate, unsigned char *channels);
84 bb270c08 Diego Biurrun
        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 931c85d0 Thomas Raivio
#endif
90 115329f1 Diego Biurrun
91 280bd7b7 Zdenek Kabelac
    void FAADAPI (*faacDecClose)(faacDecHandle hDecoder);
92 115329f1 Diego Biurrun
93
94 280bd7b7 Zdenek Kabelac
} 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 931c85d0 Thomas Raivio
#ifndef FAAD2_VERSION
107
    unsigned long channels;
108
#else
109 280bd7b7 Zdenek Kabelac
    unsigned char channels;
110 931c85d0 Thomas Raivio
#endif
111 280bd7b7 Zdenek Kabelac
    int r = 0;
112
113 79b0b66b Måns Rullgård
    if (avctx->extradata){
114 bb270c08 Diego Biurrun
        r = s->faacDecInit2(s->faac_handle, (uint8_t*) avctx->extradata,
115
                            avctx->extradata_size,
116
                            &samplerate, &channels);
117 79b0b66b Måns Rullgård
        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 940aed50 Luca Abeni
128 280bd7b7 Zdenek Kabelac
    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 931c85d0 Thomas Raivio
#ifndef FAAD2_VERSION
137
    unsigned long bytesconsumed;
138
    short *sample_buffer = NULL;
139
    unsigned long samples;
140
    int out;
141
#else
142 280bd7b7 Zdenek Kabelac
    faacDecFrameInfo frame_info;
143 931c85d0 Thomas Raivio
    void *out;
144
#endif
145
    if(buf_size == 0)
146 bb270c08 Diego Biurrun
        return 0;
147 931c85d0 Thomas Raivio
#ifndef FAAD2_VERSION
148 115329f1 Diego Biurrun
    out = s->faacDecDecode(s->faac_handle,
149
                           (unsigned char*)buf,
150
                           &bytesconsumed,
151
                           data,
152 931c85d0 Thomas Raivio
                           &samples);
153
    samples *= s->sample_size;
154
    if (data_size)
155 bb270c08 Diego Biurrun
        *data_size = samples;
156 931c85d0 Thomas Raivio
    return (buf_size < (int)bytesconsumed)
157 bb270c08 Diego Biurrun
        ? buf_size : (int)bytesconsumed;
158 931c85d0 Thomas Raivio
#else
159 115329f1 Diego Biurrun
160 79b0b66b Måns Rullgård
    if(!s->init){
161
        unsigned long srate;
162
        unsigned char channels;
163
        int r = 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 0;
168
        }
169
        avctx->sample_rate = srate;
170
        avctx->channels = channels;
171
        s->init = 1;
172
    }
173
174 931c85d0 Thomas Raivio
    out = s->faacDecDecode(s->faac_handle, &frame_info, (unsigned char*)buf, (unsigned long)buf_size);
175 280bd7b7 Zdenek Kabelac
176
    if (frame_info.error > 0) {
177 bb270c08 Diego Biurrun
        av_log(avctx, AV_LOG_ERROR, "faac: frame decoding failed: %s\n",
178
                s->faacDecGetErrorMessage(frame_info.error));
179 280bd7b7 Zdenek Kabelac
        return 0;
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 bb270c08 Diego Biurrun
        *data_size = frame_info.samples;
187 280bd7b7 Zdenek Kabelac
188
    return (buf_size < (int)frame_info.bytesconsumed)
189 bb270c08 Diego Biurrun
        ? buf_size : (int)frame_info.bytesconsumed;
190 931c85d0 Thomas Raivio
#endif
191 280bd7b7 Zdenek Kabelac
}
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 bb270c08 Diego Biurrun
        av_log(avctx, AV_LOG_ERROR, "FAAD library: %s could not be opened! \n%s\n",
216
                libfaadname, dlerror());
217 280bd7b7 Zdenek Kabelac
        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 bb270c08 Diego Biurrun
        dfaac(Open, (faacDecHandle FAADAPI (*)(void)));
229
        dfaac(GetCurrentConfiguration, (faacDecConfigurationPtr
230
                                        FAADAPI (*)(faacDecHandle)));
231 931c85d0 Thomas Raivio
#ifndef FAAD2_VERSION
232 bb270c08 Diego Biurrun
        dfaac(SetConfiguration, (int FAADAPI (*)(faacDecHandle,
233
                                                           faacDecConfigurationPtr)));
234 280bd7b7 Zdenek Kabelac
235 bb270c08 Diego Biurrun
        dfaac(Init, (int FAADAPI (*)(faacDecHandle, unsigned char*,
236
                                     unsigned long*, unsigned long*)));
237 931c85d0 Thomas Raivio
    dfaac(Init2, (int FAADAPI (*)(faacDecHandle, unsigned char*,
238 bb270c08 Diego Biurrun
                                       unsigned long, unsigned long*,
239
                                       unsigned long*)));
240 931c85d0 Thomas Raivio
    dfaac(Close, (void FAADAPI (*)(faacDecHandle hDecoder)));
241 bb270c08 Diego Biurrun
        dfaac(Decode, (int FAADAPI (*)(faacDecHandle, unsigned char*,
242
                             unsigned long*, short*, unsigned long*)));
243 931c85d0 Thomas Raivio
#else
244 bb270c08 Diego Biurrun
        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 931c85d0 Thomas Raivio
#endif
255 280bd7b7 Zdenek Kabelac
#undef dfacc
256
257
#ifdef CONFIG_FAADBIN
258
        break;
259
    }
260
    if (err) {
261
        dlclose(s->handle);
262 bb270c08 Diego Biurrun
        av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot resolve %s in %s!\n",
263
                err, libfaadname);
264 280bd7b7 Zdenek Kabelac
        return -1;
265
    }
266
#endif
267
268
    s->faac_handle = s->faacDecOpen();
269
    if (!s->faac_handle) {
270 3d0ef6dd Michael Niedermayer
        av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot create handler!\n");
271 280bd7b7 Zdenek Kabelac
        faac_decode_end(avctx);
272
        return -1;
273
    }
274
275
276
    faac_cfg = s->faacDecGetCurrentConfiguration(s->faac_handle);
277
278
    if (faac_cfg) {
279 bb270c08 Diego Biurrun
        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 931c85d0 Thomas Raivio
#ifdef FAAD2_VERSION
284 bb270c08 Diego Biurrun
            faac_cfg->outputFormat = FAAD_FMT_16BIT;
285 931c85d0 Thomas Raivio
#endif
286 bb270c08 Diego Biurrun
            s->sample_size = 2;
287
            break;
288
        case 24:
289 931c85d0 Thomas Raivio
#ifdef FAAD2_VERSION
290 bb270c08 Diego Biurrun
            faac_cfg->outputFormat = FAAD_FMT_24BIT;
291 931c85d0 Thomas Raivio
#endif
292 bb270c08 Diego Biurrun
            s->sample_size = 3;
293
            break;
294
        case 32:
295 931c85d0 Thomas Raivio
#ifdef FAAD2_VERSION
296 bb270c08 Diego Biurrun
            faac_cfg->outputFormat = FAAD_FMT_32BIT;
297 931c85d0 Thomas Raivio
#endif
298 bb270c08 Diego Biurrun
            s->sample_size = 4;
299
            break;
300
        }
301 280bd7b7 Zdenek Kabelac
302 bb270c08 Diego Biurrun
        faac_cfg->defSampleRate = (!avctx->sample_rate) ? 44100 : avctx->sample_rate;
303
        faac_cfg->defObjectType = LC;
304 280bd7b7 Zdenek Kabelac
    }
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