- better communication between audio decoder and output: aout plugins
[vlc.git] / 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.11 2002/01/09 00:33:37 asmax 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 <videolan/vlc.h>
34
35 #include "audio_output.h"               /* aout_fifo_t (for audio_decoder.h) */
36
37 #include "stream_control.h"
38 #include "input_ext-dec.h"
39
40 #include "mpeg_adec_generic.h"
41 #include "mpeg_adec.h"
42
43 #define ADEC_FRAME_SIZE (2*1152)
44
45 /*****************************************************************************
46  * Local Prototypes
47  *****************************************************************************/
48 static int   decoder_Probe ( probedata_t * );
49 static int   decoder_Run   ( decoder_config_t * );
50 static void  EndThread     ( adec_thread_t * );
51 static void  DecodeThread  ( adec_thread_t * );
52
53 /*****************************************************************************
54  * Capabilities
55  *****************************************************************************/
56 void _M( adec_getfunctions )( function_list_t * p_function_list )
57 {
58     p_function_list->pf_probe = decoder_Probe;
59     p_function_list->functions.dec.pf_run = decoder_Run;
60 }
61
62 /*****************************************************************************
63  * Build configuration tree.
64  *****************************************************************************/
65 MODULE_CONFIG_START
66 MODULE_CONFIG_STOP
67
68 MODULE_INIT_START
69     SET_DESCRIPTION( "Mpeg I layer 1/2 audio decoder" )
70     ADD_CAPABILITY( DECODER, 100 )
71     ADD_REQUIREMENT( FPU )
72     ADD_SHORTCUT( "builtin" )
73 MODULE_INIT_STOP
74
75 MODULE_ACTIVATE_START
76     _M( adec_getfunctions )( &p_module->p_functions->dec );
77 MODULE_ACTIVATE_STOP
78
79 MODULE_DEACTIVATE_START
80 MODULE_DEACTIVATE_STOP
81
82 /*****************************************************************************
83  * decoder_Probe: probe the decoder and return score
84  *****************************************************************************/
85 static int decoder_Probe( probedata_t *p_data )
86 {
87     return( ( p_data->i_type == MPEG1_AUDIO_ES
88                || p_data->i_type == MPEG2_AUDIO_ES ) ? 100 : 0 );
89 }
90
91 /*****************************************************************************
92  * decoder_Run: initialize, go inside main loop, detroy
93  *****************************************************************************/
94 static int decoder_Run ( decoder_config_t * p_config )
95 {
96     adec_thread_t   * p_adec;
97     
98     intf_DbgMsg("mpeg_adec debug: thread launched, initializing.");
99     
100     /* Allocate the memory needed to store the thread's structure */
101     if ( (p_adec = (adec_thread_t *)malloc (sizeof(adec_thread_t))) == NULL ) 
102     {
103         intf_ErrMsg ( "adec error: not enough memory for"
104                       " adec_CreateThread() to create the new thread" );
105         DecoderError( p_config->p_decoder_fifo );
106         return 0;
107     }
108     
109     /*
110      * Initialize the thread properties
111      */
112     p_adec->p_config = p_config;
113     p_adec->p_fifo = p_config->p_decoder_fifo;
114
115     /* 
116      * Initilize the banks
117      */
118     p_adec->bank_0.actual = p_adec->bank_0.v1;
119     p_adec->bank_0.pos = 0;
120     p_adec->bank_1.actual = p_adec->bank_1.v1;
121     p_adec->bank_1.pos = 0;
122     
123     /*
124      * Initialize bit stream 
125      */
126     p_adec->p_config->pf_init_bit_stream( &p_adec->bit_stream,
127         p_adec->p_config->p_decoder_fifo, NULL, NULL );
128
129     /* We do not create the audio output fifo now, but
130        it will be created when the first frame is received */
131     p_adec->p_aout_fifo = NULL;
132
133     intf_DbgMsg("mpeg_adec debug: thread initialized, decoding begins.");
134
135     p_adec->i_sync = 0;
136
137     /* Audio decoder thread's main loop */
138     while( (!p_adec->p_fifo->b_die) && (!p_adec->p_fifo->b_error) )
139     {
140         DecodeThread( p_adec );
141     }
142     
143     /* If b_error is set, the audio decoder thread enters the error loop */
144     if( p_adec->p_fifo->b_error ) 
145     {
146         DecoderError( p_adec->p_fifo );
147     }
148
149     /* End of the audio decoder thread */
150     EndThread( p_adec );
151
152     return( 0 );
153 }
154
155 /*
156  * Following finctions are local to this module
157  */
158
159 /*****************************************************************************
160  * DecodeThread: decodes a mpeg frame
161  *****************************************************************************/
162 static void DecodeThread( adec_thread_t * p_adec )
163 {
164     s16 * buffer;
165     adec_sync_info_t sync_info;
166
167     if( ! adec_SyncFrame (p_adec, &sync_info) )
168     {
169         
170         /* TODO: check if audio type has changed */
171         
172         /* Create the output fifo if it doesn't exist yet */
173         if( p_adec->p_aout_fifo == NULL )
174         {
175             int fifo_type;
176             int channels;
177             
178             if( sync_info.b_stereo )
179             {
180                 fifo_type = AOUT_ADEC_STEREO_FIFO;
181                 channels = 2;
182             }
183             else
184             {
185                 fifo_type = AOUT_ADEC_MONO_FIFO;
186                 channels = 1;
187             }
188             p_adec->p_aout_fifo = aout_CreateFifo( fifo_type, channels,
189                     sync_info.sample_rate, 0, ADEC_FRAME_SIZE, NULL );
190             if( p_adec->p_aout_fifo == NULL)
191             {
192                 intf_ErrMsg( "adec error: failed to create Audio Output "
193                         "Fifo." );
194                 DecoderError( p_adec->p_fifo );
195             }
196         }
197
198         p_adec->i_sync = 1;
199
200         p_adec->p_aout_fifo->l_rate = sync_info.sample_rate;
201
202         buffer = ((s16 *)p_adec->p_aout_fifo->buffer)
203                     + (p_adec->p_aout_fifo->l_end_frame * ADEC_FRAME_SIZE);
204
205         if( p_adec->p_fifo->p_first->i_pts )
206         {
207             p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
208                 p_adec->p_fifo->p_first->i_pts;
209             p_adec->p_fifo->p_first->i_pts = 0;
210         }
211         else
212         {
213             p_adec->p_aout_fifo->date[p_adec->p_aout_fifo->l_end_frame] =
214                 LAST_MDATE;
215         }
216
217         if( adec_DecodeFrame (p_adec, buffer) )
218         {
219             /* Ouch, failed decoding... We'll have to resync */
220             p_adec->i_sync = 0;
221         }
222         else
223         {
224             vlc_mutex_lock (&p_adec->p_aout_fifo->data_lock);
225
226             p_adec->p_aout_fifo->l_end_frame =
227                 (p_adec->p_aout_fifo->l_end_frame + 1) & AOUT_FIFO_SIZE;
228             vlc_cond_signal (&p_adec->p_aout_fifo->data_wait);
229             vlc_mutex_unlock (&p_adec->p_aout_fifo->data_lock);
230         }
231     }
232 }
233
234 /*****************************************************************************
235  * EndThread : audio decoder thread destruction
236  *****************************************************************************
237  * This function is called when the thread ends after a sucessful
238  * initialization.
239  *****************************************************************************/
240 static void EndThread ( adec_thread_t *p_adec )
241 {
242     intf_DbgMsg ( "adec debug: destroying audio decoder thread %p", p_adec );
243
244     /* If the audio output fifo was created, we destroy it */
245     if ( p_adec->p_aout_fifo != NULL ) 
246     {
247         aout_DestroyFifo ( p_adec->p_aout_fifo );
248
249         /* Make sure the output thread leaves the NextFrame() function */
250         vlc_mutex_lock (&(p_adec->p_aout_fifo->data_lock));
251         vlc_cond_signal (&(p_adec->p_aout_fifo->data_wait));
252         vlc_mutex_unlock (&(p_adec->p_aout_fifo->data_lock));
253     }
254     /* Destroy descriptor */
255     free( p_adec );
256
257     intf_DbgMsg ("adec debug: audio decoder thread %p destroyed", p_adec);
258 }
259