• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/libfaad.c

Go to the documentation of this file.
00001 /*
00002  * Faad decoder
00003  * Copyright (c) 2003 Zdenek Kabelac
00004  * Copyright (c) 2004 Thomas Raivio
00005  *
00006  * This file is part of FFmpeg.
00007  *
00008  * FFmpeg is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * FFmpeg is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with FFmpeg; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00030 #include "avcodec.h"
00031 #include "faad.h"
00032 
00033 #ifndef FAADAPI
00034 #define FAADAPI
00035 #endif
00036 
00037 /*
00038  * when CONFIG_LIBFAADBIN is true libfaad will be opened at runtime
00039  */
00040 //#undef CONFIG_LIBFAADBIN
00041 //#define CONFIG_LIBFAADBIN 0
00042 //#define CONFIG_LIBFAADBIN 1
00043 
00044 #if CONFIG_LIBFAADBIN
00045 #include <dlfcn.h>
00046 static const char* const libfaadname = "libfaad.so";
00047 #else
00048 #define dlopen(a)
00049 #define dlclose(a)
00050 #endif
00051 
00052 typedef struct {
00053     void* handle;               /* dlopen handle */
00054     void* faac_handle;          /* FAAD library handle */
00055     int sample_size;
00056     int init;
00057 
00058     /* faad calls */
00059     faacDecHandle FAADAPI (*faacDecOpen)(void);
00060     faacDecConfigurationPtr FAADAPI (*faacDecGetCurrentConfiguration)(faacDecHandle hDecoder);
00061 #ifndef FAAD2_VERSION
00062     int FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder,
00063                                            faacDecConfigurationPtr config);
00064     int FAADAPI (*faacDecInit)(faacDecHandle hDecoder,
00065                                unsigned char *buffer,
00066                                unsigned long *samplerate,
00067                                unsigned long *channels);
00068     int FAADAPI (*faacDecInit2)(faacDecHandle hDecoder, unsigned char *pBuffer,
00069                                 unsigned long SizeOfDecoderSpecificInfo,
00070                                 unsigned long *samplerate, unsigned long *channels);
00071     int FAADAPI (*faacDecDecode)(faacDecHandle hDecoder,
00072                                  unsigned char *buffer,
00073                                  unsigned long *bytesconsumed,
00074                                  short *sample_buffer,
00075                                  unsigned long *samples);
00076 #else
00077     unsigned char FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder,
00078                                                      faacDecConfigurationPtr config);
00079     long FAADAPI (*faacDecInit)(faacDecHandle hDecoder,
00080                                 unsigned char *buffer,
00081                                 unsigned long buffer_size,
00082                                 unsigned long *samplerate,
00083                                 unsigned char *channels);
00084     char FAADAPI (*faacDecInit2)(faacDecHandle hDecoder, unsigned char *pBuffer,
00085                                  unsigned long SizeOfDecoderSpecificInfo,
00086                                  unsigned long *samplerate, unsigned char *channels);
00087     void *FAADAPI (*faacDecDecode)(faacDecHandle hDecoder,
00088                                    faacDecFrameInfo *hInfo,
00089                                    unsigned char *buffer,
00090                                    unsigned long buffer_size);
00091     char* FAADAPI (*faacDecGetErrorMessage)(unsigned char errcode);
00092 #endif
00093 
00094     void FAADAPI (*faacDecClose)(faacDecHandle hDecoder);
00095 
00096 
00097 } FAACContext;
00098 
00099 static const unsigned long faac_srates[] =
00100 {
00101     96000, 88200, 64000, 48000, 44100, 32000,
00102     24000, 22050, 16000, 12000, 11025, 8000
00103 };
00104 
00105 static void channel_setup(AVCodecContext *avctx)
00106 {
00107 #ifdef FAAD2_VERSION
00108     FAACContext *s = avctx->priv_data;
00109     if (avctx->request_channels > 0 && avctx->request_channels == 2 &&
00110         avctx->request_channels < avctx->channels) {
00111         faacDecConfigurationPtr faac_cfg;
00112         avctx->channels = 2;
00113         faac_cfg = s->faacDecGetCurrentConfiguration(s->faac_handle);
00114         faac_cfg->downMatrix = 1;
00115         s->faacDecSetConfiguration(s->faac_handle, faac_cfg);
00116     }
00117 #endif
00118 }
00119 
00120 static av_cold int faac_init_mp4(AVCodecContext *avctx)
00121 {
00122     FAACContext *s = avctx->priv_data;
00123     unsigned long samplerate;
00124 #ifndef FAAD2_VERSION
00125     unsigned long channels;
00126 #else
00127     unsigned char channels;
00128 #endif
00129     int r = 0;
00130 
00131     if (avctx->extradata){
00132         r = s->faacDecInit2(s->faac_handle, (uint8_t*) avctx->extradata,
00133                             avctx->extradata_size,
00134                             &samplerate, &channels);
00135         if (r < 0){
00136             av_log(avctx, AV_LOG_ERROR,
00137                    "faacDecInit2 failed r:%d   sr:%ld  ch:%ld  s:%d\n",
00138                    r, samplerate, (long)channels, avctx->extradata_size);
00139         } else {
00140             avctx->sample_rate = samplerate;
00141             avctx->channels = channels;
00142             channel_setup(avctx);
00143             s->init = 1;
00144         }
00145     }
00146 
00147     return r;
00148 }
00149 
00150 static int faac_decode_frame(AVCodecContext *avctx,
00151                              void *data, int *data_size,
00152                              uint8_t *buf, int buf_size)
00153 {
00154     FAACContext *s = avctx->priv_data;
00155 #ifndef FAAD2_VERSION
00156     unsigned long bytesconsumed;
00157     short *sample_buffer = NULL;
00158     unsigned long samples;
00159     int out;
00160 #else
00161     faacDecFrameInfo frame_info;
00162     void *out;
00163 #endif
00164     if(buf_size == 0)
00165         return 0;
00166 #ifndef FAAD2_VERSION
00167     out = s->faacDecDecode(s->faac_handle,
00168                            (unsigned char*)buf,
00169                            &bytesconsumed,
00170                            data,
00171                            &samples);
00172     samples *= s->sample_size;
00173     if (data_size)
00174         *data_size = samples;
00175     return (buf_size < (int)bytesconsumed)
00176         ? buf_size : (int)bytesconsumed;
00177 #else
00178 
00179     if(!s->init){
00180         unsigned long srate;
00181         unsigned char channels;
00182         int r = s->faacDecInit(s->faac_handle, buf, buf_size, &srate, &channels);
00183         if(r < 0){
00184             av_log(avctx, AV_LOG_ERROR, "faac: codec init failed.\n");
00185             return -1;
00186         }
00187         avctx->sample_rate = srate;
00188         avctx->channels = channels;
00189         channel_setup(avctx);
00190         s->init = 1;
00191     }
00192 
00193     out = s->faacDecDecode(s->faac_handle, &frame_info, (unsigned char*)buf, (unsigned long)buf_size);
00194 
00195     if (frame_info.error > 0) {
00196         av_log(avctx, AV_LOG_ERROR, "faac: frame decoding failed: %s\n",
00197                s->faacDecGetErrorMessage(frame_info.error));
00198         return -1;
00199     }
00200     if (!avctx->frame_size)
00201         avctx->frame_size = frame_info.samples/avctx->channels;
00202     frame_info.samples *= s->sample_size;
00203     memcpy(data, out, frame_info.samples); // CHECKME - can we cheat this one
00204 
00205     if (data_size)
00206         *data_size = frame_info.samples;
00207 
00208     return (buf_size < (int)frame_info.bytesconsumed)
00209         ? buf_size : (int)frame_info.bytesconsumed;
00210 #endif
00211 }
00212 
00213 static av_cold int faac_decode_end(AVCodecContext *avctx)
00214 {
00215     FAACContext *s = avctx->priv_data;
00216 
00217     s->faacDecClose(s->faac_handle);
00218 
00219     dlclose(s->handle);
00220     return 0;
00221 }
00222 
00223 static av_cold int faac_decode_init(AVCodecContext *avctx)
00224 {
00225     FAACContext *s = avctx->priv_data;
00226     faacDecConfigurationPtr faac_cfg;
00227 
00228 #if CONFIG_LIBFAADBIN
00229     const char* err = 0;
00230 
00231     s->handle = dlopen(libfaadname, RTLD_LAZY);
00232     if (!s->handle)
00233     {
00234         av_log(avctx, AV_LOG_ERROR, "FAAD library: %s could not be opened! \n%s\n",
00235                libfaadname, dlerror());
00236         return -1;
00237     }
00238 
00239 #define dfaac(a) do {                                                   \
00240         const char* n = AV_STRINGIFY(faacDec ## a);                     \
00241         if (!err && !(s->faacDec ## a = dlsym(s->handle, n))) {         \
00242             err = n;                                                    \
00243         }                                                               \
00244     } while(0)
00245 #else  /* !CONFIG_LIBFAADBIN */
00246 #define dfaac(a)     s->faacDec ## a = faacDec ## a
00247 #endif /* CONFIG_LIBFAADBIN */
00248 
00249     // resolve all needed function calls
00250     dfaac(Open);
00251     dfaac(Close);
00252     dfaac(GetCurrentConfiguration);
00253     dfaac(SetConfiguration);
00254     dfaac(Init);
00255     dfaac(Init2);
00256     dfaac(Decode);
00257 #ifdef FAAD2_VERSION
00258     dfaac(GetErrorMessage);
00259 #endif
00260 
00261 #undef dfaac
00262 
00263 #if CONFIG_LIBFAADBIN
00264     if (err) {
00265         dlclose(s->handle);
00266         av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot resolve %s in %s!\n",
00267                err, libfaadname);
00268         return -1;
00269     }
00270 #endif
00271 
00272     s->faac_handle = s->faacDecOpen();
00273     if (!s->faac_handle) {
00274         av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot create handler!\n");
00275         faac_decode_end(avctx);
00276         return -1;
00277     }
00278 
00279 
00280     faac_cfg = s->faacDecGetCurrentConfiguration(s->faac_handle);
00281 
00282     if (faac_cfg) {
00283         switch (avctx->bits_per_coded_sample) {
00284         case 8: av_log(avctx, AV_LOG_ERROR, "FAADlib unsupported bps %d\n", avctx->bits_per_coded_sample); break;
00285         default:
00286         case 16:
00287 #ifdef FAAD2_VERSION
00288             faac_cfg->outputFormat = FAAD_FMT_16BIT;
00289 #endif
00290             s->sample_size = 2;
00291             break;
00292         case 24:
00293 #ifdef FAAD2_VERSION
00294             faac_cfg->outputFormat = FAAD_FMT_24BIT;
00295 #endif
00296             s->sample_size = 3;
00297             break;
00298         case 32:
00299 #ifdef FAAD2_VERSION
00300             faac_cfg->outputFormat = FAAD_FMT_32BIT;
00301 #endif
00302             s->sample_size = 4;
00303             break;
00304         }
00305 
00306         faac_cfg->defSampleRate = (!avctx->sample_rate) ? 44100 : avctx->sample_rate;
00307         faac_cfg->defObjectType = LC;
00308     }
00309 
00310     s->faacDecSetConfiguration(s->faac_handle, faac_cfg);
00311 
00312     faac_init_mp4(avctx);
00313 
00314     if(!s->init && avctx->channels > 0)
00315         channel_setup(avctx);
00316 
00317     avctx->sample_fmt = SAMPLE_FMT_S16;
00318     return 0;
00319 }
00320 
00321 #define AAC_CODEC(id, name, long_name_) \
00322 AVCodec name ## _decoder = {    \
00323     #name,                      \
00324     CODEC_TYPE_AUDIO,           \
00325     id,                         \
00326     sizeof(FAACContext),        \
00327     faac_decode_init,           \
00328     NULL,                       \
00329     faac_decode_end,            \
00330     faac_decode_frame,          \
00331     .long_name = NULL_IF_CONFIG_SMALL(long_name_), \
00332 }
00333 
00334 // FIXME - raw AAC files - maybe just one entry will be enough
00335 AAC_CODEC(CODEC_ID_AAC, libfaad, "libfaad AAC (Advanced Audio Codec)");
00336 
00337 #undef AAC_CODEC

Generated on Sat Feb 16 2013 09:23:12 for ffmpeg by  doxygen 1.7.1