• 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                              AVPacket *avpkt)
00153 {
00154     const uint8_t *buf = avpkt->data;
00155     int buf_size = avpkt->size;
00156     FAACContext *s = avctx->priv_data;
00157 #ifndef FAAD2_VERSION
00158     unsigned long bytesconsumed;
00159     short *sample_buffer = NULL;
00160     unsigned long samples;
00161     int out;
00162 #else
00163     faacDecFrameInfo frame_info;
00164     void *out;
00165 #endif
00166     if(buf_size == 0)
00167         return 0;
00168 #ifndef FAAD2_VERSION
00169     out = s->faacDecDecode(s->faac_handle,
00170                            (unsigned char*)buf,
00171                            &bytesconsumed,
00172                            data,
00173                            &samples);
00174     samples *= s->sample_size;
00175     if (data_size)
00176         *data_size = samples;
00177     return (buf_size < (int)bytesconsumed)
00178         ? buf_size : (int)bytesconsumed;
00179 #else
00180 
00181     if(!s->init){
00182         unsigned long srate;
00183         unsigned char channels;
00184         int r = s->faacDecInit(s->faac_handle, buf, buf_size, &srate, &channels);
00185         if(r < 0){
00186             av_log(avctx, AV_LOG_ERROR, "libfaad: codec init failed.\n");
00187             return -1;
00188         }
00189         avctx->sample_rate = srate;
00190         avctx->channels = channels;
00191         channel_setup(avctx);
00192         s->init = 1;
00193     }
00194 
00195     out = s->faacDecDecode(s->faac_handle, &frame_info, (unsigned char*)buf, (unsigned long)buf_size);
00196 
00197     if (frame_info.error > 0) {
00198         av_log(avctx, AV_LOG_ERROR, "libfaad: frame decoding failed: %s\n",
00199                s->faacDecGetErrorMessage(frame_info.error));
00200         return -1;
00201     }
00202     if (!avctx->frame_size)
00203         avctx->frame_size = frame_info.samples/avctx->channels;
00204     frame_info.samples *= s->sample_size;
00205     memcpy(data, out, frame_info.samples); // CHECKME - can we cheat this one
00206 
00207     if (data_size)
00208         *data_size = frame_info.samples;
00209 
00210     return (buf_size < (int)frame_info.bytesconsumed)
00211         ? buf_size : (int)frame_info.bytesconsumed;
00212 #endif
00213 }
00214 
00215 static av_cold int faac_decode_end(AVCodecContext *avctx)
00216 {
00217     FAACContext *s = avctx->priv_data;
00218 
00219     s->faacDecClose(s->faac_handle);
00220 
00221     dlclose(s->handle);
00222     return 0;
00223 }
00224 
00225 static av_cold int faac_decode_init(AVCodecContext *avctx)
00226 {
00227     FAACContext *s = avctx->priv_data;
00228     faacDecConfigurationPtr faac_cfg;
00229 
00230 #if CONFIG_LIBFAADBIN
00231     const char* err = 0;
00232 
00233     s->handle = dlopen(libfaadname, RTLD_LAZY);
00234     if (!s->handle)
00235     {
00236         av_log(avctx, AV_LOG_ERROR, "FAAD library: %s could not be opened! \n%s\n",
00237                libfaadname, dlerror());
00238         return -1;
00239     }
00240 
00241 #define dfaac(a) do {                                                   \
00242         const char* n = AV_STRINGIFY(faacDec ## a);                     \
00243         if (!err && !(s->faacDec ## a = dlsym(s->handle, n))) {         \
00244             err = n;                                                    \
00245         }                                                               \
00246     } while(0)
00247 #else  /* !CONFIG_LIBFAADBIN */
00248 #define dfaac(a)     s->faacDec ## a = faacDec ## a
00249 #endif /* CONFIG_LIBFAADBIN */
00250 
00251     // resolve all needed function calls
00252     dfaac(Open);
00253     dfaac(Close);
00254     dfaac(GetCurrentConfiguration);
00255     dfaac(SetConfiguration);
00256     dfaac(Init);
00257     dfaac(Init2);
00258     dfaac(Decode);
00259 #ifdef FAAD2_VERSION
00260     dfaac(GetErrorMessage);
00261 #endif
00262 
00263 #undef dfaac
00264 
00265 #if CONFIG_LIBFAADBIN
00266     if (err) {
00267         dlclose(s->handle);
00268         av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot resolve %s in %s!\n",
00269                err, libfaadname);
00270         return -1;
00271     }
00272 #endif
00273 
00274     s->faac_handle = s->faacDecOpen();
00275     if (!s->faac_handle) {
00276         av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot create handler!\n");
00277         faac_decode_end(avctx);
00278         return -1;
00279     }
00280 
00281 
00282     faac_cfg = s->faacDecGetCurrentConfiguration(s->faac_handle);
00283 
00284     if (faac_cfg) {
00285         switch (avctx->bits_per_coded_sample) {
00286         case 8: av_log(avctx, AV_LOG_ERROR, "FAADlib unsupported bps %d\n", avctx->bits_per_coded_sample); break;
00287         default:
00288         case 16:
00289 #ifdef FAAD2_VERSION
00290             faac_cfg->outputFormat = FAAD_FMT_16BIT;
00291 #endif
00292             s->sample_size = 2;
00293             break;
00294         case 24:
00295 #ifdef FAAD2_VERSION
00296             faac_cfg->outputFormat = FAAD_FMT_24BIT;
00297 #endif
00298             s->sample_size = 3;
00299             break;
00300         case 32:
00301 #ifdef FAAD2_VERSION
00302             faac_cfg->outputFormat = FAAD_FMT_32BIT;
00303 #endif
00304             s->sample_size = 4;
00305             break;
00306         }
00307 
00308         faac_cfg->defSampleRate = (!avctx->sample_rate) ? 44100 : avctx->sample_rate;
00309         faac_cfg->defObjectType = LC;
00310     }
00311 
00312     s->faacDecSetConfiguration(s->faac_handle, faac_cfg);
00313 
00314     faac_init_mp4(avctx);
00315 
00316     if(!s->init && avctx->channels > 0)
00317         channel_setup(avctx);
00318 
00319     avctx->sample_fmt = SAMPLE_FMT_S16;
00320     return 0;
00321 }
00322 
00323 AVCodec libfaad_decoder = {
00324     "libfaad",
00325     AVMEDIA_TYPE_AUDIO,
00326     CODEC_ID_AAC,
00327     sizeof(FAACContext),
00328     faac_decode_init,
00329     NULL,
00330     faac_decode_end,
00331     faac_decode_frame,
00332     .long_name = NULL_IF_CONFIG_SMALL("libfaad AAC (Advanced Audio Codec)"),
00333 };

Generated on Fri Sep 16 2011 17:17:38 for FFmpeg by  doxygen 1.7.1