]> git.sesse.net Git - vlc/blob - plugins/mad_adec/mad_adec.c
Another fix.
[vlc] / plugins / mad_adec / 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 #define MODULE_NAME mad
24 #include "modules_inner.h"
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include "defs.h"
30
31 #include <stdlib.h>                                      /* malloc(), free() */
32 #include <string.h>                                              /* strdup() */
33
34 #include "config.h"
35 #include "common.h"                                     /* boolean_t, byte_t */
36 #include "intf_msg.h"
37 #include "threads.h"
38 #include "mtime.h"
39 #include "tests.h"
40
41 #include "audio_output.h"
42
43 #include "modules.h"
44 #include "modules_export.h"
45
46 #include "stream_control.h"
47 #include "input_ext-dec.h"
48
49 #include "debug.h"
50
51 /*****************************************************************************
52  * Libmad include files                                                      *
53  *****************************************************************************/
54 #include <mad.h>
55 #include "mad_adec.h"
56 #include "mad_libmad.h"
57
58 /*****************************************************************************
59  * Local prototypes
60  *****************************************************************************/
61 static int  decoder_Probe  ( probedata_t * );
62 static int  decoder_Run    ( decoder_config_t * );
63 static int  InitThread     ( mad_adec_thread_t * p_mad_adec );
64 static void mad_adec_EndThread      ( mad_adec_thread_t * p_mad_adec );
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 mad_adec module" )
80     ADD_COMMENT( "No device to configure." )
81 MODULE_CONFIG_STOP
82
83 MODULE_INIT_START
84     p_module->i_capabilities = MODULE_CAPABILITY_DEC;
85     p_module->psz_longname = "Libmad MPEG 1/2/3 audio decoder library";
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  * Tries to launch a decoder and return score so that the interface is able
99  * to chose.
100  *****************************************************************************/
101 static int decoder_Probe( probedata_t *p_data )
102 {
103     if( p_data->i_type == MPEG1_AUDIO_ES || p_data->i_type == MPEG2_AUDIO_ES )
104     {
105         if( TestMethod( ADEC_MPEG_VAR, "mad" ) )
106         {
107             return( 999 );
108         }
109         return( 50 );
110     }
111     else
112     {
113         return( 0 );
114     }
115 }
116
117 /*****************************************************************************
118  * decoder_Run: this function is called just after the thread is created
119  *****************************************************************************/
120 static int decoder_Run ( decoder_config_t * p_config )
121 {
122     mad_adec_thread_t *   p_mad_adec;
123
124     intf_ErrMsg( "mad_adec debug: mad_adec thread launched, initializing" );
125
126     /* Allocate the memory needed to store the thread's structure */
127     p_mad_adec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t));
128
129     if (p_mad_adec == NULL)
130     {
131         intf_ErrMsg ( "mad_adec error: not enough memory "
132                       "for decoder_Run() to allocate p_mad_adec" );
133         DecoderError( p_config->p_decoder_fifo );
134         return( -1 );
135     }
136
137     /*
138      * Initialize the thread properties
139      */
140     p_mad_adec->p_config = p_config;
141     p_mad_adec->p_fifo = p_mad_adec->p_config->p_decoder_fifo;
142     if( InitThread( p_mad_adec ) )
143     {
144         intf_ErrMsg( "mad_adec error: could not initialize thread" );
145         DecoderError( p_config->p_decoder_fifo );
146         free( p_mad_adec );
147         return( -1 );
148     }
149
150     /* mad decoder thread's main loop */
151     while ((!p_mad_adec->p_fifo->b_die) && (!p_mad_adec->p_fifo->b_error))
152     {
153         intf_ErrMsg( "mad_adec: starting libmad decoder" );
154         if (mad_decoder_run(p_mad_adec->libmad_decoder, MAD_DECODER_MODE_SYNC)==-1)
155         {
156           intf_ErrMsg( "mad_adec error: libmad decoder returns abnormally");
157           DecoderError( p_mad_adec->p_fifo );
158           mad_adec_EndThread(p_mad_adec);
159           return( -1 );
160         }
161     }
162
163     /* If b_error is set, the mad decoder thread enters the error loop */
164     if (p_mad_adec->p_fifo->b_error)
165     {
166         DecoderError( p_mad_adec->p_fifo );
167     }
168
169     /* End of the ac3 decoder thread */
170     mad_adec_EndThread (p_mad_adec);
171
172     return( 0 );
173 }
174
175 /*****************************************************************************
176  * InitThread: initialize data before entering main loop
177  *****************************************************************************/
178 static int InitThread( mad_adec_thread_t * p_mad_adec )
179 {
180     /*
181      * Properties of audio for libmad
182      */
183         
184     /* Initialize the libmad decoder structures */
185     p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
186
187     /*
188      * Initialize bit stream
189      */
190     p_mad_adec->p_config->pf_init_bit_stream( &p_mad_adec->bit_stream,
191                                               p_mad_adec->p_config->p_decoder_fifo,
192                                               NULL,    /* pf_bitstream_callback */
193                                               NULL );  /* void **/
194
195     RealignBits( &p_mad_adec->bit_stream );
196
197     mad_decoder_init( p_mad_adec->libmad_decoder,
198                       p_mad_adec,       /* vlc's thread structure and p_fifo playbuffer */
199                       libmad_input,     /* input_func */
200                       libmad_header,    /* header_func */
201                       0,                /* filter */
202                       libmad_output,    /* output_func */
203                       0,        /* error */
204                       0);               /* message */
205
206     mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
207         
208     /*
209      * Initialize the output properties
210      */
211
212     /* Creating the audio output fifo */
213     p_mad_adec->p_aout_fifo = aout_CreateFifo(  AOUT_ADEC_STEREO_FIFO, /* fifo type */
214                                                 2,                     /* nr. of channels */
215                                                 48000,                 /* frame rate in Hz ?*/
216                                                 0,                     /* units */
217                                                 ADEC_FRAME_SIZE/2,     /* frame size */
218                                                 NULL  );               /* buffer */
219
220     if ( p_mad_adec->p_aout_fifo == NULL )
221     {
222         return( -1 );
223     }
224
225     intf_ErrMsg("mad_adec debug: mad decoder thread %p initialized", p_mad_adec);
226
227     return( 0 );
228 }
229
230
231 /*****************************************************************************
232  * mad_adec_EndThread : libmad decoder thread destruction
233  *****************************************************************************/
234 static void mad_adec_EndThread (mad_adec_thread_t * p_mad_adec)
235 {
236     intf_ErrMsg ("mad_adec debug: destroying mad decoder thread %p", p_mad_adec);
237
238     /* If the audio output fifo was created, we destroy it */
239     if (p_mad_adec->p_aout_fifo != NULL)
240     {
241         aout_DestroyFifo (p_mad_adec->p_aout_fifo);
242
243         /* Make sure the output thread leaves the NextFrame() function */
244         vlc_mutex_lock (&(p_mad_adec->p_aout_fifo->data_lock));
245         vlc_cond_signal (&(p_mad_adec->p_aout_fifo->data_wait));
246         vlc_mutex_unlock (&(p_mad_adec->p_aout_fifo->data_lock));
247     }
248
249     /* mad_decoder_finish releases the memory allocated inside the struct */
250     mad_decoder_finish( p_mad_adec->libmad_decoder );
251
252     /* Unlock the modules */
253     free( p_mad_adec->libmad_decoder );
254 //    free( p_mad_adec->p_config ); /* for now a reminder until integration with cvs */
255     free( p_mad_adec );
256
257     intf_ErrMsg ("mad_adec debug: mad decoder thread %p destroyed", p_mad_adec);
258 }
259