]> git.sesse.net Git - vlc/blob - modules/codec/mpeg_audio/decoder.c
660207794223ec56e18fd234f6fe71f8f1cbb18e
[vlc] / modules / codec / mpeg_audio / decoder.c
1 /*****************************************************************************
2  * decoder.c: MPEG audio decoder thread
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: decoder.c,v 1.7 2002/10/27 16:58:13 gbazin Exp $
6  *
7  * Authors: Michel Kaempf <maxx@via.ecp.fr>
8  *          Michel Lespinasse <walken@via.ecp.fr>
9  *          Samuel Hocevar <sam@via.ecp.fr>
10  *          Cyril Deguet <asmax@via.ecp.fr>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #include <stdlib.h>                                      /* malloc(), free() */
31 #include <string.h>
32
33 #include <vlc/vlc.h>
34 #include <vlc/decoder.h>
35 #include <vlc/aout.h>
36
37 #include "generic.h"
38 #include "decoder.h"
39
40 #define ADEC_FRAME_NB 1152
41
42 /*****************************************************************************
43  * Local Prototypes
44  *****************************************************************************/
45 static int  OpenDecoder    ( vlc_object_t * );
46 static int  RunDecoder     ( decoder_fifo_t * );
47
48 static void EndThread      ( adec_thread_t * );
49 static void DecodeThread   ( adec_thread_t * );
50
51 /*****************************************************************************
52  * Module descriptor
53  *****************************************************************************/
54 vlc_module_begin();
55     set_description( _("MPEG I/II layer 1/2 audio decoder") );
56     set_capability( "decoder", 50 );
57     add_requirement( FPU );
58     add_shortcut( "builtin" );
59     set_callbacks( OpenDecoder, NULL );
60 vlc_module_end();
61
62 /*****************************************************************************
63  * OpenDecoder: probe the decoder and return score
64  *****************************************************************************
65  * Tries to launch a decoder and return score so that the interface is able
66  * to choose.
67  *****************************************************************************/
68 static int OpenDecoder( vlc_object_t *p_this )
69 {   
70     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
71
72     if( p_fifo->i_fourcc != VLC_FOURCC('m','p','g','a') )
73     {   
74         return VLC_EGENERIC;
75     }
76     
77     p_fifo->pf_run = RunDecoder;
78     return VLC_SUCCESS;
79 }
80
81 /*****************************************************************************
82  * RunDecoder: initialize, go inside main loop, destroy
83  *****************************************************************************/
84 static int RunDecoder( decoder_fifo_t *p_fifo )
85 {
86     adec_thread_t   * p_dec;
87     
88     /* Allocate the memory needed to store the thread's structure */
89     if ( (p_dec = (adec_thread_t *)malloc (sizeof(adec_thread_t))) == NULL ) 
90     {
91         msg_Err( p_fifo, "out of memory" );
92         DecoderError( p_fifo );
93         return 0;
94     }
95     
96     /*
97      * Initialize the thread properties
98      */
99     p_dec->p_fifo = p_fifo;
100
101     /* 
102      * Initilize the banks
103      */
104     p_dec->bank_0.actual = p_dec->bank_0.v1;
105     p_dec->bank_0.pos = 0;
106     p_dec->bank_1.actual = p_dec->bank_1.v1;
107     p_dec->bank_1.pos = 0;
108     
109     /*
110      * Initialize bit stream 
111      */
112     if( InitBitstream( &p_dec->bit_stream, p_dec->p_fifo, NULL, NULL )
113         != VLC_SUCCESS )
114     {
115         msg_Err( p_fifo, "cannot initialize bitstream" );
116         DecoderError( p_fifo );
117         return 0;
118     }
119
120     /* We do not create the audio output fifo now, but
121        it will be created when the first frame is received */
122     p_dec->p_aout = NULL;
123     p_dec->p_aout_input = NULL;
124
125     /* Audio decoder thread's main loop */
126     while( (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) )
127     {
128         DecodeThread( p_dec );
129     }
130     
131     /* If b_error is set, the audio decoder thread enters the error loop */
132     if( p_dec->p_fifo->b_error ) 
133     {
134         DecoderError( p_dec->p_fifo );
135     }
136
137     /* End of the audio decoder thread */
138     EndThread( p_dec );
139
140     return( 0 );
141 }
142
143 /*
144  * Following functions are local to this module
145  */
146
147 /*****************************************************************************
148  * DecodeThread: decodes a mpeg frame
149  *****************************************************************************/
150 static void DecodeThread( adec_thread_t * p_dec )
151 {
152     mtime_t pts;
153     aout_buffer_t * p_aout_buffer;
154
155     adec_sync_info_t sync_info;
156     
157     /* Look for sync word - should be 0x0b77 */
158     RealignBits( &p_dec->bit_stream );
159     while( (ShowBits( &p_dec->bit_stream, 16 ) & 0xfff0) != 0xfff0 && 
160            (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error))
161     {
162         RemoveBits( &p_dec->bit_stream, 8 );
163     }
164
165     /* Set the Presentation Time Stamp */
166     NextPTS( &p_dec->bit_stream, &pts, NULL );
167     if ( pts != 0 && pts != aout_DateGet( &p_dec->end_date ) )
168     {
169         aout_DateSet( &p_dec->end_date, pts );
170     }
171
172     if( !adec_SyncFrame( p_dec, &sync_info ) )
173     {
174         /* Create the output fifo if it doesn't exist yet */
175         if( ( p_dec->p_aout_input == NULL ) ||
176             ( p_dec->output_format.i_channels !=
177                ( sync_info.b_stereo ? AOUT_CHAN_STEREO : AOUT_CHAN_MONO ) ) ||
178             ( p_dec->output_format.i_rate != sync_info.sample_rate ) )
179         {
180             if( p_dec->p_aout_input )
181             {
182                 /* Delete old output */
183                 msg_Warn( p_dec->p_fifo, "opening a new aout" );
184                 aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
185             }
186
187             /* Set output configuration */
188             p_dec->output_format.i_format   = VLC_FOURCC('f','l','3','2');
189             p_dec->output_format.i_channels =
190                ( sync_info.b_stereo ? AOUT_CHAN_STEREO : AOUT_CHAN_MONO );
191             p_dec->output_format.i_rate     = sync_info.sample_rate;
192             aout_DateInit( &p_dec->end_date, sync_info.sample_rate );
193             p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
194                                                &p_dec->p_aout,
195                                                &p_dec->output_format );
196         }
197
198         if( p_dec->p_aout_input == NULL )
199         {
200             msg_Err( p_dec->p_fifo, "failed to create aout fifo" );
201             p_dec->p_fifo->b_error = 1;
202             return;
203         }
204
205         if( !aout_DateGet( &p_dec->end_date ) )
206         {
207             /* We've just started the stream, wait for the first PTS. */
208             return;
209         }
210
211         p_aout_buffer = aout_DecNewBuffer( p_dec->p_aout,
212                                            p_dec->p_aout_input,
213                                            ADEC_FRAME_NB );
214         if( !p_aout_buffer )
215         {
216             msg_Err( p_dec->p_fifo, "cannot get aout buffer" );
217             p_dec->p_fifo->b_error = 1;
218             return;
219         }
220         p_aout_buffer->start_date = aout_DateGet( &p_dec->end_date );
221         p_aout_buffer->end_date = aout_DateIncrement( &p_dec->end_date,
222                                                       ADEC_FRAME_NB );
223
224         if( adec_DecodeFrame (p_dec, (float*)p_aout_buffer->p_buffer ) )
225         {
226             /* Ouch, failed decoding... We'll have to resync */
227             aout_DecDeleteBuffer( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer );
228         }
229         else
230         {
231             aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer );
232         }
233     }
234 }
235
236 /*****************************************************************************
237  * EndThread : audio decoder thread destruction
238  *****************************************************************************
239  * This function is called when the thread ends after a sucessful
240  * initialization.
241  *****************************************************************************/
242 static void EndThread ( adec_thread_t *p_dec )
243 {
244     /* If the audio output fifo was created, we destroy it */
245     if( p_dec->p_aout_input )
246     {
247         aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
248         
249     }
250
251     CloseBitstream( &p_dec->bit_stream );
252
253     /* Destroy descriptor */
254     free( p_dec );
255 }
256