]> git.sesse.net Git - vlc/blob - plugins/mpeg_adec/mpeg_adec.c
libmad plug-in, courtesy of Jean-Paul Saman <jpsaman@wxs.nl>.
[vlc] / plugins / mpeg_adec / mpeg_adec.c
1 /*****************************************************************************
2  * mpeg_adec.c: MPEG audio decoder thread
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: mpeg_adec.c,v 1.5 2001/12/04 13:47:46 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  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 #define MODULE_NAME mpeg_adec
27 #include "modules_inner.h"
28
29 /*****************************************************************************
30  * Preamble
31  *****************************************************************************/
32 #include "defs.h"
33
34 #include <stdlib.h>                                      /* malloc(), free() */
35 #include <string.h>
36
37 #include "config.h"
38 #include "common.h"                                     /* boolean_t, byte_t */
39 #include "intf_msg.h"
40 #include "threads.h"
41 #include "mtime.h"
42 #include "tests.h"
43
44 #include "audio_output.h"               /* aout_fifo_t (for audio_decoder.h) */
45
46 #include "modules.h"
47 #include "modules_export.h"
48
49 #include "stream_control.h"
50 #include "input_ext-dec.h"
51
52 #include "mpeg_adec_generic.h"
53 #include "mpeg_adec.h"
54
55 #define ADEC_FRAME_SIZE (2*1152)
56
57 /*****************************************************************************
58  * Local Prototypes
59  *****************************************************************************/
60 static int          adec_Probe( probedata_t * );
61 static int          adec_RunThread   ( decoder_config_t * );
62 static void         adec_EndThread ( adec_thread_t * );
63 static void         adec_ErrorThread ( adec_thread_t * );
64 static void         adec_Decode( adec_thread_t * );
65
66
67 /*****************************************************************************
68  * Capabilities
69  *****************************************************************************/
70 void _M( adec_getfunctions )( function_list_t * p_function_list )
71 {
72     p_function_list->pf_probe = adec_Probe;
73     p_function_list->functions.dec.pf_run = adec_RunThread;
74 }
75
76 /*****************************************************************************
77  * Build configuration tree.
78  *****************************************************************************/
79 MODULE_CONFIG_START
80 ADD_WINDOW( "Configuration for mpeg audio decoder module" )
81     ADD_COMMENT( "Nothing to configure" )
82 MODULE_CONFIG_STOP
83
84 MODULE_INIT_START
85     p_module->i_capabilities = MODULE_CAPABILITY_DEC;
86     p_module->psz_longname = "Mpeg I layer 1/2 audio decoder";
87 MODULE_INIT_STOP
88
89 MODULE_ACTIVATE_START
90     _M( adec_getfunctions )( &p_module->p_functions->dec );
91 MODULE_ACTIVATE_STOP
92
93 MODULE_DEACTIVATE_START
94 MODULE_DEACTIVATE_STOP
95
96 /*****************************************************************************
97  * adec_Probe: probe the decoder and return score
98  *****************************************************************************/
99 static int adec_Probe( probedata_t *p_data )
100 {
101     if( p_data->i_type == MPEG1_AUDIO_ES || p_data->i_type == MPEG2_AUDIO_ES )
102     {
103         if( !TestCPU( CPU_CAPABILITY_FPU ) )
104         {
105             /* This can work but we'd really prefer libmad to take over. */
106             return( 1 );
107         }
108         if( TestMethod( ADEC_MPEG_VAR, "builtin" ) )
109         {
110             return( 999 );
111         }
112         return( 100 );
113     }
114     return( 0 );
115 }
116
117 /*****************************************************************************
118  * adec_RunThread: initialize, go inside main loop, detroy
119  *****************************************************************************/
120 static int adec_RunThread ( decoder_config_t * p_config )
121 {
122     adec_thread_t   * p_adec;
123     
124     intf_DbgMsg("mpeg_adec debug: thread launched, initializing.");
125     
126     /* Allocate the memory needed to store the thread's structure */
127     if ( (p_adec = (adec_thread_t *)malloc (sizeof(adec_thread_t))) == NULL ) 
128     {
129         intf_ErrMsg ( "adec error: not enough memory for"
130                       " adec_CreateThread() to create the new thread" );
131         return 0;
132     }
133     
134     /*
135      * Initialize the thread properties
136      */
137     p_adec->p_config = p_config;
138     p_adec->p_fifo = p_config->p_decoder_fifo;
139
140     /* 
141      * Initilize the banks
142      */
143     p_adec->bank_0.actual = p_adec->bank_0.v1;
144     p_adec->bank_0.pos = 0;
145     p_adec->bank_1.actual = p_adec->bank_1.v1;
146     p_adec->bank_1.pos = 0;
147     
148     /*
149      * Initialize bit stream 
150      */
151     p_adec->p_config->pf_init_bit_stream( &p_adec->bit_stream,
152         p_adec->p_config->p_decoder_fifo, NULL, NULL );
153
154     /* Create the audio output fifo */
155     p_adec->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, 2, 0, 0,
156                                            ADEC_FRAME_SIZE, NULL );
157     if ( p_adec->p_aout_fifo == NULL )
158     {
159         intf_ErrMsg("mpeg_adec error: cannot create audio output fifo");
160         return -1;
161     }
162
163     intf_DbgMsg("mpeg_adec debug: thread initialized, decoding begins.");
164
165     p_adec->i_sync = 0;
166
167     /* Audio decoder thread's main loop */
168     while( (!p_adec->p_fifo->b_die) && (!p_adec->p_fifo->b_error) )
169     {
170         adec_Decode( p_adec );
171     }
172     
173     /* If b_error is set, the audio decoder thread enters the error loop */
174     if( p_adec->p_fifo->b_error ) 
175     {
176         adec_ErrorThread( p_adec );
177     }
178
179     /* End of the audio decoder thread */
180     adec_EndThread( p_adec );
181
182     return( 0 );
183 }
184
185 /*
186  * Following finctions are local to this module
187  */
188
189 /*****************************************************************************
190  * adec_Decode: decodes a mpeg frame
191  *****************************************************************************/
192 static void adec_Decode( adec_thread_t * p_adec )
193 {
194     s16 * buffer;
195     adec_sync_info_t sync_info;
196
197     if( ! adec_SyncFrame (p_adec, &sync_info) )
198     {
199         p_adec->i_sync = 1;
200
201         p_adec->p_aout_fifo->l_rate = sync_info.sample_rate;
202
203         buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
204                     + (p_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE);
205
206         if( DECODER_FIFO_START( *p_adec->p_fifo)->i_pts )
207         {
208             p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
209                 DECODER_FIFO_START( *p_adec->p_fifo )->i_pts;
210             DECODER_FIFO_START(*p_adec->p_fifo)->i_pts = 0;
211         }
212         else
213         {
214             p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
215                 LAST_MDATE;
216         }
217
218         if( adec_DecodeFrame (p_adec, buffer) )
219         {
220             /* Ouch, failed decoding... We'll have to resync */
221             p_adec->i_sync = 0;
222         }
223         else
224         {
225             vlc_mutex_lock (&p_adec->p_aout_fifo->data_lock);
226
227             p_adec->p_aout_fifo->l_end_frame =
228                 (p_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
229             vlc_cond_signal (&p_adec->p_aout_fifo->data_wait);
230             vlc_mutex_unlock (&p_adec->p_aout_fifo->data_lock);
231         }
232     }
233 }
234
235 /*****************************************************************************
236  * adec_ErrorThread : audio decoder's RunThread() error loop
237  *****************************************************************************
238  * This function is called when an error occured during thread main's loop. The
239  * thread can still receive feed, but must be ready to terminate as soon as
240  * possible.
241  *****************************************************************************/
242 static void adec_ErrorThread ( adec_thread_t *p_adec )
243 {
244     /* We take the lock, because we are going to read/write the start/end
245      * indexes of the decoder fifo */
246     vlc_mutex_lock ( &p_adec->p_fifo->data_lock );
247
248     /* Wait until a `die' order is sent */
249     while ( !p_adec->p_fifo->b_die ) 
250     {
251         /* Trash all received PES packets */
252         while ( !DECODER_FIFO_ISEMPTY(*p_adec->p_fifo) ) 
253         {
254             p_adec->p_fifo->pf_delete_pes ( p_adec->p_fifo->p_packets_mgt,
255                                    DECODER_FIFO_START(*p_adec->p_fifo) );
256             DECODER_FIFO_INCSTART ( *p_adec->p_fifo );
257         }
258
259         /* Waiting for the input thread to put new PES packets in the fifo */
260         vlc_cond_wait ( &p_adec->p_fifo->data_wait, &p_adec->p_fifo->data_lock );
261     }
262
263     /* We can release the lock before leaving */
264     vlc_mutex_unlock ( &p_adec->p_fifo->data_lock );
265 }
266
267
268 /*****************************************************************************
269  * adec_EndThread : audio decoder thread destruction
270  *****************************************************************************
271  * This function is called when the thread ends after a sucessful
272  * initialization.
273  *****************************************************************************/
274 static void adec_EndThread ( adec_thread_t *p_adec )
275 {
276     intf_DbgMsg ( "adec debug: destroying audio decoder thread %p", p_adec );
277
278     /* If the audio output fifo was created, we destroy it */
279     if ( p_adec->p_aout_fifo != NULL ) 
280     {
281         aout_DestroyFifo ( p_adec->p_aout_fifo );
282
283         /* Make sure the output thread leaves the NextFrame() function */
284         vlc_mutex_lock (&(p_adec->p_aout_fifo->data_lock));
285         vlc_cond_signal (&(p_adec->p_aout_fifo->data_wait));
286         vlc_mutex_unlock (&(p_adec->p_aout_fifo->data_lock));
287     }
288     /* Destroy descriptor */
289     free( p_adec );
290
291     intf_DbgMsg ("adec debug: audio decoder thread %p destroyed", p_adec);
292 }
293