]> git.sesse.net Git - vlc/blob - plugins/mpeg_adec/mpeg_adec.c
* Added a missing call to DecoderError() in mpeg_adec.c.
[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.2.3 2001/12/31 03:59:59 sam 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   decoder_Probe ( probedata_t * );
61 static int   decoder_Run   ( decoder_config_t * );
62 static void  EndThread     ( adec_thread_t * );
63 static void  DecodeThread  ( adec_thread_t * );
64
65
66 /*****************************************************************************
67  * Capabilities
68  *****************************************************************************/
69 void _M( adec_getfunctions )( function_list_t * p_function_list )
70 {
71     p_function_list->pf_probe = decoder_Probe;
72     p_function_list->functions.dec.pf_run = decoder_Run;
73 }
74
75 /*****************************************************************************
76  * Build configuration tree.
77  *****************************************************************************/
78 MODULE_CONFIG_START
79 ADD_WINDOW( "Configuration for mpeg audio decoder module" )
80     ADD_COMMENT( "Nothing to configure" )
81 MODULE_CONFIG_STOP
82
83 MODULE_INIT_START
84     p_module->i_capabilities = MODULE_CAPABILITY_DEC;
85     p_module->psz_longname = "Mpeg I layer 1/2 audio decoder";
86 MODULE_INIT_STOP
87
88 MODULE_ACTIVATE_START
89     _M( adec_getfunctions )( &p_module->p_functions->dec );
90 MODULE_ACTIVATE_STOP
91
92 MODULE_DEACTIVATE_START
93 MODULE_DEACTIVATE_STOP
94
95 /*****************************************************************************
96  * decoder_Probe: probe the decoder and return score
97  *****************************************************************************/
98 static int decoder_Probe( probedata_t *p_data )
99 {
100     if( p_data->i_type == MPEG1_AUDIO_ES || p_data->i_type == MPEG2_AUDIO_ES )
101     {
102         if( !TestCPU( CPU_CAPABILITY_FPU ) )
103         {
104             /* This can work but we'd really prefer libmad to take over. */
105             return( 1 );
106         }
107         if( TestMethod( ADEC_MPEG_VAR, "builtin" ) )
108         {
109             return( 999 );
110         }
111         return( 100 );
112     }
113     return( 0 );
114 }
115
116 /*****************************************************************************
117  * decoder_Run: initialize, go inside main loop, detroy
118  *****************************************************************************/
119 static int decoder_Run ( decoder_config_t * p_config )
120 {
121     adec_thread_t   * p_adec;
122     
123     intf_DbgMsg("mpeg_adec debug: thread launched, initializing.");
124     
125     /* Allocate the memory needed to store the thread's structure */
126     if ( (p_adec = (adec_thread_t *)malloc (sizeof(adec_thread_t))) == NULL ) 
127     {
128         intf_ErrMsg ( "adec error: not enough memory for"
129                       " adec_CreateThread() to create the new thread" );
130         DecoderError( p_config->p_decoder_fifo );
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         DecoderError( p_config->p_decoder_fifo );
161         return -1;
162     }
163
164     intf_DbgMsg("mpeg_adec debug: thread initialized, decoding begins.");
165
166     p_adec->i_sync = 0;
167
168     /* Audio decoder thread's main loop */
169     while( (!p_adec->p_fifo->b_die) && (!p_adec->p_fifo->b_error) )
170     {
171         DecodeThread( p_adec );
172     }
173     
174     /* If b_error is set, the audio decoder thread enters the error loop */
175     if( p_adec->p_fifo->b_error ) 
176     {
177         DecoderError( p_adec->p_fifo );
178     }
179
180     /* End of the audio decoder thread */
181     EndThread( p_adec );
182
183     return( 0 );
184 }
185
186 /*
187  * Following finctions are local to this module
188  */
189
190 /*****************************************************************************
191  * DecodeThread: decodes a mpeg frame
192  *****************************************************************************/
193 static void DecodeThread( adec_thread_t * p_adec )
194 {
195     s16 * buffer;
196     adec_sync_info_t sync_info;
197
198     if( ! adec_SyncFrame (p_adec, &sync_info) )
199     {
200         p_adec->i_sync = 1;
201
202         p_adec->p_aout_fifo->l_rate = sync_info.sample_rate;
203
204         buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
205                     + (p_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE);
206
207         if( p_adec->p_fifo->p_first->i_pts )
208         {
209             p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
210                 p_adec->p_fifo->p_first->i_pts;
211             p_adec->p_fifo->p_first->i_pts = 0;
212         }
213         else
214         {
215             p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
216                 LAST_MDATE;
217         }
218
219         if( adec_DecodeFrame (p_adec, buffer) )
220         {
221             /* Ouch, failed decoding... We'll have to resync */
222             p_adec->i_sync = 0;
223         }
224         else
225         {
226             vlc_mutex_lock (&p_adec->p_aout_fifo->data_lock);
227
228             p_adec->p_aout_fifo->l_end_frame =
229                 (p_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
230             vlc_cond_signal (&p_adec->p_aout_fifo->data_wait);
231             vlc_mutex_unlock (&p_adec->p_aout_fifo->data_lock);
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_adec )
243 {
244     intf_DbgMsg ( "adec debug: destroying audio decoder thread %p", p_adec );
245
246     /* If the audio output fifo was created, we destroy it */
247     if ( p_adec->p_aout_fifo != NULL ) 
248     {
249         aout_DestroyFifo ( p_adec->p_aout_fifo );
250
251         /* Make sure the output thread leaves the NextFrame() function */
252         vlc_mutex_lock (&(p_adec->p_aout_fifo->data_lock));
253         vlc_cond_signal (&(p_adec->p_aout_fifo->data_wait));
254         vlc_mutex_unlock (&(p_adec->p_aout_fifo->data_lock));
255     }
256     /* Destroy descriptor */
257     free( p_adec );
258
259     intf_DbgMsg ("adec debug: audio decoder thread %p destroyed", p_adec);
260 }
261