Fix indentation.
[mplayer/glamo.git] / libmpcodecs / ad_faad.c
blob4613f3093750755fefe3835a56a93652935e8467
1 /* ad_faad.c - MPlayer AAC decoder using libfaad2
2 * This file is part of MPlayer, see http://mplayerhq.hu/ for info.
3 * (c)2002 by Felix Buenemann <atmosfear at users.sourceforge.net>
4 * File licensed under the GPL, see http://www.fsf.org/ for more info.
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
11 #include "config.h"
12 #include "ad_internal.h"
13 #include "libaf/reorder_ch.h"
15 static ad_info_t info =
17 "AAC (MPEG2/4 Advanced Audio Coding)",
18 "faad",
19 "Felix Buenemann",
20 "faad2",
21 "uses libfaad2"
24 LIBAD_EXTERN(faad)
26 #ifndef CONFIG_FAAD_INTERNAL
27 #include <faad.h>
28 #else
29 #include "libfaad2/faad.h"
30 #endif
32 /* configure maximum supported channels, *
33 * this is theoretically max. 64 chans */
34 #define FAAD_MAX_CHANNELS 6
35 #define FAAD_BUFFLEN (FAAD_MIN_STREAMSIZE*FAAD_MAX_CHANNELS)
37 //#define AAC_DUMP_COMPRESSED
39 static faacDecHandle faac_hdec;
40 static faacDecFrameInfo faac_finfo;
42 static int preinit(sh_audio_t *sh)
44 sh->audio_out_minsize=8192*FAAD_MAX_CHANNELS;
45 sh->audio_in_minsize=FAAD_BUFFLEN;
46 return 1;
49 static int aac_probe(unsigned char *buffer, int len)
51 int i = 0, pos = 0;
52 mp_msg(MSGT_DECAUDIO,MSGL_V, "\nAAC_PROBE: %d bytes\n", len);
53 while(i <= len-4) {
54 if(
55 ((buffer[i] == 0xff) && ((buffer[i+1] & 0xf6) == 0xf0)) ||
56 (buffer[i] == 'A' && buffer[i+1] == 'D' && buffer[i+2] == 'I' && buffer[i+3] == 'F')
57 ) {
58 pos = i;
59 break;
61 mp_msg(MSGT_DECAUDIO,MSGL_V, "AUDIO PAYLOAD: %x %x %x %x\n", buffer[i], buffer[i+1], buffer[i+2], buffer[i+3]);
62 i++;
64 mp_msg(MSGT_DECAUDIO,MSGL_V, "\nAAC_PROBE: ret %d\n", pos);
65 return pos;
68 static int init(sh_audio_t *sh)
70 unsigned long faac_samplerate;
71 unsigned char faac_channels;
72 int faac_init, pos = 0;
73 faac_hdec = faacDecOpen();
75 // If we don't get the ES descriptor, try manual config
76 if(!sh->codecdata_len && sh->wf) {
77 sh->codecdata_len = sh->wf->cbSize;
78 sh->codecdata = malloc(sh->codecdata_len);
79 memcpy(sh->codecdata, sh->wf+1, sh->codecdata_len);
80 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"FAAD: codecdata extracted from WAVEFORMATEX\n");
82 if(!sh->codecdata_len) {
83 #if 1
84 faacDecConfigurationPtr faac_conf;
85 /* Set the default object type and samplerate */
86 /* This is useful for RAW AAC files */
87 faac_conf = faacDecGetCurrentConfiguration(faac_hdec);
88 if(sh->samplerate)
89 faac_conf->defSampleRate = sh->samplerate;
90 /* XXX: FAAD support FLOAT output, how do we handle
91 * that (FAAD_FMT_FLOAT)? ::atmos
93 if (audio_output_channels <= 2) faac_conf->downMatrix = 1;
94 switch(sh->samplesize){
95 case 1: // 8Bit
96 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"FAAD: 8Bit samplesize not supported by FAAD, assuming 16Bit!\n");
97 default:
98 sh->samplesize=2;
99 case 2: // 16Bit
100 faac_conf->outputFormat = FAAD_FMT_16BIT;
101 break;
102 case 3: // 24Bit
103 faac_conf->outputFormat = FAAD_FMT_24BIT;
104 break;
105 case 4: // 32Bit
106 faac_conf->outputFormat = FAAD_FMT_32BIT;
107 break;
109 //faac_conf->defObjectType = LTP; // => MAIN, LC, SSR, LTP available.
111 faacDecSetConfiguration(faac_hdec, faac_conf);
112 #endif
114 sh->a_in_buffer_len = demux_read_data(sh->ds, sh->a_in_buffer, sh->a_in_buffer_size);
115 pos = aac_probe(sh->a_in_buffer, sh->a_in_buffer_len);
116 if(pos) {
117 sh->a_in_buffer_len -= pos;
118 memmove(sh->a_in_buffer, &(sh->a_in_buffer[pos]), sh->a_in_buffer_len);
119 sh->a_in_buffer_len +=
120 demux_read_data(sh->ds,&(sh->a_in_buffer[sh->a_in_buffer_len]),
121 sh->a_in_buffer_size - sh->a_in_buffer_len);
122 pos = 0;
125 /* init the codec */
126 faac_init = faacDecInit(faac_hdec, sh->a_in_buffer,
127 sh->a_in_buffer_len, &faac_samplerate, &faac_channels);
129 sh->a_in_buffer_len -= (faac_init > 0)?faac_init:0; // how many bytes init consumed
130 // XXX FIXME: shouldn't we memcpy() here in a_in_buffer ?? --A'rpi
132 } else { // We have ES DS in codecdata
133 faacDecConfigurationPtr faac_conf = faacDecGetCurrentConfiguration(faac_hdec);
134 if (audio_output_channels <= 2) {
135 faac_conf->downMatrix = 1;
136 faacDecSetConfiguration(faac_hdec, faac_conf);
139 /*int i;
140 for(i = 0; i < sh_audio->codecdata_len; i++)
141 printf("codecdata_dump %d: 0x%02X\n", i, sh_audio->codecdata[i]);*/
143 faac_init = faacDecInit2(faac_hdec, sh->codecdata,
144 sh->codecdata_len, &faac_samplerate, &faac_channels);
146 if(faac_init < 0) {
147 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"FAAD: Failed to initialize the decoder!\n"); // XXX: deal with cleanup!
148 faacDecClose(faac_hdec);
149 // XXX: free a_in_buffer here or in uninit?
150 return 0;
151 } else {
152 mp_msg(MSGT_DECAUDIO,MSGL_V,"FAAD: Decoder init done (%dBytes)!\n", sh->a_in_buffer_len); // XXX: remove or move to debug!
153 mp_msg(MSGT_DECAUDIO,MSGL_V,"FAAD: Negotiated samplerate: %ldHz channels: %d\n", faac_samplerate, faac_channels);
154 sh->channels = faac_channels;
155 if (audio_output_channels <= 2) sh->channels = faac_channels > 1 ? 2 : 1;
156 sh->samplerate = faac_samplerate;
157 sh->samplesize=2;
158 //sh->o_bps = sh->samplesize*faac_channels*faac_samplerate;
159 if(!sh->i_bps) {
160 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"FAAD: compressed input bitrate missing, assuming 128kbit/s!\n");
161 sh->i_bps = 128*1000/8; // XXX: HACK!!! ::atmos
162 } else
163 mp_msg(MSGT_DECAUDIO,MSGL_V,"FAAD: got %dkbit/s bitrate from MP4 header!\n",sh->i_bps*8/1000);
165 return 1;
168 static void uninit(sh_audio_t *sh)
170 mp_msg(MSGT_DECAUDIO,MSGL_V,"FAAD: Closing decoder!\n");
171 faacDecClose(faac_hdec);
174 static int aac_sync(sh_audio_t *sh)
176 int pos = 0;
177 if(!sh->codecdata_len) {
178 if(sh->a_in_buffer_len < sh->a_in_buffer_size){
179 sh->a_in_buffer_len +=
180 demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len],
181 sh->a_in_buffer_size - sh->a_in_buffer_len);
183 pos = aac_probe(sh->a_in_buffer, sh->a_in_buffer_len);
184 if(pos) {
185 sh->a_in_buffer_len -= pos;
186 memmove(sh->a_in_buffer, &(sh->a_in_buffer[pos]), sh->a_in_buffer_len);
187 mp_msg(MSGT_DECAUDIO,MSGL_V, "\nAAC SYNC AFTER %d bytes\n", pos);
190 return pos;
193 static int control(sh_audio_t *sh,int cmd,void* arg, ...)
195 switch(cmd)
197 case ADCTRL_RESYNC_STREAM:
198 aac_sync(sh);
199 return CONTROL_TRUE;
200 #if 0
201 case ADCTRL_SKIP_FRAME:
202 return CONTROL_TRUE;
203 #endif
205 return CONTROL_UNKNOWN;
208 #define MAX_FAAD_ERRORS 10
209 static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen)
211 int len = 0, last_dec_len = 1, errors = 0;
212 // int j = 0;
213 void *faac_sample_buffer;
215 while(len < minlen && last_dec_len > 0 && errors < MAX_FAAD_ERRORS) {
217 /* update buffer for raw aac streams: */
218 if(!sh->codecdata_len)
219 if(sh->a_in_buffer_len < sh->a_in_buffer_size){
220 sh->a_in_buffer_len +=
221 demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len],
222 sh->a_in_buffer_size - sh->a_in_buffer_len);
225 #ifdef DUMP_AAC_COMPRESSED
226 {int i;
227 for (i = 0; i < 16; i++)
228 printf ("%02X ", sh->a_in_buffer[i]);
229 printf ("\n");}
230 #endif
232 if(!sh->codecdata_len){
233 // raw aac stream:
234 do {
235 faac_sample_buffer = faacDecDecode(faac_hdec, &faac_finfo, sh->a_in_buffer, sh->a_in_buffer_len);
237 /* update buffer index after faacDecDecode */
238 if(faac_finfo.bytesconsumed >= sh->a_in_buffer_len) {
239 sh->a_in_buffer_len=0;
240 } else {
241 sh->a_in_buffer_len-=faac_finfo.bytesconsumed;
242 memmove(sh->a_in_buffer,&sh->a_in_buffer[faac_finfo.bytesconsumed],sh->a_in_buffer_len);
245 if(faac_finfo.error > 0) {
246 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"FAAD: error: %s, trying to resync!\n",
247 faacDecGetErrorMessage(faac_finfo.error));
248 if (sh->a_in_buffer_len <= 0) {
249 errors = MAX_FAAD_ERRORS;
250 break;
252 sh->a_in_buffer_len--;
253 memmove(sh->a_in_buffer,&sh->a_in_buffer[1],sh->a_in_buffer_len);
254 aac_sync(sh);
255 errors++;
256 } else
257 break;
258 } while(errors < MAX_FAAD_ERRORS);
259 } else {
260 // packetized (.mp4) aac stream:
261 unsigned char* bufptr=NULL;
262 double pts;
263 int buflen=ds_get_packet_pts(sh->ds, &bufptr, &pts);
264 if(buflen<=0) break;
265 if (pts != MP_NOPTS_VALUE) {
266 sh->pts = pts;
267 sh->pts_bytes = 0;
269 faac_sample_buffer = faacDecDecode(faac_hdec, &faac_finfo, bufptr, buflen);
271 //for (j=0;j<faac_finfo.channels;j++) printf("%d:%d\n", j, faac_finfo.channel_position[j]);
273 if(faac_finfo.error > 0) {
274 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"FAAD: Failed to decode frame: %s \n",
275 faacDecGetErrorMessage(faac_finfo.error));
276 } else if (faac_finfo.samples == 0) {
277 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"FAAD: Decoded zero samples!\n");
278 } else {
279 /* XXX: samples already multiplied by channels! */
280 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"FAAD: Successfully decoded frame (%ld Bytes)!\n",
281 sh->samplesize*faac_finfo.samples);
283 if (sh->channels >= 5)
284 reorder_channel_copy_nch(faac_sample_buffer,
285 AF_CHANNEL_LAYOUT_AAC_DEFAULT,
286 buf+len, AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT,
287 sh->channels,
288 faac_finfo.samples, sh->samplesize);
289 else
290 memcpy(buf+len,faac_sample_buffer, sh->samplesize*faac_finfo.samples);
291 last_dec_len = sh->samplesize*faac_finfo.samples;
292 len += last_dec_len;
293 sh->pts_bytes += last_dec_len;
294 //printf("FAAD: buffer: %d bytes consumed: %d \n", k, faac_finfo.bytesconsumed);
297 return len;