2 * MPlayer AAC decoder using libfaad2
4 * Copyright (C) 2002 Felix Buenemann <atmosfear at users.sourceforge.net>
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "ad_internal.h"
30 #include "libaf/reorder_ch.h"
32 static const ad_info_t info
=
34 "AAC (MPEG2/4 Advanced Audio Coding)",
43 #ifndef CONFIG_FAAD_INTERNAL
46 #include "libfaad2/faad.h"
49 /* configure maximum supported channels, *
50 * this is theoretically max. 64 chans */
51 #define FAAD_MAX_CHANNELS 8
52 #define FAAD_BUFFLEN (FAAD_MIN_STREAMSIZE*FAAD_MAX_CHANNELS)
54 //#define AAC_DUMP_COMPRESSED
56 static faacDecHandle faac_hdec
;
57 static faacDecFrameInfo faac_finfo
;
59 static int preinit(sh_audio_t
*sh
)
61 sh
->audio_out_minsize
=8192*FAAD_MAX_CHANNELS
;
62 sh
->audio_in_minsize
=FAAD_BUFFLEN
;
66 static int aac_probe(unsigned char *buffer
, int len
)
69 mp_msg(MSGT_DECAUDIO
,MSGL_V
, "\nAAC_PROBE: %d bytes\n", len
);
72 ((buffer
[i
] == 0xff) && ((buffer
[i
+1] & 0xf6) == 0xf0)) ||
73 (buffer
[i
] == 'A' && buffer
[i
+1] == 'D' && buffer
[i
+2] == 'I' && buffer
[i
+3] == 'F')
78 mp_msg(MSGT_DECAUDIO
,MSGL_V
, "AUDIO PAYLOAD: %x %x %x %x\n", buffer
[i
], buffer
[i
+1], buffer
[i
+2], buffer
[i
+3]);
81 mp_msg(MSGT_DECAUDIO
,MSGL_V
, "\nAAC_PROBE: ret %d\n", pos
);
85 static int init(sh_audio_t
*sh
)
87 struct MPOpts
*opts
= sh
->opts
;
88 unsigned long faac_samplerate
;
89 unsigned char faac_channels
;
90 int faac_init
, pos
= 0;
91 faac_hdec
= faacDecOpen();
93 // If we don't get the ES descriptor, try manual config
94 if(!sh
->codecdata_len
&& sh
->wf
) {
95 sh
->codecdata_len
= sh
->wf
->cbSize
;
96 sh
->codecdata
= malloc(sh
->codecdata_len
);
97 memcpy(sh
->codecdata
, sh
->wf
+1, sh
->codecdata_len
);
98 mp_msg(MSGT_DECAUDIO
,MSGL_DBG2
,"FAAD: codecdata extracted from WAVEFORMATEX\n");
100 if(!sh
->codecdata_len
|| sh
->format
== mmioFOURCC('M', 'P', '4', 'L')) {
101 faacDecConfigurationPtr faac_conf
;
102 /* Set the default object type and samplerate */
103 /* This is useful for RAW AAC files */
104 faac_conf
= faacDecGetCurrentConfiguration(faac_hdec
);
106 faac_conf
->defSampleRate
= sh
->samplerate
;
107 /* XXX: FAAD support FLOAT output, how do we handle
108 * that (FAAD_FMT_FLOAT)? ::atmos
110 if (opts
->audio_output_channels
<= 2)
111 faac_conf
->downMatrix
= 1;
112 switch(sh
->samplesize
){
114 mp_msg(MSGT_DECAUDIO
,MSGL_WARN
,"FAAD: 8Bit samplesize not supported by FAAD, assuming 16Bit!\n");
118 faac_conf
->outputFormat
= FAAD_FMT_16BIT
;
121 faac_conf
->outputFormat
= FAAD_FMT_24BIT
;
124 faac_conf
->outputFormat
= FAAD_FMT_32BIT
;
127 //faac_conf->defObjectType = LTP; // => MAIN, LC, SSR, LTP available.
129 faacDecSetConfiguration(faac_hdec
, faac_conf
);
131 sh
->a_in_buffer_len
= demux_read_data(sh
->ds
, sh
->a_in_buffer
, sh
->a_in_buffer_size
);
132 if (!sh
->a_in_buffer_len
) {
133 // faad init will crash with 0 buffer length
134 mp_msg(MSGT_DECAUDIO
, MSGL_FATAL
, "Could not get audio data!\n");
137 #if CONFIG_FAAD_INTERNAL
138 /* init the codec, look for LATM */
139 faac_init
= faacDecInit(faac_hdec
, sh
->a_in_buffer
,
140 sh
->a_in_buffer_len
, &faac_samplerate
, &faac_channels
,1);
141 if (faac_init
< 0 && sh
->a_in_buffer_len
>= 3 && sh
->format
== mmioFOURCC('M', 'P', '4', 'L')) {
142 // working LATM not found at first try, look further on in stream
145 for (i
= 0; i
< 5; i
++) {
146 pos
= sh
->a_in_buffer_len
-3;
147 memmove(sh
->a_in_buffer
, &(sh
->a_in_buffer
[pos
]), 3);
148 sh
->a_in_buffer_len
= 3;
149 sh
->a_in_buffer_len
+= demux_read_data(sh
->ds
,&sh
->a_in_buffer
[sh
->a_in_buffer_len
],
150 sh
->a_in_buffer_size
- sh
->a_in_buffer_len
);
151 faac_init
= faacDecInit(faac_hdec
, sh
->a_in_buffer
,
152 sh
->a_in_buffer_len
, &faac_samplerate
, &faac_channels
,1);
153 if (faac_init
>= 0) break;
157 /* external faad does not have latm lookup support */
158 faac_init
= faacDecInit(faac_hdec
, sh
->a_in_buffer
,
159 sh
->a_in_buffer_len
, &faac_samplerate
, &faac_channels
);
163 pos
= aac_probe(sh
->a_in_buffer
, sh
->a_in_buffer_len
);
165 sh
->a_in_buffer_len
-= pos
;
166 memmove(sh
->a_in_buffer
, &(sh
->a_in_buffer
[pos
]), sh
->a_in_buffer_len
);
167 sh
->a_in_buffer_len
+=
168 demux_read_data(sh
->ds
,&(sh
->a_in_buffer
[sh
->a_in_buffer_len
]),
169 sh
->a_in_buffer_size
- sh
->a_in_buffer_len
);
174 #if CONFIG_FAAD_INTERNAL
175 faac_init
= faacDecInit(faac_hdec
, sh
->a_in_buffer
,
176 sh
->a_in_buffer_len
, &faac_samplerate
, &faac_channels
,0);
178 faac_init
= faacDecInit(faac_hdec
, sh
->a_in_buffer
,
179 sh
->a_in_buffer_len
, &faac_samplerate
, &faac_channels
);
183 sh
->a_in_buffer_len
-= (faac_init
> 0)?faac_init
:0; // how many bytes init consumed
184 // XXX FIXME: shouldn't we memcpy() here in a_in_buffer ?? --A'rpi
186 } else { // We have ES DS in codecdata
187 faacDecConfigurationPtr faac_conf
= faacDecGetCurrentConfiguration(faac_hdec
);
188 if (opts
->audio_output_channels
<= 2) {
189 faac_conf
->downMatrix
= 1;
190 faacDecSetConfiguration(faac_hdec
, faac_conf
);
194 for(i = 0; i < sh_audio->codecdata_len; i++)
195 printf("codecdata_dump %d: 0x%02X\n", i, sh_audio->codecdata[i]);*/
197 faac_init
= faacDecInit2(faac_hdec
, sh
->codecdata
,
198 sh
->codecdata_len
, &faac_samplerate
, &faac_channels
);
201 mp_msg(MSGT_DECAUDIO
,MSGL_WARN
,"FAAD: Failed to initialize the decoder!\n"); // XXX: deal with cleanup!
202 faacDecClose(faac_hdec
);
203 // XXX: free a_in_buffer here or in uninit?
206 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"FAAD: Decoder init done (%dBytes)!\n", sh
->a_in_buffer_len
); // XXX: remove or move to debug!
207 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"FAAD: Negotiated samplerate: %ldHz channels: %d\n", faac_samplerate
, faac_channels
);
208 // 8 channels is aac channel order #7.
209 sh
->channels
= faac_channels
== 7 ? 8 : faac_channels
;
210 if (opts
->audio_output_channels
<= 2)
211 sh
->channels
= faac_channels
> 1 ? 2 : 1;
212 sh
->samplerate
= faac_samplerate
;
214 //sh->o_bps = sh->samplesize*faac_channels*faac_samplerate;
216 mp_msg(MSGT_DECAUDIO
, MSGL_V
, "FAAD: compressed input bitrate missing, assuming 128kbit/s!\n");
217 sh
->i_bps
= 128*1000/8; // XXX: HACK!!! ::atmos
219 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"FAAD: got %dkbit/s bitrate from MP4 header!\n",sh
->i_bps
*8/1000);
224 static void uninit(sh_audio_t
*sh
)
226 mp_msg(MSGT_DECAUDIO
,MSGL_V
,"FAAD: Closing decoder!\n");
227 faacDecClose(faac_hdec
);
230 static int aac_sync(sh_audio_t
*sh
)
233 // do not probe LATM, faad does that
234 if(!sh
->codecdata_len
&& sh
->format
!= mmioFOURCC('M', 'P', '4', 'L')) {
235 if(sh
->a_in_buffer_len
< sh
->a_in_buffer_size
){
236 sh
->a_in_buffer_len
+=
237 demux_read_data(sh
->ds
,&sh
->a_in_buffer
[sh
->a_in_buffer_len
],
238 sh
->a_in_buffer_size
- sh
->a_in_buffer_len
);
240 pos
= aac_probe(sh
->a_in_buffer
, sh
->a_in_buffer_len
);
242 sh
->a_in_buffer_len
-= pos
;
243 memmove(sh
->a_in_buffer
, &(sh
->a_in_buffer
[pos
]), sh
->a_in_buffer_len
);
244 mp_msg(MSGT_DECAUDIO
,MSGL_V
, "\nAAC SYNC AFTER %d bytes\n", pos
);
250 static int control(sh_audio_t
*sh
,int cmd
,void* arg
, ...)
254 case ADCTRL_RESYNC_STREAM
:
258 case ADCTRL_SKIP_FRAME
:
262 return CONTROL_UNKNOWN
;
265 #define MAX_FAAD_ERRORS 10
266 static int decode_audio(sh_audio_t
*sh
,unsigned char *buf
,int minlen
,int maxlen
)
268 int len
= 0, last_dec_len
= 1, errors
= 0;
270 void *faac_sample_buffer
;
272 while(len
< minlen
&& last_dec_len
> 0 && errors
< MAX_FAAD_ERRORS
) {
274 /* update buffer for raw aac streams: */
275 if(!sh
->codecdata_len
)
276 if(sh
->a_in_buffer_len
< sh
->a_in_buffer_size
){
277 sh
->a_in_buffer_len
+=
278 demux_read_data(sh
->ds
,&sh
->a_in_buffer
[sh
->a_in_buffer_len
],
279 sh
->a_in_buffer_size
- sh
->a_in_buffer_len
);
282 #ifdef DUMP_AAC_COMPRESSED
284 for (i
= 0; i
< 16; i
++)
285 printf ("%02X ", sh
->a_in_buffer
[i
]);
289 if(!sh
->codecdata_len
){
292 faac_sample_buffer
= faacDecDecode(faac_hdec
, &faac_finfo
, sh
->a_in_buffer
, sh
->a_in_buffer_len
);
294 /* update buffer index after faacDecDecode */
295 if(faac_finfo
.bytesconsumed
>= sh
->a_in_buffer_len
) {
296 sh
->a_in_buffer_len
=0;
298 sh
->a_in_buffer_len
-=faac_finfo
.bytesconsumed
;
299 memmove(sh
->a_in_buffer
,&sh
->a_in_buffer
[faac_finfo
.bytesconsumed
],sh
->a_in_buffer_len
);
302 if(faac_finfo
.error
> 0) {
303 mp_msg(MSGT_DECAUDIO
,MSGL_WARN
,"FAAD: error: %s, trying to resync!\n",
304 faacDecGetErrorMessage(faac_finfo
.error
));
305 if (sh
->a_in_buffer_len
<= 0) {
306 errors
= MAX_FAAD_ERRORS
;
309 sh
->a_in_buffer_len
--;
310 memmove(sh
->a_in_buffer
,&sh
->a_in_buffer
[1],sh
->a_in_buffer_len
);
315 } while(errors
< MAX_FAAD_ERRORS
);
317 // packetized (.mp4) aac stream:
318 unsigned char* bufptr
=NULL
;
320 int buflen
=ds_get_packet_pts(sh
->ds
, &bufptr
, &pts
);
322 if (pts
!= MP_NOPTS_VALUE
) {
326 faac_sample_buffer
= faacDecDecode(faac_hdec
, &faac_finfo
, bufptr
, buflen
);
328 //for (j=0;j<faac_finfo.channels;j++) printf("%d:%d\n", j, faac_finfo.channel_position[j]);
330 if(faac_finfo
.error
> 0) {
331 mp_msg(MSGT_DECAUDIO
,MSGL_WARN
,"FAAD: Failed to decode frame: %s \n",
332 faacDecGetErrorMessage(faac_finfo
.error
));
333 } else if (faac_finfo
.samples
== 0) {
334 mp_msg(MSGT_DECAUDIO
,MSGL_DBG2
,"FAAD: Decoded zero samples!\n");
336 /* XXX: samples already multiplied by channels! */
337 mp_msg(MSGT_DECAUDIO
,MSGL_DBG2
,"FAAD: Successfully decoded frame (%ld Bytes)!\n",
338 sh
->samplesize
*faac_finfo
.samples
);
340 if (sh
->channels
>= 5)
341 reorder_channel_copy_nch(faac_sample_buffer
,
342 AF_CHANNEL_LAYOUT_AAC_DEFAULT
,
343 buf
+len
, AF_CHANNEL_LAYOUT_MPLAYER_DEFAULT
,
345 faac_finfo
.samples
, sh
->samplesize
);
347 memcpy(buf
+len
,faac_sample_buffer
, sh
->samplesize
*faac_finfo
.samples
);
348 last_dec_len
= sh
->samplesize
*faac_finfo
.samples
;
350 sh
->pts_bytes
+= last_dec_len
;
351 //printf("FAAD: buffer: %d bytes consumed: %d \n", k, faac_finfo.bytesconsumed);