]> git.sesse.net Git - vlc/blob - plugins/mad/mad_adec.c
* ./plugins/mga/mga.c: removed the mgammx module and put the code in
[vlc] / plugins / mad / mad_adec.c
1 /***************************************************************************
2               mad_adec.c  -  description
3                 -------------------
4     Plugin Module definition for using libmad audio decoder in vlc. The
5     libmad codec uses integer arithmic only. This makes it suitable for using
6     it on architectures without a hardware FPU unit, such as the StrongArm
7     CPU.
8
9     begin                : Mon Nov 5 2001
10     copyright            : (C) 2001 by Jean-Paul Saman
11     email                : jpsaman@wxs.nl
12  ***************************************************************************/
13
14 /***************************************************************************
15  *                                                                         *
16  *   This program is free software; you can redistribute it and/or modify  *
17  *   it under the terms of the GNU General Public License as published by  *
18  *   the Free Software Foundation; either version 2 of the License, or     *
19  *   (at your option) any later version.                                   *
20  *                                                                         *
21  ***************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include <stdlib.h>                                      /* malloc(), free() */
27 #include <string.h>                                              /* strdup() */
28
29 #include <videolan/vlc.h>
30
31 #include "audio_output.h"
32
33 #include "stream_control.h"
34 #include "input_ext-dec.h"
35
36 #include "debug.h"
37
38 /*****************************************************************************
39  * Libmad include files                                                      *
40  *****************************************************************************/
41 #include <mad.h>
42 #include "mad_adec.h"
43 #include "mad_libmad.h"
44
45 /*****************************************************************************
46  * Local prototypes
47  *****************************************************************************/
48 static int  decoder_Probe  ( probedata_t * );
49 static int  decoder_Run    ( decoder_config_t * );
50 static int  InitThread     ( mad_adec_thread_t * p_mad_adec );
51 static void EndThread      ( mad_adec_thread_t * p_mad_adec );
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( "Libmad MPEG 1/2/3 audio decoder library" )
70     ADD_CAPABILITY( DECODER, 950 )
71     ADD_SHORTCUT( "mad" )
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  * Tries to launch a decoder and return score so that the interface is able
85  * to chose.
86  *****************************************************************************/
87 static int decoder_Probe( probedata_t *p_data )
88 {
89     if( p_data->i_type == MPEG1_AUDIO_ES || p_data->i_type == MPEG2_AUDIO_ES )
90     {
91         return( 50 );
92     }
93     else
94     {
95         return( 0 );
96     }
97 }
98
99 /*****************************************************************************
100  * decoder_Run: this function is called just after the thread is created
101  *****************************************************************************/
102 static int decoder_Run ( decoder_config_t * p_config )
103 {
104     mad_adec_thread_t *   p_mad_adec;
105
106     intf_ErrMsg( "mad_adec debug: mad_adec thread launched, initializing" );
107
108     /* Allocate the memory needed to store the thread's structure */
109     p_mad_adec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t));
110
111     if (p_mad_adec == NULL)
112     {
113         intf_ErrMsg ( "mad_adec error: not enough memory "
114                       "for decoder_Run() to allocate p_mad_adec" );
115         DecoderError( p_config->p_decoder_fifo );
116         return( -1 );
117     }
118
119     /*
120      * Initialize the thread properties
121      */
122     p_mad_adec->p_config = p_config;
123     p_mad_adec->p_fifo = p_mad_adec->p_config->p_decoder_fifo;
124     if( InitThread( p_mad_adec ) )
125     {
126         intf_ErrMsg( "mad_adec error: could not initialize thread" );
127         DecoderError( p_config->p_decoder_fifo );
128         free( p_mad_adec );
129         return( -1 );
130     }
131
132     /* mad decoder thread's main loop */
133     while ((!p_mad_adec->p_fifo->b_die) && (!p_mad_adec->p_fifo->b_error))
134     {
135         intf_ErrMsg( "mad_adec: starting libmad decoder" );
136         if (mad_decoder_run(p_mad_adec->libmad_decoder, MAD_DECODER_MODE_SYNC)==-1)
137         {
138           intf_ErrMsg( "mad_adec error: libmad decoder returns abnormally");
139           DecoderError( p_mad_adec->p_fifo );
140           EndThread(p_mad_adec);
141           return( -1 );
142         }
143     }
144
145     /* If b_error is set, the mad decoder thread enters the error loop */
146     if (p_mad_adec->p_fifo->b_error)
147     {
148         DecoderError( p_mad_adec->p_fifo );
149     }
150
151     /* End of the ac3 decoder thread */
152     EndThread (p_mad_adec);
153
154     return( 0 );
155 }
156
157 /*****************************************************************************
158  * InitThread: initialize data before entering main loop
159  *****************************************************************************/
160 static int InitThread( mad_adec_thread_t * p_mad_adec )
161 {
162     /*
163      * Properties of audio for libmad
164      */
165         
166     /* Initialize the libmad decoder structures */
167     p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
168
169     /*
170      * Initialize bit stream
171      */
172     p_mad_adec->p_config->pf_init_bit_stream( &p_mad_adec->bit_stream,
173                                               p_mad_adec->p_config->p_decoder_fifo,
174                                               NULL,    /* pf_bitstream_callback */
175                                               NULL );  /* void **/
176
177     RealignBits( &p_mad_adec->bit_stream );
178
179     mad_decoder_init( p_mad_adec->libmad_decoder,
180                       p_mad_adec,       /* vlc's thread structure and p_fifo playbuffer */
181                       libmad_input,     /* input_func */
182                       0,                /* header_func */
183                       0,                /* filter */
184                       libmad_output,    /* output_func */
185                       0,                /* error */
186                       0);               /* message */
187
188     mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
189         
190     /*
191      * Initialize the output properties
192      */
193
194     /* Creating the audio output fifo */
195     p_mad_adec->p_aout_fifo = aout_CreateFifo(  AOUT_ADEC_STEREO_FIFO, /* fifo type */
196                                                 2,                     /* nr. of channels */
197                                                 48000,                 /* frame rate in Hz ?*/
198                                                 0,                     /* units */
199                                                 ADEC_FRAME_SIZE/2,     /* frame size */
200                                                 NULL  );               /* buffer */
201
202     if ( p_mad_adec->p_aout_fifo == NULL )
203     {
204         return( -1 );
205     }
206
207     intf_ErrMsg("mad_adec debug: mad decoder thread %p initialized", p_mad_adec);
208
209     return( 0 );
210 }
211
212 /*****************************************************************************
213  * EndThread : libmad decoder thread destruction
214  *****************************************************************************/
215 static void EndThread (mad_adec_thread_t * p_mad_adec)
216 {
217     intf_ErrMsg ("mad_adec debug: destroying mad decoder thread %p", p_mad_adec);
218
219     /* If the audio output fifo was created, we destroy it */
220     if (p_mad_adec->p_aout_fifo != NULL)
221     {
222         aout_DestroyFifo (p_mad_adec->p_aout_fifo);
223
224         /* Make sure the output thread leaves the NextFrame() function */
225         vlc_mutex_lock (&(p_mad_adec->p_aout_fifo->data_lock));
226         vlc_cond_signal (&(p_mad_adec->p_aout_fifo->data_wait));
227         vlc_mutex_unlock (&(p_mad_adec->p_aout_fifo->data_lock));
228     }
229
230     /* mad_decoder_finish releases the memory allocated inside the struct */
231     mad_decoder_finish( p_mad_adec->libmad_decoder );
232
233     /* Unlock the modules, p_mad_adec->p_config is released by the decoder subsystem  */
234     free( p_mad_adec->libmad_decoder );
235     free( p_mad_adec );
236
237     intf_ErrMsg ("mad_adec debug: mad decoder thread %p destroyed", p_mad_adec);
238 }
239