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 Fri Oct 26 02:35:37 2012 for FFmpeg by doxygen 1.5.8

AltStyle によって変換されたページ (->オリジナル) /