| @@ -1,333 +0,0 @@ |
| 1 | /* | | |
| 2 | * Faad decoder | | |
| 3 | * Copyright (c) 2003 Zdenek Kabelac | | |
| 4 | * Copyright (c) 2004 Thomas Raivio | | |
| 5 | * | | |
| 6 | * This file is part of FFmpeg. | | |
| 7 | * | | |
| 8 | * FFmpeg is free software; you can redistribute it and/or | | |
| 9 | * modify it under the terms of the GNU Lesser General Public | | |
| 10 | * License as published by the Free Software Foundation; either | | |
| 11 | * version 2.1 of the License, or (at your option) any later version. | | |
| 12 | * | | |
| 13 | * FFmpeg is distributed in the hope that it will be useful, | | |
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | | |
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | | |
| 16 | * Lesser General Public License for more details. | | |
| 17 | * | | |
| 18 | * You should have received a copy of the GNU Lesser General Public | | |
| 19 | * License along with FFmpeg; if not, write to the Free Software | | |
| 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | | |
| 21 | */ | | |
| 22 | | | |
| 23 | /** | | |
| 24 | * @file | | |
| 25 | * AAC decoder. | | |
| 26 | * | | |
| 27 | * still a bit unfinished - but it plays something | | |
| 28 | */ | | |
| 29 | | | |
| 30 | #include "avcodec.h" | | |
| 31 | #include "faad.h" | | |
| 32 | | | |
| 33 | #ifndef FAADAPI | | |
| 34 | #define FAADAPI | | |
| 35 | #endif | | |
| 36 | | | |
| 37 | /* | | |
| 38 | * when CONFIG_LIBFAADBIN is true libfaad will be opened at runtime | | |
| 39 | */ | | |
| 40 | //#undef CONFIG_LIBFAADBIN | | |
| 41 | //#define CONFIG_LIBFAADBIN 0 | | |
| 42 | //#define CONFIG_LIBFAADBIN 1 | | |
| 43 | | | |
| 44 | #if CONFIG_LIBFAADBIN | | |
| 45 | #include <dlfcn.h> | | |
| 46 | static const char* const libfaadname = "libfaad.so"; | | |
| 47 | #else | | |
| 48 | #define dlopen(a) | | |
| 49 | #define dlclose(a) | | |
| 50 | #endif | | |
| 51 | | | |
| 52 | typedef struct { | | |
| 53 | void* handle; /* dlopen handle */ | | |
| 54 | void* faac_handle; /* FAAD library handle */ | | |
| 55 | int sample_size; | | |
| 56 | int init; | | |
| 57 | | | |
| 58 | /* faad calls */ | | |
| 59 | faacDecHandle FAADAPI (*faacDecOpen)(void); | | |
| 60 | faacDecConfigurationPtr FAADAPI (*faacDecGetCurrentConfiguration)(faacDecHandle hDecoder); | | |
| 61 | #ifndef FAAD2_VERSION | | |
| 62 | int FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder, | | |
| 63 | faacDecConfigurationPtr config); | | |
| 64 | int FAADAPI (*faacDecInit)(faacDecHandle hDecoder, | | |
| 65 | unsigned char *buffer, | | |
| 66 | unsigned long *samplerate, | | |
| 67 | unsigned long *channels); | | |
| 68 | int FAADAPI (*faacDecInit2)(faacDecHandle hDecoder, unsigned char *pBuffer, | | |
| 69 | unsigned long SizeOfDecoderSpecificInfo, | | |
| 70 | unsigned long *samplerate, unsigned long *channels); | | |
| 71 | int FAADAPI (*faacDecDecode)(faacDecHandle hDecoder, | | |
| 72 | unsigned char *buffer, | | |
| 73 | unsigned long *bytesconsumed, | | |
| 74 | short *sample_buffer, | | |
| 75 | unsigned long *samples); | | |
| 76 | #else | | |
| 77 | unsigned char FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder, | | |
| 78 | faacDecConfigurationPtr config); | | |
| 79 | long FAADAPI (*faacDecInit)(faacDecHandle hDecoder, | | |
| 80 | unsigned char *buffer, | | |
| 81 | unsigned long buffer_size, | | |
| 82 | unsigned long *samplerate, | | |
| 83 | unsigned char *channels); | | |
| 84 | char FAADAPI (*faacDecInit2)(faacDecHandle hDecoder, unsigned char *pBuffer, | | |
| 85 | unsigned long SizeOfDecoderSpecificInfo, | | |
| 86 | unsigned long *samplerate, unsigned char *channels); | | |
| 87 | void *FAADAPI (*faacDecDecode)(faacDecHandle hDecoder, | | |
| 88 | faacDecFrameInfo *hInfo, | | |
| 89 | unsigned char *buffer, | | |
| 90 | unsigned long buffer_size); | | |
| 91 | char* FAADAPI (*faacDecGetErrorMessage)(unsigned char errcode); | | |
| 92 | #endif | | |
| 93 | | | |
| 94 | void FAADAPI (*faacDecClose)(faacDecHandle hDecoder); | | |
| 95 | | | |
| 96 | | | |
| 97 | } FAACContext; | | |
| 98 | | | |
| 99 | static const unsigned long faac_srates[] = | | |
| 100 | { | | |
| 101 | 96000, 88200, 64000, 48000, 44100, 32000, | | |
| 102 | 24000, 22050, 16000, 12000, 11025, 8000 | | |
| 103 | }; | | |
| 104 | | | |
| 105 | static void channel_setup(AVCodecContext *avctx) | | |
| 106 | { | | |
| 107 | #ifdef FAAD2_VERSION | | |
| 108 | FAACContext *s = avctx->priv_data; | | |
| 109 | if (avctx->request_channels > 0 && avctx->request_channels == 2 && | | |
| 110 | avctx->request_channels < avctx->channels) { | | |
| 111 | faacDecConfigurationPtr faac_cfg; | | |
| 112 | avctx->channels = 2; | | |
| 113 | faac_cfg = s->faacDecGetCurrentConfiguration(s->faac_handle); | | |
| 114 | faac_cfg->downMatrix = 1; | | |
| 115 | s->faacDecSetConfiguration(s->faac_handle, faac_cfg); | | |
| 116 | } | | |
| 117 | #endif | | |
| 118 | } | | |
| 119 | | | |
| 120 | static av_cold int faac_init_mp4(AVCodecContext *avctx) | | |
| 121 | { | | |
| 122 | FAACContext *s = avctx->priv_data; | | |
| 123 | unsigned long samplerate; | | |
| 124 | #ifndef FAAD2_VERSION | | |
| 125 | unsigned long channels; | | |
| 126 | #else | | |
| 127 | unsigned char channels; | | |
| 128 | #endif | | |
| 129 | int r = 0; | | |
| 130 | | | |
| 131 | if (avctx->extradata){ | | |
| 132 | r = s->faacDecInit2(s->faac_handle, (uint8_t*) avctx->extradata, | | |
| 133 | avctx->extradata_size, | | |
| 134 | &samplerate, &channels); | | |
| 135 | if (r < 0){ | | |
| 136 | av_log(avctx, AV_LOG_ERROR, | | |
| 137 | "faacDecInit2 failed r:%d sr:%ld ch:%ld s:%d\n", | | |
| 138 | r, samplerate, (long)channels, avctx->extradata_size); | | |
| 139 | } else { | | |
| 140 | avctx->sample_rate = samplerate; | | |
| 141 | avctx->channels = channels; | | |
| 142 | channel_setup(avctx); | | |
| 143 | s->init = 1; | | |
| 144 | } | | |
| 145 | } | | |
| 146 | | | |
| 147 | return r; | | |
| 148 | } | | |
| 149 | | | |
| 150 | static int faac_decode_frame(AVCodecContext *avctx, | | |
| 151 | void *data, int *data_size, | | |
| 152 | AVPacket *avpkt) | | |
| 153 | { | | |
| 154 | const uint8_t *buf = avpkt->data; | | |
| 155 | int buf_size = avpkt->size; | | |
| 156 | FAACContext *s = avctx->priv_data; | | |
| 157 | #ifndef FAAD2_VERSION | | |
| 158 | unsigned long bytesconsumed; | | |
| 159 | short *sample_buffer = NULL; | | |
| 160 | unsigned long samples; | | |
| 161 | int out; | | |
| 162 | #else | | |
| 163 | faacDecFrameInfo frame_info; | | |
| 164 | void *out; | | |
| 165 | #endif | | |
| 166 | if(buf_size == 0) | | |
| 167 | return 0; | | |
| 168 | #ifndef FAAD2_VERSION | | |
| 169 | out = s->faacDecDecode(s->faac_handle, | | |
| 170 | (unsigned char*)buf, | | |
| 171 | &bytesconsumed, | | |
| 172 | data, | | |
| 173 | &samples); | | |
| 174 | samples *= s->sample_size; | | |
| 175 | if (data_size) | | |
| 176 | *data_size = samples; | | |
| 177 | return (buf_size < (int)bytesconsumed) | | |
| 178 | ? buf_size : (int)bytesconsumed; | | |
| 179 | #else | | |
| 180 | | | |
| 181 | if(!s->init){ | | |
| 182 | unsigned long srate; | | |
| 183 | unsigned char channels; | | |
| 184 | int r = s->faacDecInit(s->faac_handle, buf, buf_size, &srate, &channels); | | |
| 185 | if(r < 0){ | | |
| 186 | av_log(avctx, AV_LOG_ERROR, "libfaad: codec init failed.\n"); | | |
| 187 | return -1; | | |
| 188 | } | | |
| 189 | avctx->sample_rate = srate; | | |
| 190 | avctx->channels = channels; | | |
| 191 | channel_setup(avctx); | | |
| 192 | s->init = 1; | | |
| 193 | } | | |
| 194 | | | |
| 195 | out = s->faacDecDecode(s->faac_handle, &frame_info, (unsigned char*)buf, (unsigned long)buf_size); | | |
| 196 | | | |
| 197 | if (frame_info.error > 0) { | | |
| 198 | av_log(avctx, AV_LOG_ERROR, "libfaad: frame decoding failed: %s\n", | | |
| 199 | s->faacDecGetErrorMessage(frame_info.error)); | | |
| 200 | return -1; | | |
| 201 | } | | |
| 202 | if (!avctx->frame_size) | | |
| 203 | avctx->frame_size = frame_info.samples/avctx->channels; | | |
| 204 | frame_info.samples *= s->sample_size; | | |
| 205 | memcpy(data, out, frame_info.samples); // CHECKME - can we cheat this one | | |
| 206 | | | |
| 207 | if (data_size) | | |
| 208 | *data_size = frame_info.samples; | | |
| 209 | | | |
| 210 | return (buf_size < (int)frame_info.bytesconsumed) | | |
| 211 | ? buf_size : (int)frame_info.bytesconsumed; | | |
| 212 | #endif | | |
| 213 | } | | |
| 214 | | | |
| 215 | static av_cold int faac_decode_end(AVCodecContext *avctx) | | |
| 216 | { | | |
| 217 | FAACContext *s = avctx->priv_data; | | |
| 218 | | | |
| 219 | s->faacDecClose(s->faac_handle); | | |
| 220 | | | |
| 221 | dlclose(s->handle); | | |
| 222 | return 0; | | |
| 223 | } | | |
| 224 | | | |
| 225 | static av_cold int faac_decode_init(AVCodecContext *avctx) | | |
| 226 | { | | |
| 227 | FAACContext *s = avctx->priv_data; | | |
| 228 | faacDecConfigurationPtr faac_cfg; | | |
| 229 | | | |
| 230 | #if CONFIG_LIBFAADBIN | | |
| 231 | const char* err = 0; | | |
| 232 | | | |
| 233 | s->handle = dlopen(libfaadname, RTLD_LAZY); | | |
| 234 | if (!s->handle) | | |
| 235 | { | | |
| 236 | av_log(avctx, AV_LOG_ERROR, "FAAD library: %s could not be opened! \n%s\n", | | |
| 237 | libfaadname, dlerror()); | | |
| 238 | return -1; | | |
| 239 | } | | |
| 240 | | | |
| 241 | #define dfaac(a) do { \ | | |
| 242 | const char* n = AV_STRINGIFY(faacDec ## a); \ | | |
| 243 | if (!err && !(s->faacDec ## a = dlsym(s->handle, n))) { \ | | |
| 244 | err = n; \ | | |
| 245 | } \ | | |
| 246 | } while(0) | | |
| 247 | #else /* !CONFIG_LIBFAADBIN */ | | |
| 248 | #define dfaac(a) s->faacDec ## a = faacDec ## a | | |
| 249 | #endif /* CONFIG_LIBFAADBIN */ | | |
| 250 | | | |
| 251 | // resolve all needed function calls | | |
| 252 | dfaac(Open); | | |
| 253 | dfaac(Close); | | |
| 254 | dfaac(GetCurrentConfiguration); | | |
| 255 | dfaac(SetConfiguration); | | |
| 256 | dfaac(Init); | | |
| 257 | dfaac(Init2); | | |
| 258 | dfaac(Decode); | | |
| 259 | #ifdef FAAD2_VERSION | | |
| 260 | dfaac(GetErrorMessage); | | |
| 261 | #endif | | |
| 262 | | | |
| 263 | #undef dfaac | | |
| 264 | | | |
| 265 | #if CONFIG_LIBFAADBIN | | |
| 266 | if (err) { | | |
| 267 | dlclose(s->handle); | | |
| 268 | av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot resolve %s in %s!\n", | | |
| 269 | err, libfaadname); | | |
| 270 | return -1; | | |
| 271 | } | | |
| 272 | #endif | | |
| 273 | | | |
| 274 | s->faac_handle = s->faacDecOpen(); | | |
| 275 | if (!s->faac_handle) { | | |
| 276 | av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot create handler!\n"); | | |
| 277 | faac_decode_end(avctx); | | |
| 278 | return -1; | | |
| 279 | } | | |
| 280 | | | |
| 281 | | | |
| 282 | faac_cfg = s->faacDecGetCurrentConfiguration(s->faac_handle); | | |
| 283 | | | |
| 284 | if (faac_cfg) { | | |
| 285 | switch (avctx->bits_per_coded_sample) { | | |
| 286 | case 8: av_log(avctx, AV_LOG_ERROR, "FAADlib unsupported bps %d\n", avctx->bits_per_coded_sample); break; | | |
| 287 | default: | | |
| 288 | case 16: | | |
| 289 | #ifdef FAAD2_VERSION | | |
| 290 | faac_cfg->outputFormat = FAAD_FMT_16BIT; | | |
| 291 | #endif | | |
| 292 | s->sample_size = 2; | | |
| 293 | break; | | |
| 294 | case 24: | | |
| 295 | #ifdef FAAD2_VERSION | | |
| 296 | faac_cfg->outputFormat = FAAD_FMT_24BIT; | | |
| 297 | #endif | | |
| 298 | s->sample_size = 3; | | |
| 299 | break; | | |
| 300 | case 32: | | |
| 301 | #ifdef FAAD2_VERSION | | |
| 302 | faac_cfg->outputFormat = FAAD_FMT_32BIT; | | |
| 303 | #endif | | |
| 304 | s->sample_size = 4; | | |
| 305 | break; | | |
| 306 | } | | |
| 307 | | | |
| 308 | faac_cfg->defSampleRate = (!avctx->sample_rate) ? 44100 : avctx->sample_rate; | | |
| 309 | faac_cfg->defObjectType = LC; | | |
| 310 | } | | |
| 311 | | | |
| 312 | s->faacDecSetConfiguration(s->faac_handle, faac_cfg); | | |
| 313 | | | |
| 314 | faac_init_mp4(avctx); | | |
| 315 | | | |
| 316 | if(!s->init && avctx->channels > 0) | | |
| 317 | channel_setup(avctx); | | |
| 318 | | | |
| 319 | avctx->sample_fmt = SAMPLE_FMT_S16; | | |
| 320 | return 0; | | |
| 321 | } | | |
| 322 | | | |
| 323 | AVCodec libfaad_decoder = { | | |
| 324 | "libfaad", | | |
| 325 | AVMEDIA_TYPE_AUDIO, | | |
| 326 | CODEC_ID_AAC, | | |
| 327 | sizeof(FAACContext), | | |
| 328 | faac_decode_init, | | |
| 329 | NULL, | | |
| 330 | faac_decode_end, | | |
| 331 | faac_decode_frame, | | |
| 332 | .long_name = NULL_IF_CONFIG_SMALL("libfaad AAC (Advanced Audio Codec)"), | | |
| 333 | }; | | |