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.
12 #include "ad_internal.h"
16 static ad_info_t info
=
18 "AAC (MPEG2/4 Advanced Audio Coding)",
27 #ifndef USE_INTERNAL_FAAD
30 #include "libfaad2/faad.h"
33 /* configure maximum supported channels, *
34 * this is theoretically max. 64 chans */
35 #define FAAD_MAX_CHANNELS 6
36 #define FAAD_BUFFLEN (FAAD_MIN_STREAMSIZE*FAAD_MAX_CHANNELS)
38 //#define AAC_DUMP_COMPRESSED
40 static faacDecHandle faac_hdec
;
41 static faacDecFrameInfo faac_finfo
;
43 static int preinit(sh_audio_t
*sh
)
45 sh
->audio_out_minsize
=8192*FAAD_MAX_CHANNELS
;
46 sh
->audio_in_minsize
=FAAD_BUFFLEN
;
50 static int aac_probe(unsigned char *buffer
, int len
)
53 mp_msg(MSGT_DECAUDIO
,MSGL_V
, "\nAAC_PROBE: %d bytes\n", len
);
56 ((buffer
[i
] == 0xff) && ((buffer
[i
+1] & 0xf6) == 0xf0)) ||
57 (buffer
[i
] == 'A' && buffer
[i
+1] == 'D' && buffer
[i
+2] == 'I' && buffer
[i
+3] == 'F')
62 mp_msg(MSGT_DECAUDIO
,MSGL_V
, "AUDIO PAYLOAD: %x %x %x %x\n", buffer
[i
], buffer
[i
+1], buffer
[i
+2], buffer
[i
+3]);
65 mp_msg(MSGT_DECAUDIO
,MSGL_V
, "\nAAC_PROBE: ret %d\n", pos
);
69 extern int audio_output_channels
;
70 static int init(sh_audio_t
*sh
)
72 unsigned long faac_samplerate
;
73 unsigned char faac_channels
;
74 int faac_init
, pos
= 0;
75 faac_hdec
= faacDecOpen();
77 // If we don't get the ES descriptor, try manual config
78 if(!sh
->codecdata_len
&& sh
->wf
) {
79 sh
->codecdata_len
= sh
->wf
->cbSize
;
80 sh
->codecdata
= (char*)(sh
->wf
+1);
81 mp_msg(MSGT_DECAUDIO
,MSGL_DBG2
,"FAAD: codecdata extracted from WAVEFORMATEX\n");
83 if(!sh
->codecdata_len
) {
85 faacDecConfigurationPtr faac_conf
;
86 /* Set the default object type and samplerate */
87 /* This is useful for RAW AAC files */
88 faac_conf
= faacDecGetCurrentConfiguration(faac_hdec
);
90 faac_conf
->defSampleRate
= sh
->samplerate
;
91 /* XXX: FAAD support FLOAT output, how do we handle
92 * that (FAAD_FMT_FLOAT)? ::atmos
94 if (audio_output_channels
<= 2) faac_conf
->downMatrix
= 1;
95 switch(sh
->samplesize
){
97 mp_msg(MSGT_DECAUDIO
,MSGL_WARN
,"FAAD: 8Bit samplesize not supported by FAAD, assuming 16Bit!\n");
101 faac_conf
->outputFormat
= FAAD_FMT_16BIT
;
104 faac_conf
->outputFormat
= FAAD_FMT_24BIT
;
107 faac_conf
->outputFormat
= FAAD_FMT_32BIT
;
110 //faac_conf->defObjectType = LTP; // => MAIN, LC, SSR, LTP available.
112 faacDecSetConfiguration(faac_hdec
, faac_conf
);
115 sh
->a_in_buffer_len
= demux_read_data(sh
->ds
, sh
->a_in_buffer
, sh
->a_in_buffer_size
);
116 pos
= aac_probe(sh
->a_in_buffer
, sh
->a_in_buffer_len
);
118 sh
->a_in_buffer_len
-= pos
;
119 memmove(sh
->a_in_buffer
, &(sh
->a_in_buffer
[pos
]), sh
->a_in_buffer_len
);
120 sh
->a_in_buffer_len
+=
121 demux_read_data(sh
->ds
,&(sh
->a_in_buffer
[sh
->a_in_buffer_len
]),
122 sh
->a_in_buffer_size
- sh
->a_in_buffer_len
);
127 faac_init
= faacDecInit(faac_hdec
, sh
->a_in_buffer
,
128 sh
->a_in_buffer_len
, &faac_samplerate
, &faac_channels
);
130 sh
->a_in_buffer_len
-= (faac_init
> 0)?faac_init
:0; // how many bytes init consumed
131 // XXX FIXME: shouldn't we memcpy() here in a_in_buffer ?? --A'rpi
133 } else { // We have ES DS in codecdata
134 faacDecConfigurationPtr faac_conf
= faacDecGetCurrentConfiguration(faac_hdec
);
135 if (audio_output_channels
<= 2) {
136 faac_conf
->downMatrix
= 1;
137 faacDecSetConfiguration(faac_hdec
, faac_conf
);
141 for(i = 0; i < sh_audio->codecdata_len; i++)
142 printf("codecdata_dump %d: 0x%02X\n", i, sh_audio->codecdata[i]);*/
144 faac_init
= faacDecInit2(faac_hdec
, sh
->codecdata
,
145 sh
->codecdata_len
, &faac_samplerate
, &faac_channels
);
148 mp_msg(MSGT_DECAUDIO
,MSGL_WARN
,"FAAD: Failed to initialize the decoder!\n"); // XXX: deal with cleanup!
149 faacDecClose(faac_hdec
);
150 // XXX: free a_in_buffer here or in uninit?
153 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"FAAD: Decoder init done (%dBytes)!\n", sh
->a_in_buffer_len
); // XXX: remove or move to debug!
154 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"FAAD: Negotiated samplerate: %ldHz channels: %d\n", faac_samplerate
, faac_channels
);
155 sh
->channels
= faac_channels
;
156 if (audio_output_channels
<= 2) sh
->channels
= faac_channels
> 1 ? 2 : 1;
157 sh
->samplerate
= faac_samplerate
;
159 //sh->o_bps = sh->samplesize*faac_channels*faac_samplerate;
161 mp_msg(MSGT_DECAUDIO
,MSGL_WARN
,"FAAD: compressed input bitrate missing, assuming 128kbit/s!\n");
162 sh
->i_bps
= 128*1000/8; // XXX: HACK!!! ::atmos
164 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"FAAD: got %dkbit/s bitrate from MP4 header!\n",sh
->i_bps
*8/1000);
169 static void uninit(sh_audio_t
*sh
)
171 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"FAAD: Closing decoder!\n");
172 faacDecClose(faac_hdec
);
175 static int aac_sync(sh_audio_t
*sh
)
178 if(!sh
->codecdata_len
) {
179 if(sh
->a_in_buffer_len
< sh
->a_in_buffer_size
){
180 sh
->a_in_buffer_len
+=
181 demux_read_data(sh
->ds
,&sh
->a_in_buffer
[sh
->a_in_buffer_len
],
182 sh
->a_in_buffer_size
- sh
->a_in_buffer_len
);
184 pos
= aac_probe(sh
->a_in_buffer
, sh
->a_in_buffer_len
);
186 sh
->a_in_buffer_len
-= pos
;
187 memmove(sh
->a_in_buffer
, &(sh
->a_in_buffer
[pos
]), sh
->a_in_buffer_len
);
188 mp_msg(MSGT_DECAUDIO
,MSGL_V
, "\nAAC SYNC AFTER %d bytes\n", pos
);
194 static int control(sh_audio_t
*sh
,int cmd
,void* arg
, ...)
198 case ADCTRL_RESYNC_STREAM
:
202 case ADCTRL_SKIP_FRAME
:
206 return CONTROL_UNKNOWN
;
209 #define MAX_FAAD_ERRORS 10
210 static int decode_audio(sh_audio_t
*sh
,unsigned char *buf
,int minlen
,int maxlen
)
212 int j
= 0, len
= 0, last_dec_len
= 1, errors
= 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
227 for (i
= 0; i
< 16; i
++)
228 printf ("%02X ", sh
->a_in_buffer
[i
]);
232 if(!sh
->codecdata_len
){
235 faac_sample_buffer
= faacDecDecode(faac_hdec
, &faac_finfo
, sh
->a_in_buffer
+j
, 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;
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
));
252 } while(j
< FAAD_BUFFLEN
&& errors
< MAX_FAAD_ERRORS
);
254 // packetized (.mp4) aac stream:
255 unsigned char* bufptr
=NULL
;
257 int buflen
=ds_get_packet_pts(sh
->ds
, &bufptr
, &pts
);
259 if (pts
!= MP_NOPTS_VALUE
) {
263 faac_sample_buffer
= faacDecDecode(faac_hdec
, &faac_finfo
, bufptr
, buflen
);
265 //for (j=0;j<faac_finfo.channels;j++) printf("%d:%d\n", j, faac_finfo.channel_position[j]);
267 if(faac_finfo
.error
> 0) {
268 mp_msg(MSGT_DECAUDIO
,MSGL_WARN
,"FAAD: Failed to decode frame: %s \n",
269 faacDecGetErrorMessage(faac_finfo
.error
));
270 } else if (faac_finfo
.samples
== 0) {
271 mp_msg(MSGT_DECAUDIO
,MSGL_DBG2
,"FAAD: Decoded zero samples!\n");
273 /* XXX: samples already multiplied by channels! */
274 mp_msg(MSGT_DECAUDIO
,MSGL_DBG2
,"FAAD: Successfully decoded frame (%ld Bytes)!\n",
275 sh
->samplesize
*faac_finfo
.samples
);
276 memcpy(buf
+len
,faac_sample_buffer
, sh
->samplesize
*faac_finfo
.samples
);
277 last_dec_len
= sh
->samplesize
*faac_finfo
.samples
;
279 sh
->pts_bytes
+= last_dec_len
;
280 //printf("FAAD: buffer: %d bytes consumed: %d \n", k, faac_finfo.bytesconsumed);
286 #endif /* !HAVE_FAAD */