]> git.sesse.net Git - vlc/blob - plugins/ac3_adec/ac3_adec.c
* ALL: new module API. Makes a few things a lot simpler, and we gain
[vlc] / plugins / ac3_adec / ac3_adec.c
1 /*****************************************************************************
2  * ac3_adec.c: ac3 decoder module main file
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: ac3_adec.c,v 1.35 2002/07/31 20:56:50 sam Exp $
6  *
7  * Authors: Michel Lespinasse <walken@zoy.org>
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 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <string.h>                                              /* memset() */
29
30 #include <vlc/vlc.h>
31 #include <vlc/aout.h>
32 #include <vlc/decoder.h>
33
34 #ifdef HAVE_UNISTD_H
35 #   include <unistd.h>                                           /* getpid() */
36 #endif
37
38 #include "ac3_imdct.h"
39 #include "ac3_downmix.h"
40 #include "ac3_adec.h"
41
42 #define AC3DEC_FRAME_SIZE (2*1536) 
43
44 /*****************************************************************************
45  * Local prototypes
46  *****************************************************************************/
47 static int  OpenDecoder       ( vlc_object_t * );
48 static int  RunDecoder        ( decoder_fifo_t * );
49 static int  InitThread        ( ac3dec_t * p_adec );
50 static void EndThread         ( ac3dec_t * p_adec );
51 static void BitstreamCallback ( bit_stream_t *p_bit_stream,
52                                 vlc_bool_t b_new_pes );
53
54 /*****************************************************************************
55  * Module descriptor
56  *****************************************************************************/
57 vlc_module_begin();
58     add_category_hint( N_("Miscellaneous"), NULL );
59     add_module  ( "ac3-downmix", "downmix", NULL, NULL,
60                   N_("AC3 downmix module"), NULL );
61     add_module  ( "ac3-imdct", "imdct", NULL, NULL,
62                   N_("AC3 IMDCT module"), NULL );
63     set_description( _("software AC3 decoder") );
64     set_capability( "decoder", 50 );
65     set_callbacks( OpenDecoder, NULL );
66     add_shortcut( "ac3" );
67 vlc_module_end();         
68
69 /*****************************************************************************
70  * OpenDecoder: probe the decoder and return score
71  *****************************************************************************
72  * Tries to launch a decoder and return score so that the interface is able 
73  * to chose.
74  *****************************************************************************/
75 static int OpenDecoder( vlc_object_t *p_this )
76 {
77     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
78     
79     if( p_fifo->i_fourcc != VLC_FOURCC('a','5','2',' ') )
80     {   
81         return VLC_EGENERIC;
82     }
83
84     p_fifo->pf_run = RunDecoder;
85     return VLC_SUCCESS;
86 }
87
88 /*****************************************************************************
89  * RunDecoder: this function is called just after the thread is created
90  *****************************************************************************/
91 static int RunDecoder( decoder_fifo_t *p_fifo )
92 {
93     ac3dec_t *   p_ac3dec;
94     void *       p_orig;                          /* pointer before memalign */
95     vlc_bool_t   b_sync = 0;
96
97     /* Allocate the memory needed to store the thread's structure */
98     p_ac3dec = (ac3dec_t *)vlc_memalign( &p_orig, 16, sizeof(ac3dec_t) );
99     memset( p_ac3dec, 0, sizeof( ac3dec_t ) );
100
101     if( p_ac3dec == NULL )
102     {
103         msg_Err( p_fifo, "out of memory" );
104         DecoderError( p_fifo );
105         return( -1 );
106     }
107
108     /*
109      * Initialize the thread properties
110      */
111     p_ac3dec->p_fifo = p_fifo;
112     if( InitThread( p_ac3dec ) )
113     {
114         msg_Err( p_fifo, "could not initialize thread" );
115         DecoderError( p_fifo );
116         free( p_orig );
117         return( -1 );
118     }
119
120     /* ac3 decoder thread's main loop */
121     /* FIXME : do we have enough room to store the decoded frames ?? */
122     while ((!p_ac3dec->p_fifo->b_die) && (!p_ac3dec->p_fifo->b_error))
123     {
124         s16 * buffer;
125         ac3_sync_info_t sync_info;
126
127         if( !b_sync )
128         {
129              int i_sync_ptr;
130 #define p_bit_stream (&p_ac3dec->bit_stream)
131
132              /* Go to the next PES packet and jump to sync_ptr */
133              do {
134                 BitstreamNextDataPacket( p_bit_stream );
135              } while( !p_bit_stream->p_decoder_fifo->b_die
136                        && !p_bit_stream->p_decoder_fifo->b_error
137                        && p_bit_stream->p_data !=
138                           p_bit_stream->p_decoder_fifo->p_first->p_first );
139              i_sync_ptr = *(p_bit_stream->p_byte - 2) << 8
140                             | *(p_bit_stream->p_byte - 1);
141              p_bit_stream->p_byte += i_sync_ptr;
142
143              /* Empty the bit FIFO and realign the bit stream */
144              p_bit_stream->fifo.buffer = 0;
145              p_bit_stream->fifo.i_available = 0;
146              AlignWord( p_bit_stream );
147              b_sync = 1;
148 #undef p_bit_stream
149         }
150
151         if (ac3_sync_frame (p_ac3dec, &sync_info))
152         {
153             b_sync = 0;
154             continue;
155         }
156
157         if( ( p_ac3dec->p_aout_fifo != NULL ) &&
158             ( p_ac3dec->p_aout_fifo->i_rate != sync_info.sample_rate ) )
159         {
160             /* Make sure the output thread leaves the NextFrame() function */
161             vlc_mutex_lock (&(p_ac3dec->p_aout_fifo->data_lock));
162             aout_DestroyFifo (p_ac3dec->p_aout_fifo);
163             vlc_cond_signal (&(p_ac3dec->p_aout_fifo->data_wait));
164             vlc_mutex_unlock (&(p_ac3dec->p_aout_fifo->data_lock));
165
166             p_ac3dec->p_aout_fifo = NULL;
167         }
168
169         /* Creating the audio output fifo if not created yet */
170         if (p_ac3dec->p_aout_fifo == NULL ) {
171             p_ac3dec->p_aout_fifo =
172                 aout_CreateFifo( p_ac3dec->p_fifo, AOUT_FIFO_PCM, 2,
173                          sync_info.sample_rate, AC3DEC_FRAME_SIZE, NULL  );
174             if ( p_ac3dec->p_aout_fifo == NULL )
175             {
176                 p_ac3dec->p_fifo->b_error = 1;
177                 break;
178             }
179         }
180
181         CurrentPTS( &p_ac3dec->bit_stream,
182             &p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->i_end_frame],
183             NULL );
184         if( !p_ac3dec->p_aout_fifo->date[p_ac3dec->p_aout_fifo->i_end_frame] )
185         {
186             p_ac3dec->p_aout_fifo->date[
187                 p_ac3dec->p_aout_fifo->i_end_frame] =
188                 LAST_MDATE;
189         }
190     
191         buffer = ((s16 *)p_ac3dec->p_aout_fifo->buffer) + 
192             (p_ac3dec->p_aout_fifo->i_end_frame * AC3DEC_FRAME_SIZE);
193
194         if (ac3_decode_frame (p_ac3dec, buffer))
195         {
196             b_sync = 0;
197             continue;
198         }
199         
200         vlc_mutex_lock (&p_ac3dec->p_aout_fifo->data_lock);
201         p_ac3dec->p_aout_fifo->i_end_frame = 
202             (p_ac3dec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
203         vlc_cond_signal (&p_ac3dec->p_aout_fifo->data_wait);
204         vlc_mutex_unlock (&p_ac3dec->p_aout_fifo->data_lock);
205
206         RealignBits(&p_ac3dec->bit_stream);
207     }
208
209     /* If b_error is set, the ac3 decoder thread enters the error loop */
210     if (p_ac3dec->p_fifo->b_error)
211     {
212         DecoderError( p_ac3dec->p_fifo );
213     }
214
215     /* End of the ac3 decoder thread */
216     EndThread (p_ac3dec);
217
218     free( p_orig );
219
220     return( 0 );
221 }
222
223 /*****************************************************************************
224  * InitThread: initialize data before entering main loop
225  *****************************************************************************/
226 static int InitThread( ac3dec_t * p_ac3dec )
227 {
228     char *psz_name;
229
230     /*
231      * Choose the best downmix module
232      */
233     p_ac3dec->p_downmix = vlc_object_create( p_ac3dec->p_fifo,
234                                              sizeof( downmix_t ) );
235     p_ac3dec->p_downmix->psz_object_name = "downmix";
236
237     psz_name = config_GetPsz( p_ac3dec->p_downmix, "ac3-downmix" );
238     p_ac3dec->p_downmix->p_module =
239                     module_Need( p_ac3dec->p_downmix, "downmix", psz_name );
240     if( psz_name ) free( psz_name );
241
242     if( p_ac3dec->p_downmix->p_module == NULL )
243     {
244         msg_Err( p_ac3dec->p_fifo, "no suitable downmix module" );
245         vlc_object_destroy( p_ac3dec->p_downmix );
246         return( -1 );
247     }
248
249     /*
250      * Choose the best IMDCT module
251      */
252     p_ac3dec->p_imdct = vlc_object_create( p_ac3dec->p_fifo,
253                                            sizeof( imdct_t ) );
254     
255 #define IMDCT p_ac3dec->p_imdct
256     psz_name = config_GetPsz( p_ac3dec->p_fifo, "ac3-imdct" );
257     p_ac3dec->p_imdct->p_module =
258                    module_Need( p_ac3dec->p_imdct, "imdct", psz_name );
259     if( psz_name ) free( psz_name );
260
261     if( p_ac3dec->p_imdct->p_module == NULL )
262     {
263         msg_Err( p_ac3dec->p_fifo, "no suitable IMDCT module" );
264         vlc_object_destroy( p_ac3dec->p_imdct );
265         module_Unneed( p_ac3dec->p_downmix, p_ac3dec->p_downmix->p_module );
266         vlc_object_destroy( p_ac3dec->p_downmix );
267         return( -1 );
268     }
269
270     /* Initialize the ac3 decoder structures */
271     p_ac3dec->samples = vlc_memalign( &p_ac3dec->samples_orig,
272                                       16, 6 * 256 * sizeof(float) );
273
274     IMDCT->buf    = vlc_memalign( &IMDCT->buf_orig,
275                                   16, N/4 * sizeof(complex_t) );
276     IMDCT->delay  = vlc_memalign( &IMDCT->delay_orig,
277                                   16, 6 * 256 * sizeof(float) );
278     IMDCT->delay1 = vlc_memalign( &IMDCT->delay1_orig,
279                                   16, 6 * 256 * sizeof(float) );
280     IMDCT->xcos1  = vlc_memalign( &IMDCT->xcos1_orig,
281                                   16, N/4 * sizeof(float) );
282     IMDCT->xsin1  = vlc_memalign( &IMDCT->xsin1_orig,
283                                   16, N/4 * sizeof(float) );
284     IMDCT->xcos2  = vlc_memalign( &IMDCT->xcos2_orig,
285                                   16, N/8 * sizeof(float) );
286     IMDCT->xsin2  = vlc_memalign( &IMDCT->xsin2_orig,
287                                   16, N/8 * sizeof(float) );
288     IMDCT->xcos_sin_sse = vlc_memalign( &IMDCT->xcos_sin_sse_orig,
289                                         16, 128 * 4 * sizeof(float) );
290     IMDCT->w_1    = vlc_memalign( &IMDCT->w_1_orig,
291                                   16, 1  * sizeof(complex_t) );
292     IMDCT->w_2    = vlc_memalign( &IMDCT->w_2_orig,
293                                   16, 2  * sizeof(complex_t) );
294     IMDCT->w_4    = vlc_memalign( &IMDCT->w_4_orig,
295                                   16, 4  * sizeof(complex_t) );
296     IMDCT->w_8    = vlc_memalign( &IMDCT->w_8_orig,
297                                   16, 8  * sizeof(complex_t) );
298     IMDCT->w_16   = vlc_memalign( &IMDCT->w_16_orig,
299                                   16, 16 * sizeof(complex_t) );
300     IMDCT->w_32   = vlc_memalign( &IMDCT->w_32_orig,
301                                   16, 32 * sizeof(complex_t) );
302     IMDCT->w_64   = vlc_memalign( &IMDCT->w_64_orig,
303                                   16, 64 * sizeof(complex_t) );
304 #undef IMDCT
305
306     E_( ac3_init )( p_ac3dec );
307
308     /*
309      * Initialize the output properties
310      */
311     p_ac3dec->p_aout_fifo = NULL;
312
313     /*
314      * Bit stream
315      */
316     InitBitstream( &p_ac3dec->bit_stream, p_ac3dec->p_fifo,
317                    BitstreamCallback, (void *) p_ac3dec );
318     
319     return( 0 );
320 }
321
322 /*****************************************************************************
323  * EndThread : ac3 decoder thread destruction
324  *****************************************************************************/
325 static void EndThread (ac3dec_t * p_ac3dec)
326 {
327     /* If the audio output fifo was created, we destroy it */
328     if (p_ac3dec->p_aout_fifo != NULL)
329     {
330         aout_DestroyFifo (p_ac3dec->p_aout_fifo);
331
332         /* Make sure the output thread leaves the NextFrame() function */
333         vlc_mutex_lock (&(p_ac3dec->p_aout_fifo->data_lock));
334         vlc_cond_signal (&(p_ac3dec->p_aout_fifo->data_wait));
335         vlc_mutex_unlock (&(p_ac3dec->p_aout_fifo->data_lock));
336     }
337
338     /* Free allocated structures */
339 #define IMDCT p_ac3dec->p_imdct
340     free( IMDCT->w_1_orig );
341     free( IMDCT->w_64_orig );
342     free( IMDCT->w_32_orig );
343     free( IMDCT->w_16_orig );
344     free( IMDCT->w_8_orig );
345     free( IMDCT->w_4_orig );
346     free( IMDCT->w_2_orig );
347     free( IMDCT->xcos_sin_sse_orig );
348     free( IMDCT->xsin2_orig );
349     free( IMDCT->xcos2_orig );
350     free( IMDCT->xsin1_orig );
351     free( IMDCT->xcos1_orig );
352     free( IMDCT->delay1_orig );
353     free( IMDCT->delay_orig );
354     free( IMDCT->buf_orig );
355 #undef IMDCT
356
357     free( p_ac3dec->samples_orig );
358
359     /* Unlock the modules */
360     module_Unneed( p_ac3dec->p_downmix, p_ac3dec->p_downmix->p_module );
361     vlc_object_destroy( p_ac3dec->p_downmix );
362
363     module_Unneed( p_ac3dec->p_imdct, p_ac3dec->p_imdct->p_module );
364     vlc_object_destroy( p_ac3dec->p_imdct );
365
366     /* Free what's left of the decoder */
367     free( p_ac3dec->imdct_orig );
368 }
369
370 /*****************************************************************************
371  * BitstreamCallback: Import parameters from the new data/PES packet
372  *****************************************************************************
373  * This function is called by input's NextDataPacket.
374  *****************************************************************************/
375 static void BitstreamCallback ( bit_stream_t * p_bit_stream,
376                                 vlc_bool_t b_new_pes )
377 {
378     if( b_new_pes )
379     {
380         /* Drop special AC3 header */
381 /*        p_bit_stream->p_byte += 3; */
382     }
383 }
384