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