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