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 #define MODULE_NAME mad_adec
24 #include "modules_inner.h"
26 /*****************************************************************************
28 *****************************************************************************/
31 #include <stdlib.h> /* malloc(), free() */
32 #include <string.h> /* strdup() */
35 #include "common.h" /* boolean_t, byte_t */
40 #include "audio_output.h"
43 #include "modules_export.h"
45 #include "stream_control.h"
46 #include "input_ext-dec.h"
50 /*****************************************************************************
51 * Libmad include files *
52 *****************************************************************************/
55 #include "mad_libmad.h"
57 /*****************************************************************************
59 *****************************************************************************/
60 static int mad_adec_Probe ( probedata_t * );
61 static int mad_adec_Run ( decoder_config_t * );
62 static int mad_adec_Init (mad_adec_thread_t * p_mad_adec);
63 static void mad_adec_ErrorThread (mad_adec_thread_t * p_mad_adec);
64 static void mad_adec_EndThread (mad_adec_thread_t * p_mad_adec);
66 /*****************************************************************************
68 *****************************************************************************/
69 void _M( adec_getfunctions )( function_list_t * p_function_list )
71 p_function_list->pf_probe = mad_adec_Probe;
72 p_function_list->functions.dec.pf_run = mad_adec_Run;
75 /*****************************************************************************
76 * Build configuration tree.
77 *****************************************************************************/
79 ADD_WINDOW( "Configuration for mad_adec module" )
80 ADD_COMMENT( "No device to configure." )
84 p_module->i_capabilities = MODULE_CAPABILITY_DEC;
85 p_module->psz_longname = "Libmad MPEG 1/2/3 audio decoder library";
89 _M( adec_getfunctions )( &p_module->p_functions->dec );
92 MODULE_DEACTIVATE_START
93 MODULE_DEACTIVATE_STOP
95 /*****************************************************************************
96 * mad_adec_Probe: probe the decoder and return score
97 *****************************************************************************
98 * Tries to launch a decoder and return score so that the interface is able
100 *****************************************************************************/
101 static int mad_adec_Probe( probedata_t *p_data )
103 if( p_data->i_type == MPEG1_AUDIO_ES || p_data->i_type == MPEG2_AUDIO_ES )
105 if( TestMethod( ADEC_MPEG_VAR, "mad" ) )
117 /*****************************************************************************
118 * mad_adec_Run: this function is called just after the thread is created
119 *****************************************************************************/
120 static int mad_adec_Run ( decoder_config_t * p_config )
122 mad_adec_thread_t * p_mad_adec;
124 intf_ErrMsg( "mad_adec debug: mad_adec thread launched, initializing" );
126 /* Allocate the memory needed to store the thread's structure */
127 p_mad_adec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t));
129 if (p_mad_adec == NULL)
131 intf_ErrMsg ( "mad_adec error: not enough memory "
132 "for mad_adec_Run() to allocate p_mad_adec" );
137 * Initialize the thread properties
139 p_mad_adec->p_config = p_config;
140 p_mad_adec->p_fifo = p_mad_adec->p_config->p_decoder_fifo;
141 if( mad_adec_Init( p_mad_adec ) )
143 intf_ErrMsg( "mad_adec error: could not initialize thread" );
147 /* mad decoder thread's main loop */
148 while ((!p_mad_adec->p_fifo->b_die) && (!p_mad_adec->p_fifo->b_error))
150 intf_ErrMsg( "mad_adec: starting libmad decoder" );
151 if (mad_decoder_run(p_mad_adec->libmad_decoder, MAD_DECODER_MODE_SYNC)==-1)
153 intf_ErrMsg( "mad_adec error: libmad decoder returns abnormally");
154 mad_adec_EndThread(p_mad_adec);
159 /* If b_error is set, the mad decoder thread enters the error loop */
160 if (p_mad_adec->p_fifo->b_error)
162 mad_adec_ErrorThread (p_mad_adec);
165 /* End of the ac3 decoder thread */
166 mad_adec_EndThread (p_mad_adec);
171 /*****************************************************************************
172 * mad_adec_Init: initialize data before entering main loop
173 *****************************************************************************/
174 static int mad_adec_Init( mad_adec_thread_t * p_mad_adec )
177 * Properties of audio for libmad
180 /* Initialize the libmad decoder structures */
181 p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
184 * Initialize bit stream
186 p_mad_adec->p_config->pf_init_bit_stream( &p_mad_adec->bit_stream,
187 p_mad_adec->p_config->p_decoder_fifo,
188 NULL, /* pf_bitstream_callback */
191 RealignBits( &p_mad_adec->bit_stream );
193 mad_decoder_init( p_mad_adec->libmad_decoder,
194 p_mad_adec, /* vlc's thread structure and p_fifo playbuffer */
195 libmad_input, /* input_func */
196 libmad_header, /* header_func */
198 libmad_output, /* output_func */
202 mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
205 * Initialize the output properties
208 /* Creating the audio output fifo */
209 p_mad_adec->p_aout_fifo = aout_CreateFifo( AOUT_ADEC_STEREO_FIFO, /* fifo type */
210 2, /* nr. of channels */
211 48000, /* frame rate in Hz ?*/
213 ADEC_FRAME_SIZE/2, /* frame size */
216 if ( p_mad_adec->p_aout_fifo == NULL )
221 intf_ErrMsg("mad_adec debug: mad decoder thread %p initialized", p_mad_adec);
227 /*****************************************************************************
228 * mad_adec_ErrorThread : mad decoder's RunThread() error loop
229 *****************************************************************************/
230 static void mad_adec_ErrorThread (mad_adec_thread_t * p_mad_adec)
232 /* We take the lock, because we are going to read/write the start/end
233 * indexes of the decoder fifo */
234 vlc_mutex_lock (&p_mad_adec->p_fifo->data_lock);
236 /* Wait until a `die' order is sent */
237 while (!p_mad_adec->p_fifo->b_die)
239 /* Trash all received PES packets */
240 while (!DECODER_FIFO_ISEMPTY(*p_mad_adec->p_fifo))
242 p_mad_adec->p_fifo->pf_delete_pes(
243 p_mad_adec->p_fifo->p_packets_mgt,
244 DECODER_FIFO_START(*p_mad_adec->p_fifo));
245 DECODER_FIFO_INCSTART (*p_mad_adec->p_fifo);
248 /* Waiting for the input thread to put new PES packets in the fifo */
249 vlc_cond_wait (&p_mad_adec->p_fifo->data_wait,
250 &p_mad_adec->p_fifo->data_lock);
253 /* We can release the lock before leaving */
254 vlc_mutex_unlock (&p_mad_adec->p_fifo->data_lock);
257 /*****************************************************************************
258 * mad_adec_EndThread : libmad decoder thread destruction
259 *****************************************************************************/
260 static void mad_adec_EndThread (mad_adec_thread_t * p_mad_adec)
262 intf_ErrMsg ("mad_adec debug: destroying mad decoder thread %p", p_mad_adec);
264 /* If the audio output fifo was created, we destroy it */
265 if (p_mad_adec->p_aout_fifo != NULL)
267 aout_DestroyFifo (p_mad_adec->p_aout_fifo);
269 /* Make sure the output thread leaves the NextFrame() function */
270 vlc_mutex_lock (&(p_mad_adec->p_aout_fifo->data_lock));
271 vlc_cond_signal (&(p_mad_adec->p_aout_fifo->data_wait));
272 vlc_mutex_unlock (&(p_mad_adec->p_aout_fifo->data_lock));
275 /* mad_decoder_finish releases the memory allocated inside the struct */
276 mad_decoder_finish( p_mad_adec->libmad_decoder );
278 /* Unlock the modules */
279 free( p_mad_adec->libmad_decoder );
280 // free( p_mad_adec->p_config ); /* for now a reminder until integration with cvs */
283 intf_ErrMsg ("mad_adec debug: mad decoder thread %p destroyed", p_mad_adec);