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 OpenDecoder ( vlc_object_t * );
44 static int RunDecoder ( 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 #define DOWNSCALE_TEXT N_("Mad audio downscale routine (fast,mp321)")
52 #define DOWNSCALE_LONGTEXT N_( \
53 "Specify the mad audio downscale routine you want to use. By default " \
54 "the mad plugin will use the fastest routine.")
57 add_category_hint( N_("Miscellaneous"), NULL );
58 add_string( "downscale", "fast", NULL, DOWNSCALE_TEXT, DOWNSCALE_LONGTEXT );
59 set_description( _("libmad MPEG 1/2/3 audio decoder") );
60 set_capability( "decoder", 100 );
61 set_callbacks( OpenDecoder, NULL );
64 /*****************************************************************************
65 * OpenDecoder: probe the decoder and return score
66 *****************************************************************************
67 * Tries to launch a decoder and return score so that the interface is able
69 *****************************************************************************/
70 static int OpenDecoder( vlc_object_t *p_this )
72 decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
74 if( p_fifo->i_fourcc != VLC_FOURCC('m','p','g','a') )
79 p_fifo->pf_run = RunDecoder;
83 /*****************************************************************************
84 * RunDecoder: this function is called just after the thread is created
85 *****************************************************************************/
86 static int RunDecoder( decoder_fifo_t *p_fifo )
88 mad_adec_thread_t * p_mad_adec;
90 /* Allocate the memory needed to store the thread's structure */
91 p_mad_adec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t));
93 if (p_mad_adec == NULL)
95 msg_Err( p_fifo, "out of memory" );
96 DecoderError( p_fifo );
101 * Initialize the thread properties
103 p_mad_adec->p_fifo = p_fifo;
104 if( InitThread( p_mad_adec ) )
106 msg_Err( p_fifo, "could not initialize thread" );
107 DecoderError( p_fifo );
112 /* mad decoder thread's main loop */
113 while ((!p_mad_adec->p_fifo->b_die) && (!p_mad_adec->p_fifo->b_error))
115 msg_Dbg( p_mad_adec->p_fifo, "starting libmad decoder" );
116 if (mad_decoder_run(p_mad_adec->libmad_decoder, MAD_DECODER_MODE_SYNC)==-1)
118 msg_Err( p_mad_adec->p_fifo, "libmad decoder returned abnormally" );
119 DecoderError( p_mad_adec->p_fifo );
120 EndThread(p_mad_adec);
125 /* If b_error is set, the mad decoder thread enters the error loop */
126 if (p_mad_adec->p_fifo->b_error)
128 DecoderError( p_mad_adec->p_fifo );
131 /* End of the mad decoder thread */
132 EndThread (p_mad_adec);
137 /*****************************************************************************
138 * InitThread: initialize data before entering main loop
139 *****************************************************************************/
140 static int InitThread( mad_adec_thread_t * p_mad_adec )
142 decoder_fifo_t * p_fifo = p_mad_adec->p_fifo;
143 char *psz_downscale = NULL;
146 * Properties of audio for libmad
149 /* Look what scaling method was requested by the user */
150 psz_downscale = config_GetPsz( p_fifo, "downscale" );
152 if ( strncmp(psz_downscale,"fast",4)==0 )
154 p_mad_adec->audio_scaling = FAST_SCALING;
155 msg_Dbg( p_fifo, "downscale fast selected" );
157 else if ( strncmp(psz_downscale,"mpg321",7)==0 )
159 p_mad_adec->audio_scaling = MPG321_SCALING;
160 msg_Dbg( p_fifo, "downscale mpg321 selected" );
164 p_mad_adec->audio_scaling = FAST_SCALING;
165 msg_Dbg( p_fifo, "downscale default fast selected" );
168 if (psz_downscale) free(psz_downscale);
170 /* Initialize the libmad decoder structures */
171 p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
172 if (p_mad_adec->libmad_decoder == NULL)
174 msg_Err( p_mad_adec->p_fifo, "out of memory" );
177 p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
179 mad_decoder_init( p_mad_adec->libmad_decoder,
180 p_mad_adec, /* vlc's thread structure and p_fifo playbuffer */
181 libmad_input, /* input_func */
184 libmad_output, /* output_func */
188 mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
189 // mad_timer_reset(&p_mad_adec->libmad_timer);
192 * Initialize the output properties
194 p_mad_adec->p_aout_fifo = NULL;
197 * Initialize the input properties
199 /* Get the first data packet. */
200 vlc_mutex_lock( &p_fifo->data_lock );
201 while ( p_fifo->p_first == NULL )
205 vlc_mutex_unlock( &p_fifo->data_lock );
208 vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
210 vlc_mutex_unlock( &p_fifo->data_lock );
211 p_mad_adec->p_data = p_fifo->p_first->p_first;
216 /*****************************************************************************
217 * EndThread : libmad decoder thread destruction
218 *****************************************************************************/
219 static void EndThread (mad_adec_thread_t * p_mad_adec)
221 /* If the audio output fifo was created, we destroy it */
222 if (p_mad_adec->p_aout_fifo != NULL)
224 aout_DestroyFifo (p_mad_adec->p_aout_fifo);
226 /* Make sure the output thread leaves the NextFrame() function */
227 vlc_mutex_lock (&(p_mad_adec->p_aout_fifo->data_lock));
228 vlc_cond_signal (&(p_mad_adec->p_aout_fifo->data_wait));
229 vlc_mutex_unlock (&(p_mad_adec->p_aout_fifo->data_lock));
232 /* mad_decoder_finish releases the memory allocated inside the struct */
233 mad_decoder_finish( p_mad_adec->libmad_decoder );
235 /* Unlock the modules, p_mad_adec->p_fifo is released by the decoder subsystem */
236 free( p_mad_adec->libmad_decoder );