rpm: Remove MEncoder from rpm packaging
[mplayer/glamo.git] / libmpcodecs / ad_faad.c
blob63989b2a107282ac86223345c9f0d842c7e63668
1 /*
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.
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
27 #include "config.h"
28 #include "options.h"
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)",
35 "faad",
36 "Felix Buenemann",
37 "faad2",
38 "uses libfaad2"
41 LIBAD_EXTERN(faad)
43 #ifndef CONFIG_FAAD_INTERNAL
44 #include <faad.h>
45 #else
46 #include "libfaad2/faad.h"
47 #endif
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;
63 return 1;
66 static int aac_probe(unsigned char *buffer, int len)
68 int i = 0, pos = 0;
69 mp_msg(MSGT_DECAUDIO,MSGL_V, "\nAAC_PROBE: %d bytes\n", len);
70 while(i <= len-4) {
71 if(
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')
74 ) {
75 pos = i;
76 break;
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]);
79 i++;
81 mp_msg(MSGT_DECAUDIO,MSGL_V, "\nAAC_PROBE: ret %d\n", pos);
82 return 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);
105 if(sh->samplerate)
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){
113 case 1: // 8Bit
114 mp_msg(MSGT_DECAUDIO,MSGL_WARN,"FAAD: 8Bit samplesize not supported by FAAD, assuming 16Bit!\n");
115 default:
116 sh->samplesize=2;
117 case 2: // 16Bit
118 faac_conf->outputFormat = FAAD_FMT_16BIT;
119 break;
120 case 3: // 24Bit
121 faac_conf->outputFormat = FAAD_FMT_24BIT;
122 break;
123 case 4: // 32Bit
124 faac_conf->outputFormat = FAAD_FMT_32BIT;
125 break;
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");
135 return 0;
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
143 int i;
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;
156 #else
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);
160 #endif
162 if (faac_init < 0) {
163 pos = aac_probe(sh->a_in_buffer, sh->a_in_buffer_len);
164 if(pos) {
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);
170 pos = 0;
173 /* init the codec */
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);
177 #else
178 faac_init = faacDecInit(faac_hdec, sh->a_in_buffer,
179 sh->a_in_buffer_len, &faac_samplerate, &faac_channels);
180 #endif
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);
193 /*int i;
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);
200 if(faac_init < 0) {
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?
204 return 0;
205 } else {
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;
213 sh->samplesize=2;
214 //sh->o_bps = sh->samplesize*faac_channels*faac_samplerate;
215 if(!sh->i_bps) {
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
218 } else
219 mp_msg(MSGT_DECAUDIO,MSGL_V,"FAAD: got %dkbit/s bitrate from MP4 header!\n",sh->i_bps*8/1000);
221 return 1;
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)
232 int pos = 0;
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);
241 if(pos) {
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);
247 return pos;
250 static int control(sh_audio_t *sh,int cmd,void* arg, ...)
252 switch(cmd)
254 case ADCTRL_RESYNC_STREAM:
255 aac_sync(sh);
256 return CONTROL_TRUE;
257 #if 0
258 case ADCTRL_SKIP_FRAME:
259 return CONTROL_TRUE;
260 #endif
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;
269 // int j = 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
283 {int i;
284 for (i = 0; i < 16; i++)
285 printf ("%02X ", sh->a_in_buffer[i]);
286 printf ("\n");}
287 #endif
289 if(!sh->codecdata_len){
290 // raw aac stream:
291 do {
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;
297 } else {
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;
307 break;
309 sh->a_in_buffer_len--;
310 memmove(sh->a_in_buffer,&sh->a_in_buffer[1],sh->a_in_buffer_len);
311 aac_sync(sh);
312 errors++;
313 } else
314 break;
315 } while(errors < MAX_FAAD_ERRORS);
316 } else {
317 // packetized (.mp4) aac stream:
318 unsigned char* bufptr=NULL;
319 double pts;
320 int buflen=ds_get_packet_pts(sh->ds, &bufptr, &pts);
321 if(buflen<=0) break;
322 if (pts != MP_NOPTS_VALUE) {
323 sh->pts = pts;
324 sh->pts_bytes = 0;
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");
335 } else {
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,
344 sh->channels,
345 faac_finfo.samples, sh->samplesize);
346 else
347 memcpy(buf+len,faac_sample_buffer, sh->samplesize*faac_finfo.samples);
348 last_dec_len = sh->samplesize*faac_finfo.samples;
349 len += last_dec_len;
350 sh->pts_bytes += last_dec_len;
351 //printf("FAAD: buffer: %d bytes consumed: %d \n", k, faac_finfo.bytesconsumed);
354 return len;