| OLD | NEW |
| (Empty) |
| 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)(faacDecHan
dle 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 *channe
ls); | |
| 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 con
fig); | |
| 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 *chann
els); | |
| 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, (un
signed 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", avct
x->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 }; | |
| OLD | NEW |