]> git.sesse.net Git - vlc/blob - plugins/mad/mad_adec.c
0cbefed3a57d607c652dc9bf4e92725d46b2cef6
[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 /*****************************************************************************
37  * Libmad include files                                                      *
38  *****************************************************************************/
39 #include <mad.h>
40 #include "mad_adec.h"
41 #include "mad_libmad.h"
42
43 /*****************************************************************************
44  * Local prototypes
45  *****************************************************************************/
46 static int  decoder_Probe  ( u8 * );
47 static int  decoder_Run    ( decoder_config_t * );
48 static int  InitThread     ( mad_adec_thread_t * p_mad_adec );
49 static void EndThread      ( mad_adec_thread_t * p_mad_adec );
50
51 /*****************************************************************************
52  * Capabilities
53  *****************************************************************************/
54 void _M( adec_getfunctions )( function_list_t * p_function_list )
55 {
56     p_function_list->functions.dec.pf_probe = decoder_Probe;
57     p_function_list->functions.dec.pf_run   = decoder_Run;
58 }
59
60 /*****************************************************************************
61  * Build configuration tree.
62  *****************************************************************************/
63 #define DOWNSCALE_TEXT N_("Mad audio downscale routine (fast,mp321)")
64 #define DOWNSCALE_LONGTEXT N_( \
65     "Specify the mad audio downscale routine you want to use.\nBy default mad plugins will " \
66     "use the fastest routine.")
67
68 MODULE_CONFIG_START
69 ADD_CATEGORY_HINT( N_("Miscellaneous"), NULL )
70 ADD_STRING  ( "downscale", "fast", NULL, DOWNSCALE_TEXT, DOWNSCALE_LONGTEXT )
71 MODULE_CONFIG_STOP
72
73 MODULE_INIT_START
74     SET_DESCRIPTION( _("libmad MPEG 1/2/3 audio decoder library") )
75     ADD_CAPABILITY( DECODER, 100 )
76     ADD_SHORTCUT( "mad" )
77 MODULE_INIT_STOP
78
79 MODULE_ACTIVATE_START
80     _M( adec_getfunctions )( &p_module->p_functions->dec );
81 MODULE_ACTIVATE_STOP
82
83 MODULE_DEACTIVATE_START
84 MODULE_DEACTIVATE_STOP
85
86 /*****************************************************************************
87  * decoder_Probe: probe the decoder and return score
88  *****************************************************************************
89  * Tries to launch a decoder and return score so that the interface is able
90  * to chose.
91  *****************************************************************************/
92 static int decoder_Probe( u8 *pi_type )
93 {
94     if( *pi_type == MPEG1_AUDIO_ES || *pi_type == MPEG2_AUDIO_ES )
95     {
96         return 0;
97     }
98
99     return -1;
100 }
101
102 /*****************************************************************************
103  * decoder_Run: this function is called just after the thread is created
104  *****************************************************************************/
105 static int decoder_Run ( decoder_config_t * p_config )
106 {
107     mad_adec_thread_t *   p_mad_adec;
108
109     intf_WarnMsg( 4, "mad_adec debug: mad_adec thread launched, initializing" );
110
111     /* Allocate the memory needed to store the thread's structure */
112     p_mad_adec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t));
113
114     if (p_mad_adec == NULL)
115     {
116         intf_ErrMsg ( "mad_adec error: not enough memory "
117                       "for decoder_Run() to allocate p_mad_adec" );
118         DecoderError( p_config->p_decoder_fifo );
119         return( -1 );
120     }
121
122     /*
123      * Initialize the thread properties
124      */
125     p_mad_adec->p_config = p_config;
126     p_mad_adec->p_fifo = p_mad_adec->p_config->p_decoder_fifo;
127     if( InitThread( p_mad_adec ) )
128     {
129         intf_ErrMsg( "mad_adec error: could not initialize thread" );
130         DecoderError( p_config->p_decoder_fifo );
131         free( p_mad_adec );
132         return( -1 );
133     }
134
135     /* mad decoder thread's main loop */
136     while ((!p_mad_adec->p_fifo->b_die) && (!p_mad_adec->p_fifo->b_error))
137     {
138         intf_ErrMsg( "mad_adec: starting libmad decoder" );
139         if (mad_decoder_run(p_mad_adec->libmad_decoder, MAD_DECODER_MODE_SYNC)==-1)
140         {
141             intf_ErrMsg( "mad_adec error: libmad decoder returns abnormally");
142             DecoderError( p_mad_adec->p_fifo );
143             EndThread(p_mad_adec);
144             return( -1 );
145         }
146     }
147
148     /* If b_error is set, the mad decoder thread enters the error loop */
149     if (p_mad_adec->p_fifo->b_error)
150     {
151         DecoderError( p_mad_adec->p_fifo );
152     }
153
154     /* End of the mad decoder thread */
155     EndThread (p_mad_adec);
156
157     return( 0 );
158 }
159
160 /*****************************************************************************
161  * InitThread: initialize data before entering main loop
162  *****************************************************************************/
163 static int InitThread( mad_adec_thread_t * p_mad_adec )
164 {
165     decoder_fifo_t * p_fifo = p_mad_adec->p_fifo;
166     char *psz_downscale = NULL;
167
168     /*
169      * Properties of audio for libmad
170      */
171                 
172                 /* Look what scaling method was requested by the user */
173     psz_downscale = config_GetPszVariable( "downscale" );
174
175     if ( strncmp(psz_downscale,"fast",4)==0 )
176     {
177         p_mad_adec->audio_scaling = FAST_SCALING;
178         intf_WarnMsg( 4, "mad_adec debug: downscale fast selected" );
179     }
180     else if ( strncmp(psz_downscale,"mpg321",7)==0 )
181     {
182         p_mad_adec->audio_scaling = MPG321_SCALING;
183         intf_WarnMsg( 4, "mad_adec debug: downscale mpg321 selected" );
184     }
185     else
186     {
187         p_mad_adec->audio_scaling = FAST_SCALING;
188         intf_WarnMsg( 4, "mad_adec debug: downscale default fast selected" );
189     }
190
191                 if (psz_downscale) free(psz_downscale);
192
193     /* Initialize the libmad decoder structures */
194     p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
195     if (p_mad_adec->libmad_decoder == NULL)
196     {
197         intf_ErrMsg ( "mad_adec error: not enough memory "
198                       "for decoder_InitThread() to allocate p_mad_adec->libmad_decder" );
199         return -1;
200     }
201     p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
202
203     mad_decoder_init( p_mad_adec->libmad_decoder,
204                       p_mad_adec,         /* vlc's thread structure and p_fifo playbuffer */
205                       libmad_input,          /* input_func */
206                       0,                /* header_func */
207                       0,                /* filter */
208                       libmad_output,         /* output_func */
209                       0,                  /* error */
210                       0);                    /* message */
211
212     mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
213 //    mad_timer_reset(&p_mad_adec->libmad_timer);
214
215     /*
216      * Initialize the output properties
217      */
218     p_mad_adec->p_aout_fifo = NULL;
219
220     /*
221      * Initialize the input properties
222      */
223     /* Get the first data packet. */
224     vlc_mutex_lock( &p_fifo->data_lock );
225     while ( p_fifo->p_first == NULL )
226     {
227         if ( p_fifo->b_die )
228         {
229             vlc_mutex_unlock( &p_fifo->data_lock );
230             return( -1 );
231         }
232         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
233     }
234     vlc_mutex_unlock( &p_fifo->data_lock );
235     p_mad_adec->p_data = p_fifo->p_first->p_first;
236
237     intf_WarnMsg( 4, "mad_adec debug: mad decoder thread %p initialized", p_mad_adec);
238
239     return( 0 );
240 }
241
242 /*****************************************************************************
243  * EndThread : libmad decoder thread destruction
244  *****************************************************************************/
245 static void EndThread (mad_adec_thread_t * p_mad_adec)
246 {
247     intf_WarnMsg( 4, "mad_adec debug: destroying mad decoder thread %p", p_mad_adec);
248
249     /* If the audio output fifo was created, we destroy it */
250     if (p_mad_adec->p_aout_fifo != NULL)
251     {
252         aout_DestroyFifo (p_mad_adec->p_aout_fifo);
253
254         /* Make sure the output thread leaves the NextFrame() function */
255         vlc_mutex_lock (&(p_mad_adec->p_aout_fifo->data_lock));
256         vlc_cond_signal (&(p_mad_adec->p_aout_fifo->data_wait));
257         vlc_mutex_unlock (&(p_mad_adec->p_aout_fifo->data_lock));
258     }
259
260     /* mad_decoder_finish releases the memory allocated inside the struct */
261     mad_decoder_finish( p_mad_adec->libmad_decoder );
262
263     /* Unlock the modules, p_mad_adec->p_config is released by the decoder subsystem  */
264     free( p_mad_adec->libmad_decoder );
265     free( p_mad_adec );
266
267     intf_WarnMsg( 4, "mad_adec debug: mad decoder thread %p destroyed", p_mad_adec);
268 }
269