]> git.sesse.net Git - vlc/blob - modules/codec/faad.c
* all: who has seen that I have just forgot to release any buffers...
[vlc] / modules / codec / faad.c
1 /*****************************************************************************
2  * decoder.c: AAC decoder using libfaad2
3  *****************************************************************************
4  * Copyright (C) 2001, 2003 VideoLAN
5  * $Id: faad.c,v 1.3 2003/11/05 01:47:40 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <stdlib.h>
25
26 #include <vlc/aout.h>
27 #include <vlc/decoder.h>
28 #include <vlc/input.h>
29
30 #include <faad.h>
31 #include "codecs.h"
32
33 /*****************************************************************************
34  * Module descriptor
35  *****************************************************************************/
36 static int  Open( vlc_object_t * );
37
38 vlc_module_begin();
39     set_description( _("AAC audio decoder (using libfaad2)") );
40     set_capability( "decoder", 60 );
41     set_callbacks( Open, NULL );
42 vlc_module_end();
43
44
45 /****************************************************************************
46  * Local prototypes
47  ****************************************************************************/
48 static int  InitDecoder   ( decoder_t * );
49 static int  RunDecoder    ( decoder_t *, block_t * );
50 static int  EndDecoder    ( decoder_t * );
51
52 struct decoder_sys_t
53 {
54     /* faad handler */
55     faacDecHandle *hfaad;
56
57     /* audio output */
58     audio_sample_format_t output_format;
59     aout_instance_t *     p_aout;                                  /* opaque */
60     aout_input_t *        p_aout_input;                            /* opaque */
61
62     /* samples */
63     audio_date_t          date;
64
65     /* temporary buffer */
66     uint8_t               *p_buffer;
67     int                   i_buffer;
68     int                   i_buffer_size;
69 };
70
71 /*****************************************************************************
72  * OpenDecoder: probe the decoder and return score
73  *****************************************************************************/
74 static int  Open( vlc_object_t *p_this )
75 {
76     decoder_t *p_dec = (decoder_t*)p_this;
77
78     if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('m','p','4','a') )
79     {
80         return VLC_EGENERIC;
81     }
82
83     p_dec->pf_init = InitDecoder;
84     p_dec->pf_decode = RunDecoder;
85     p_dec->pf_end = EndDecoder;
86
87     p_dec->p_sys  = malloc( sizeof( decoder_sys_t ) );
88
89     return VLC_SUCCESS;
90 }
91
92 static unsigned int pi_channels_maps[7] =
93 {
94     0,
95     AOUT_CHAN_CENTER,
96     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
97     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
98     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
99     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
100      /* FIXME */
101     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_REARCENTER
102 };
103
104 /*****************************************************************************
105  * InitDecoder:
106  *****************************************************************************/
107 static int  InitDecoder   ( decoder_t *p_dec )
108 {
109     decoder_sys_t *p_sys = p_dec->p_sys;
110     WAVEFORMATEX    wf, *p_wf;
111     faacDecConfiguration *cfg;
112
113     if( ( p_wf = (WAVEFORMATEX*)p_dec->p_fifo->p_waveformatex ) == NULL )
114     {
115         p_wf = &wf;
116         memset( p_wf, 0, sizeof( WAVEFORMATEX ) );
117     }
118
119     /* Open a faad context */
120     if( ( p_sys->hfaad = faacDecOpen() ) == NULL )
121     {
122         msg_Err( p_dec, "Cannot initialize faad" );
123         return VLC_EGENERIC;
124     }
125
126     if( p_wf->cbSize > 0 )
127     {
128         /* We have a decoder config so init the handle */
129         unsigned long   i_rate;
130         unsigned char   i_channels;
131
132         if( faacDecInit2( p_sys->hfaad,
133                           (uint8_t*)&p_wf[1], p_wf->cbSize,
134                           &i_rate, &i_channels ) < 0 )
135         {
136             return VLC_EGENERIC;
137         }
138
139         p_sys->output_format.i_rate = i_rate;
140         p_sys->output_format.i_physical_channels =
141         p_sys->output_format.i_original_channels =
142             pi_channels_maps[i_channels];
143     }
144     else
145     {
146         /* Will be initalised from first frame */
147         p_sys->output_format.i_rate = 0;
148         p_sys->output_format.i_physical_channels =
149         p_sys->output_format.i_original_channels = 0;
150     }
151     p_sys->output_format.i_format = VLC_FOURCC('f','l','3','2');
152
153     p_sys->p_aout = NULL;
154     p_sys->p_aout_input = NULL;
155
156     /* set the faad config */
157     cfg = faacDecGetCurrentConfiguration( p_sys->hfaad );
158     cfg->outputFormat = FAAD_FMT_FLOAT;
159     faacDecSetConfiguration( p_sys->hfaad, cfg );
160
161     /* buffer */
162     p_sys->i_buffer = 0;
163     p_sys->i_buffer_size = 10000;
164     p_sys->p_buffer = malloc( p_sys->i_buffer_size );
165
166     return VLC_SUCCESS;
167 }
168
169 /*****************************************************************************
170  * InitDecoder:
171  *****************************************************************************/
172 static int  RunDecoder    ( decoder_t *p_dec, block_t *p_block )
173 {
174     decoder_sys_t *p_sys = p_dec->p_sys;
175
176     int          i_used = 0;
177     mtime_t      i_pts = p_block->i_pts;
178
179     /* Append the block to the temporary buffer */
180     if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
181     {
182         p_sys->i_buffer_size += p_block->i_buffer;
183         p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size );
184     }
185     memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer, p_block->i_buffer );
186     p_sys->i_buffer += p_block->i_buffer;
187
188     if( p_sys->output_format.i_rate == 0 )
189     {
190         unsigned long   i_rate;
191         unsigned char   i_channels;
192
193         /* Init faad with the first frame */
194         if( faacDecInit( p_sys->hfaad,
195                          p_sys->p_buffer, p_sys->i_buffer,
196                          &i_rate, &i_channels ) < 0 )
197         {
198             block_Release( p_block );
199             return VLC_EGENERIC;
200         }
201         p_sys->output_format.i_rate = i_rate;
202         p_sys->output_format.i_physical_channels =
203         p_sys->output_format.i_original_channels =
204             pi_channels_maps[i_channels];
205     }
206
207     /* Decode all data */
208     while( i_used < p_sys->i_buffer )
209     {
210         void *samples;
211         faacDecFrameInfo frame;
212         aout_buffer_t   *out;
213
214         samples = faacDecDecode( p_sys->hfaad, &frame,
215                                  &p_sys->p_buffer[i_used], p_sys->i_buffer - i_used );
216
217         if( frame.error > 0 )
218         {
219             msg_Warn( p_dec, "%s", faacDecGetErrorMessage( frame.error ) );
220             /* flush the buffer */
221             p_sys->i_buffer = 0;
222             block_Release( p_block );
223             return VLC_SUCCESS;
224         }
225         if( frame.channels <= 0 || frame.channels > 6 )
226         {
227             msg_Warn( p_dec, "invalid channels count" );
228             /* flush the buffer */
229             p_sys->i_buffer = 0;
230             block_Release( p_block );
231             return VLC_SUCCESS;
232         }
233         if( frame.samples <= 0 )
234         {
235             msg_Warn( p_dec, "decoded zero samples" );
236             /* flush the buffer */
237             p_sys->i_buffer = 0;
238             block_Release( p_block );
239             return VLC_SUCCESS;
240         }
241
242         /* we have decoded a valid frame */
243         /* msg_Dbg( p_dec, "consumed %d for %dHz %dc %lld", frame.bytesconsumed, frame.samplerate, frame.channels, i_pts ); */
244         i_used += frame.bytesconsumed;
245
246
247         /* create/recreate the output */
248         if( p_sys->p_aout_input &&
249             ( p_sys->output_format.i_original_channels != pi_channels_maps[frame.channels] ||
250               p_sys->output_format.i_rate != frame.samplerate ) )
251         {
252             aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
253             p_sys->p_aout_input = NULL;
254         }
255
256         if( p_sys->p_aout_input == NULL )
257         {
258             p_sys->output_format.i_physical_channels =
259             p_sys->output_format.i_original_channels = pi_channels_maps[frame.channels];
260             p_sys->output_format.i_rate = frame.samplerate;
261
262             aout_DateInit( &p_sys->date, p_sys->output_format.i_rate );
263             aout_DateSet( &p_sys->date, 0 );
264
265             p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout, &p_sys->output_format );
266         }
267
268         if( p_sys->p_aout_input == NULL )
269         {
270             msg_Err( p_dec, "cannot create aout" );
271             block_Release( p_block );
272             return VLC_EGENERIC;
273         }
274
275         if( i_pts != 0 && i_pts != aout_DateGet( &p_sys->date ) )
276         {
277             aout_DateSet( &p_sys->date, i_pts );
278         }
279         else if( !aout_DateGet( &p_sys->date ) )
280         {
281             /* Wait for a dated packet */
282             msg_Dbg( p_dec, "no date" );
283             p_sys->i_buffer = 0;
284             return VLC_SUCCESS;
285         }
286         i_pts = 0;  /* PTS is valid only once */
287
288         if( ( out = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
289                                        frame.samples / frame.channels ) ) == NULL )
290         {
291             msg_Err( p_dec, "cannot get a new buffer" );
292             block_Release( p_block );
293             return VLC_EGENERIC;
294         }
295         out->start_date = aout_DateGet( &p_sys->date );
296         out->end_date   = aout_DateIncrement( &p_sys->date,
297                                               frame.samples / frame.channels );
298         memcpy( out->p_buffer, samples, out->i_nb_bytes );
299
300         aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, out );
301     }
302
303     p_sys->i_buffer -= i_used;
304     if( p_sys->i_buffer > 0 )
305     {
306         memmove( &p_sys->p_buffer[0], &p_sys->p_buffer[i_used], p_sys->i_buffer );
307     }
308
309     block_Release( p_block );
310     return VLC_SUCCESS;
311 }
312
313 /*****************************************************************************
314  * InitDecoder:
315  *****************************************************************************/
316 static int  EndDecoder    ( decoder_t *p_dec )
317 {
318     decoder_sys_t *p_sys = p_dec->p_sys;
319
320     if( p_sys->p_aout_input )
321     {
322         aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
323     }
324
325     faacDecClose( p_sys->hfaad );
326     free( p_sys );
327
328     return VLC_SUCCESS;
329 }
330
331
332