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