Changes made to mad plugin:
[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 /*****************************************************************************
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, 50 )
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     if (p_mad_adec->libmad_decoder == NULL) {
170         intf_ErrMsg ( "mad_adec error: not enough memory "
171                       "for decoder_InitThread() to allocate p_mad_adec->libmad_decder" );
172         return -1;
173     }
174     p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
175
176     /*
177      * Initialize bit stream
178      */
179     p_mad_adec->p_config->pf_init_bit_stream( &p_mad_adec->bit_stream,
180                                               p_mad_adec->p_config->p_decoder_fifo,
181                                               NULL,    /* pf_bitstream_callback */
182                                               NULL );  /* void **/
183
184     mad_decoder_init( p_mad_adec->libmad_decoder,
185                       p_mad_adec,       /* vlc's thread structure and p_fifo playbuffer */
186                       libmad_input,     /* input_func */
187                       0,                /* header_func */
188                       0,                /* filter */
189                       libmad_output,    /* output_func */
190                       0,        /* error */
191                       0);               /* message */
192
193     mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
194     mad_timer_reset(&p_mad_adec->libmad_timer);
195
196     /* output fifo will be created when needed */
197     p_mad_adec->p_aout_fifo=NULL;
198
199     intf_ErrMsg("mad_adec debug: mad decoder thread %p initialized", p_mad_adec);
200
201     return( 0 );
202 }
203
204 /*****************************************************************************
205  * EndThread : libmad decoder thread destruction
206  *****************************************************************************/
207 static void EndThread (mad_adec_thread_t * p_mad_adec)
208 {
209     intf_ErrMsg ("mad_adec debug: destroying mad decoder thread %p", p_mad_adec);
210
211     /* If the audio output fifo was created, we destroy it */
212     if (p_mad_adec->p_aout_fifo != NULL)
213     {
214         aout_DestroyFifo (p_mad_adec->p_aout_fifo);
215
216         /* Make sure the output thread leaves the NextFrame() function */
217         vlc_mutex_lock (&(p_mad_adec->p_aout_fifo->data_lock));
218         vlc_cond_signal (&(p_mad_adec->p_aout_fifo->data_wait));
219         vlc_mutex_unlock (&(p_mad_adec->p_aout_fifo->data_lock));
220     }
221
222     /* mad_decoder_finish releases the memory allocated inside the struct */
223     mad_decoder_finish( p_mad_adec->libmad_decoder );
224
225     /* Unlock the modules, p_mad_adec->p_config is released by the decoder subsystem  */
226     free( p_mad_adec->libmad_decoder );
227     free( p_mad_adec );
228
229     intf_ErrMsg ("mad_adec debug: mad decoder thread %p destroyed", p_mad_adec);
230 }
231