1 /***************************************************************************
2 mad_adec.c - description
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
10 copyright : (C) 2001 by Jean-Paul Saman
11 email : jpsaman@wxs.nl
12 ***************************************************************************/
14 /***************************************************************************
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. *
21 ***************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
26 #include <stdlib.h> /* malloc(), free() */
27 #include <string.h> /* strdup() */
31 #include <vlc/decoder.h>
33 /*****************************************************************************
34 * Libmad include files *
35 *****************************************************************************/
38 #include "mad_libmad.h"
40 /*****************************************************************************
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 );
48 /*****************************************************************************
50 *****************************************************************************/
51 void _M( adec_getfunctions )( function_list_t * p_function_list )
53 p_function_list->functions.dec.pf_probe = decoder_Probe;
54 p_function_list->functions.dec.pf_run = decoder_Run;
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.")
66 ADD_CATEGORY_HINT( N_("Miscellaneous"), NULL )
67 ADD_STRING ( "downscale", "fast", NULL, DOWNSCALE_TEXT, DOWNSCALE_LONGTEXT )
71 SET_DESCRIPTION( _("libmad MPEG 1/2/3 audio decoder library") )
72 ADD_CAPABILITY( DECODER, 100 )
76 _M( adec_getfunctions )( &p_module->p_functions->dec );
79 MODULE_DEACTIVATE_START
80 MODULE_DEACTIVATE_STOP
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
87 *****************************************************************************/
88 static int decoder_Probe( u8 *pi_type )
90 if( *pi_type == MPEG1_AUDIO_ES || *pi_type == MPEG2_AUDIO_ES )
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 )
103 mad_adec_thread_t * p_mad_adec;
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));
108 if (p_mad_adec == NULL)
110 msg_Err( p_fifo, "out of memory" );
111 DecoderError( p_fifo );
116 * Initialize the thread properties
118 p_mad_adec->p_fifo = p_fifo;
119 if( InitThread( p_mad_adec ) )
121 msg_Err( p_fifo, "could not initialize thread" );
122 DecoderError( p_fifo );
127 /* mad decoder thread's main loop */
128 while ((!p_mad_adec->p_fifo->b_die) && (!p_mad_adec->p_fifo->b_error))
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)
133 msg_Err( p_mad_adec->p_fifo, "libmad decoder returned abnormally" );
134 DecoderError( p_mad_adec->p_fifo );
135 EndThread(p_mad_adec);
140 /* If b_error is set, the mad decoder thread enters the error loop */
141 if (p_mad_adec->p_fifo->b_error)
143 DecoderError( p_mad_adec->p_fifo );
146 /* End of the mad decoder thread */
147 EndThread (p_mad_adec);
152 /*****************************************************************************
153 * InitThread: initialize data before entering main loop
154 *****************************************************************************/
155 static int InitThread( mad_adec_thread_t * p_mad_adec )
157 decoder_fifo_t * p_fifo = p_mad_adec->p_fifo;
158 char *psz_downscale = NULL;
161 * Properties of audio for libmad
164 /* Look what scaling method was requested by the user */
165 psz_downscale = config_GetPsz( p_fifo, "downscale" );
167 if ( strncmp(psz_downscale,"fast",4)==0 )
169 p_mad_adec->audio_scaling = FAST_SCALING;
170 msg_Dbg( p_fifo, "downscale fast selected" );
172 else if ( strncmp(psz_downscale,"mpg321",7)==0 )
174 p_mad_adec->audio_scaling = MPG321_SCALING;
175 msg_Dbg( p_fifo, "downscale mpg321 selected" );
179 p_mad_adec->audio_scaling = FAST_SCALING;
180 msg_Dbg( p_fifo, "downscale default fast selected" );
183 if (psz_downscale) free(psz_downscale);
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)
189 msg_Err( p_mad_adec->p_fifo, "out of memory" );
192 p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
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 */
199 libmad_output, /* output_func */
203 mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
204 // mad_timer_reset(&p_mad_adec->libmad_timer);
207 * Initialize the output properties
209 p_mad_adec->p_aout_fifo = NULL;
212 * Initialize the input properties
214 /* Get the first data packet. */
215 vlc_mutex_lock( &p_fifo->data_lock );
216 while ( p_fifo->p_first == NULL )
220 vlc_mutex_unlock( &p_fifo->data_lock );
223 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
225 vlc_mutex_unlock( &p_fifo->data_lock );
226 p_mad_adec->p_data = p_fifo->p_first->p_first;
231 /*****************************************************************************
232 * EndThread : libmad decoder thread destruction
233 *****************************************************************************/
234 static void EndThread (mad_adec_thread_t * p_mad_adec)
236 /* If the audio output fifo was created, we destroy it */
237 if (p_mad_adec->p_aout_fifo != NULL)
239 aout_DestroyFifo (p_mad_adec->p_aout_fifo);
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));
247 /* mad_decoder_finish releases the memory allocated inside the struct */
248 mad_decoder_finish( p_mad_adec->libmad_decoder );
250 /* Unlock the modules, p_mad_adec->p_fifo is released by the decoder subsystem */
251 free( p_mad_adec->libmad_decoder );