Mercurial > libavcodec.hg
annotate faad.c @ 1757:3906ddbaffec libavcodec
optimization & bugfix extracted from the 4k line diff between ffmpeg 0.4.7 and http://www.alicestreet.com/ffh263.html
the other parts of the diff where
1. spelling fixes (rejected as only a small part of it could be applied automatically)
2. cosmetics (reindention, function reordering, var renaming, ...) with bugs (rejected)
3. rtp related stuff (rejetced as it breaks several codecs)
4. some changes to the intra/inter decission & scene change detection (quality tests needed first)
| author | michael |
|---|---|
| date | Sat, 24 Jan 2004 23:47:33 +0000 |
| parents | fdb8244da1e5 |
| children | d4525c3065d0 |
| rev | line source |
|---|---|
| 1245 | 1 /* |
| 2 * Faad decoder | |
| 3 * Copyright (c) 2003 Zdenek Kabelac. | |
| 4 * | |
| 5 * This library is free software; you can redistribute it and/or | |
| 6 * modify it under the terms of the GNU Lesser General Public | |
| 7 * License as published by the Free Software Foundation; either | |
| 8 * version 2 of the License, or (at your option) any later version. | |
| 9 * | |
| 10 * This library is distributed in the hope that it will be useful, | |
| 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 13 * Lesser General Public License for more details. | |
| 14 * | |
| 15 * You should have received a copy of the GNU Lesser General Public | |
| 16 * License along with this library; if not, write to the Free Software | |
| 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 18 */ | |
| 19 | |
| 20 /** | |
| 21 * @file faad.c | |
| 22 * AAC decoder. | |
| 23 * | |
| 24 * still a bit unfinished - but it plays something | |
| 25 */ | |
| 26 | |
| 27 #include "avcodec.h" | |
| 28 #include "faad.h" | |
| 29 | |
| 30 /* | |
| 31 * when CONFIG_FAADBIN is defined the libfaad will be opened at runtime | |
| 32 */ | |
| 33 //#undef CONFIG_FAADBIN | |
| 34 //#define CONFIG_FAADBIN | |
| 35 | |
| 36 #ifdef CONFIG_FAADBIN | |
| 37 #include <dlfcn.h> | |
| 38 static const char* libfaadname = "libfaad.so.0"; | |
| 39 #else | |
| 40 #define dlopen(a) | |
| 41 #define dlclose(a) | |
| 42 #endif | |
| 43 | |
| 44 typedef struct { | |
| 45 void* handle; /* dlopen handle */ | |
| 46 void* faac_handle; /* FAAD library handle */ | |
| 47 int frame_size; | |
| 48 int sample_size; | |
| 49 int flags; | |
| 50 | |
| 51 /* faad calls */ | |
| 52 faacDecHandle FAADAPI (*faacDecOpen)(void); | |
| 53 faacDecConfigurationPtr FAADAPI (*faacDecGetCurrentConfiguration)(faacDecHandle hDecoder); | |
| 54 unsigned char FAADAPI (*faacDecSetConfiguration)(faacDecHandle hDecoder, | |
| 55 faacDecConfigurationPtr config); | |
| 56 long FAADAPI (*faacDecInit)(faacDecHandle hDecoder, | |
| 57 unsigned char *buffer, | |
| 58 unsigned long *samplerate, | |
| 59 unsigned char *channels); | |
| 60 char FAADAPI (*faacDecInit2)(faacDecHandle hDecoder, unsigned char *pBuffer, | |
| 61 unsigned long SizeOfDecoderSpecificInfo, | |
| 62 unsigned long *samplerate, unsigned char *channels); | |
| 63 void FAADAPI (*faacDecClose)(faacDecHandle hDecoder); | |
| 64 void* FAADAPI (*faacDecDecode)(faacDecHandle hDecoder, | |
| 65 faacDecFrameInfo *hInfo, | |
| 66 unsigned char *buffer); | |
| 67 unsigned char* FAADAPI (*faacDecGetErrorMessage)(unsigned char errcode); | |
| 68 } FAACContext; | |
| 69 | |
| 70 static const unsigned long faac_srates[] = | |
| 71 { | |
| 72 96000, 88200, 64000, 48000, 44100, 32000, | |
| 73 24000, 22050, 16000, 12000, 11025, 8000 | |
| 74 }; | |
| 75 | |
| 76 static int faac_init_mp4(AVCodecContext *avctx) | |
| 77 { | |
| 78 FAACContext *s = (FAACContext *) avctx->priv_data; | |
| 79 unsigned long samplerate; | |
| 80 unsigned char channels; | |
| 81 int r = 0; | |
| 82 | |
| 83 if (avctx->extradata) | |
| 84 r = s->faacDecInit2(s->faac_handle, (uint8_t*) avctx->extradata, | |
| 85 avctx->extradata_size, | |
| 86 &samplerate, &channels); | |
| 87 // else r = s->faacDecInit(s->faac_handle ... ); | |
| 88 | |
| 89 if (r < 0) | |
|
1602
fdb8244da1e5
av_log patch(2 of ?) by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1245
diff
changeset
|
90 av_log(avctx, AV_LOG_ERROR, "faacDecInit2 failed r:%d sr:%ld ch:%d s:%d\n", |
| 1245 | 91 r, samplerate, channels, avctx->extradata_size); |
| 92 | |
| 93 return r; | |
| 94 } | |
| 95 | |
| 96 static int faac_init_aac(AVCodecContext *avctx) | |
| 97 { | |
| 98 FAACContext *s = (FAACContext *) avctx->priv_data; | |
| 99 return 0; | |
| 100 } | |
| 101 | |
| 102 static int faac_decode_frame(AVCodecContext *avctx, | |
| 103 void *data, int *data_size, | |
| 104 uint8_t *buf, int buf_size) | |
| 105 { | |
| 106 FAACContext *s = (FAACContext *) avctx->priv_data; | |
| 107 faacDecFrameInfo frame_info; | |
| 108 void* out = s->faacDecDecode(s->faac_handle, &frame_info, (unsigned char*)buf); | |
| 109 //printf("DECODE FRAME %d, %d, %d - %p\n", buf_size, frame_info.samples, frame_info.bytesconsumed, out); | |
| 110 | |
| 111 if (frame_info.error > 0) { | |
|
1602
fdb8244da1e5
av_log patch(2 of ?) by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1245
diff
changeset
|
112 av_log(avctx, AV_LOG_ERROR, "faac: frame decodinf failed: %s\n", |
| 1245 | 113 s->faacDecGetErrorMessage(frame_info.error)); |
| 114 return 0; | |
| 115 } | |
| 116 | |
| 117 frame_info.samples *= s->sample_size; | |
| 118 memcpy(data, out, frame_info.samples); // CHECKME - can we cheat this one | |
| 119 | |
| 120 if (data_size) | |
| 121 *data_size = frame_info.samples; | |
| 122 | |
| 123 return (buf_size < (int)frame_info.bytesconsumed) | |
| 124 ? buf_size : (int)frame_info.bytesconsumed; | |
| 125 } | |
| 126 | |
| 127 static int faac_decode_end(AVCodecContext *avctx) | |
| 128 { | |
| 129 FAACContext *s = (FAACContext *) avctx->priv_data; | |
| 130 | |
| 131 if (s->faacDecClose) | |
| 132 s->faacDecClose(s->faac_handle); | |
| 133 | |
| 134 dlclose(s->handle); | |
| 135 return 0; | |
| 136 } | |
| 137 | |
| 138 static int faac_decode_init(AVCodecContext *avctx) | |
| 139 { | |
| 140 FAACContext *s = (FAACContext *) avctx->priv_data; | |
| 141 faacDecConfigurationPtr faac_cfg; | |
| 142 | |
| 143 #ifdef CONFIG_FAADBIN | |
| 144 const char* err = 0; | |
| 145 | |
| 146 s->handle = dlopen(libfaadname, RTLD_LAZY); | |
| 147 if (!s->handle) | |
| 148 { | |
|
1602
fdb8244da1e5
av_log patch(2 of ?) by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1245
diff
changeset
|
149 av_log(avctx, AV_LOG_ERROR, "FAAD library: %s could not be opened! \n%s\n", |
| 1245 | 150 libfaadname, dlerror()); |
| 151 return -1; | |
| 152 } | |
| 153 #define dfaac(a, b) \ | |
| 154 do { static const char* n = "faacDec" #a; \ | |
| 155 if ((s->faacDec ## a = b dlsym( s->handle, n )) == NULL) { err = n; break; } } while(0) | |
| 156 for(;;) { | |
| 157 #else /* !CONFIG_FAADBIN */ | |
| 158 #define dfaac(a, b) s->faacDec ## a = faacDec ## a | |
| 159 #endif /* CONFIG_FAADBIN */ | |
| 160 | |
| 161 // resolve all needed function calls | |
| 162 dfaac(Open, (faacDecHandle FAADAPI (*)(void))); | |
| 163 dfaac(GetCurrentConfiguration, (faacDecConfigurationPtr | |
| 164 FAADAPI (*)(faacDecHandle))); | |
| 165 dfaac(SetConfiguration, (unsigned char FAADAPI (*)(faacDecHandle, | |
| 166 faacDecConfigurationPtr))); | |
| 167 | |
| 168 dfaac(Init, (long FAADAPI (*)(faacDecHandle, unsigned char*, | |
| 169 unsigned long*, unsigned char*))); | |
| 170 dfaac(Init2, (char FAADAPI (*)(faacDecHandle, unsigned char*, | |
| 171 unsigned long, unsigned long*, | |
| 172 unsigned char*))); | |
| 173 dfaac(Close, (void FAADAPI (*)(faacDecHandle hDecoder))); | |
| 174 dfaac(Decode, (void* FAADAPI (*)(faacDecHandle, faacDecFrameInfo*, | |
| 175 unsigned char*))); | |
| 176 | |
| 177 dfaac(GetErrorMessage, (unsigned char* FAADAPI (*)(unsigned char))); | |
| 178 #undef dfacc | |
| 179 | |
| 180 #ifdef CONFIG_FAADBIN | |
| 181 break; | |
| 182 } | |
| 183 if (err) { | |
| 184 dlclose(s->handle); | |
|
1602
fdb8244da1e5
av_log patch(2 of ?) by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1245
diff
changeset
|
185 av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot resolve %s in %s!\n", |
| 1245 | 186 err, libfaadname); |
| 187 return -1; | |
| 188 } | |
| 189 #endif | |
| 190 | |
| 191 s->faac_handle = s->faacDecOpen(); | |
| 192 if (!s->faac_handle) { | |
|
1602
fdb8244da1e5
av_log patch(2 of ?) by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1245
diff
changeset
|
193 av_log(avctx, AV_LOG_ERROR, "FAAD library: cannot create handler!\n"); |
| 1245 | 194 faac_decode_end(avctx); |
| 195 return -1; | |
| 196 } | |
| 197 | |
| 198 | |
| 199 faac_cfg = s->faacDecGetCurrentConfiguration(s->faac_handle); | |
| 200 | |
| 201 if (faac_cfg) { | |
| 202 switch (avctx->bits_per_sample) { | |
|
1602
fdb8244da1e5
av_log patch(2 of ?) by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1245
diff
changeset
|
203 case 8: av_log(avctx, AV_LOG_ERROR, "FAADlib unsupported bps %d\n", avctx->bits_per_sample); break; |
| 1245 | 204 default: |
| 205 case 16: | |
| 206 faac_cfg->outputFormat = FAAD_FMT_16BIT; | |
| 207 s->sample_size = 2; | |
| 208 break; | |
| 209 case 24: | |
| 210 faac_cfg->outputFormat = FAAD_FMT_24BIT; | |
| 211 s->sample_size = 3; | |
| 212 break; | |
| 213 case 32: | |
| 214 faac_cfg->outputFormat = FAAD_FMT_32BIT; | |
| 215 s->sample_size = 4; | |
| 216 break; | |
| 217 } | |
| 218 | |
| 219 faac_cfg->defSampleRate = (!avctx->sample_rate) ? 44100 : avctx->sample_rate; | |
| 220 faac_cfg->defObjectType = LC; | |
| 221 } | |
| 222 | |
| 223 s->faacDecSetConfiguration(s->faac_handle, faac_cfg); | |
| 224 | |
| 225 faac_init_mp4(avctx); | |
| 226 | |
| 227 return 0; | |
| 228 } | |
| 229 | |
| 230 #define AAC_CODEC(id, name) \ | |
| 231 AVCodec name ## _decoder = { \ | |
| 232 #name, \ | |
| 233 CODEC_TYPE_AUDIO, \ | |
| 234 id, \ | |
| 235 sizeof(FAACContext), \ | |
| 236 faac_decode_init, \ | |
| 237 NULL, \ | |
| 238 faac_decode_end, \ | |
| 239 faac_decode_frame, \ | |
| 240 } | |
| 241 | |
| 242 // FIXME - raw AAC files - maybe just one entry will be enough | |
| 243 AAC_CODEC(CODEC_ID_AAC, aac); | |
| 244 // If it's mp4 file - usually embeded into Qt Mov | |
| 245 AAC_CODEC(CODEC_ID_MPEG4AAC, mpeg4aac); | |
| 246 | |
| 247 #undef AAC_CODEC |
