]> git.sesse.net Git - vlc/blob - modules/codec/mpeg_audio/decoder.c
* Made audio_sample_format->i_format a FOURCC to allow the creation of
[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.5 2002/09/30 21:32:32 massiot 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     InitBitstream( &p_dec->bit_stream, p_dec->p_fifo, NULL, NULL );
113
114     /* We do not create the audio output fifo now, but
115        it will be created when the first frame is received */
116     p_dec->p_aout = NULL;
117     p_dec->p_aout_input = NULL;
118
119     /* Audio decoder thread's main loop */
120     while( (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error) )
121     {
122         DecodeThread( p_dec );
123     }
124     
125     /* If b_error is set, the audio decoder thread enters the error loop */
126     if( p_dec->p_fifo->b_error ) 
127     {
128         DecoderError( p_dec->p_fifo );
129     }
130
131     /* End of the audio decoder thread */
132     EndThread( p_dec );
133
134     return( 0 );
135 }
136
137 /*
138  * Following functions are local to this module
139  */
140
141 /*****************************************************************************
142  * DecodeThread: decodes a mpeg frame
143  *****************************************************************************/
144 static void DecodeThread( adec_thread_t * p_dec )
145 {
146     mtime_t pts;
147     aout_buffer_t * p_aout_buffer;
148
149     adec_sync_info_t sync_info;
150     
151     /* Look for sync word - should be 0x0b77 */
152     RealignBits( &p_dec->bit_stream );
153     while( (ShowBits( &p_dec->bit_stream, 16 ) & 0xfff0) != 0xfff0 && 
154            (!p_dec->p_fifo->b_die) && (!p_dec->p_fifo->b_error))
155     {
156         RemoveBits( &p_dec->bit_stream, 8 );
157     }
158
159     /* Set the Presentation Time Stamp */
160     NextPTS( &p_dec->bit_stream, &pts, NULL );
161     if ( pts != 0 && pts != aout_DateGet( &p_dec->end_date ) )
162     {
163         aout_DateSet( &p_dec->end_date, pts );
164     }
165
166     if( !adec_SyncFrame( p_dec, &sync_info ) )
167     {
168         /* Create the output fifo if it doesn't exist yet */
169         if( ( p_dec->p_aout_input == NULL )||
170             ( p_dec->output_format.i_channels != ( sync_info.b_stereo ? 2 : 1 ) )||
171             ( p_dec->output_format.i_rate != sync_info.sample_rate ) )
172         {
173             if( p_dec->p_aout_input )
174             {
175                 /* Delete old output */
176                 msg_Warn( p_dec->p_fifo, "opening a new aout" );
177                 aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
178             }
179
180             /* Set output configuration */
181             p_dec->output_format.i_format   = VLC_FOURCC('f','l','3','2');
182             p_dec->output_format.i_channels = ( sync_info.b_stereo ? 2 : 1 );
183             p_dec->output_format.i_rate     = sync_info.sample_rate;
184             aout_DateInit( &p_dec->end_date, sync_info.sample_rate );
185             p_dec->p_aout_input = aout_DecNew( p_dec->p_fifo,
186                                                &p_dec->p_aout,
187                                                &p_dec->output_format );
188         }
189
190         if( p_dec->p_aout_input == NULL )
191         {
192             msg_Err( p_dec->p_fifo, "failed to create aout fifo" );
193             p_dec->p_fifo->b_error = 1;
194             return;
195         }
196
197         if( !aout_DateGet( &p_dec->end_date ) )
198         {
199             /* We've just started the stream, wait for the first PTS. */
200             return;
201         }
202
203         p_aout_buffer = aout_DecNewBuffer( p_dec->p_aout,
204                                            p_dec->p_aout_input,
205                                            ADEC_FRAME_NB );
206         if( !p_aout_buffer )
207         {
208             msg_Err( p_dec->p_fifo, "cannot get aout buffer" );
209             p_dec->p_fifo->b_error = 1;
210             return;
211         }
212         p_aout_buffer->start_date = aout_DateGet( &p_dec->end_date );
213         p_aout_buffer->end_date = aout_DateIncrement( &p_dec->end_date,
214                                                       ADEC_FRAME_NB );
215
216         if( adec_DecodeFrame (p_dec, (float*)p_aout_buffer->p_buffer ) )
217         {
218             /* Ouch, failed decoding... We'll have to resync */
219             aout_DecDeleteBuffer( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer );
220         }
221         else
222         {
223             aout_DecPlay( p_dec->p_aout, p_dec->p_aout_input, p_aout_buffer );
224         }
225     }
226 }
227
228 /*****************************************************************************
229  * EndThread : audio decoder thread destruction
230  *****************************************************************************
231  * This function is called when the thread ends after a sucessful
232  * initialization.
233  *****************************************************************************/
234 static void EndThread ( adec_thread_t *p_dec )
235 {
236     /* If the audio output fifo was created, we destroy it */
237     if( p_dec->p_aout_input )
238     {
239         aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
240         
241     }
242
243     /* Destroy descriptor */
244     free( p_dec );
245 }
246