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