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