]> git.sesse.net Git - vlc/blob - plugins/mad/mad_adec.c
Some heavy changes today:
[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 #include "debug.h"
37
38 /*****************************************************************************
39  * Libmad include files                                                      *
40  *****************************************************************************/
41 #include <mad.h>
42 #include "mad_adec.h"
43 #include "mad_libmad.h"
44
45 /*****************************************************************************
46  * Local prototypes
47  *****************************************************************************/
48 static int  decoder_Probe  ( probedata_t * );
49 static int  decoder_Run    ( decoder_config_t * );
50 static int  InitThread     ( mad_adec_thread_t * p_mad_adec );
51 static void EndThread      ( mad_adec_thread_t * p_mad_adec );
52
53 /*****************************************************************************
54  * Capabilities
55  *****************************************************************************/
56 void _M( adec_getfunctions )( function_list_t * p_function_list )
57 {
58     p_function_list->pf_probe = decoder_Probe;
59     p_function_list->functions.dec.pf_run = decoder_Run;
60 }
61
62 /*****************************************************************************
63  * Build configuration tree.
64  *****************************************************************************/
65 MODULE_CONFIG_START
66     ADD_WINDOW( "Configuration for mad_adec module" )
67         ADD_COMMENT( "No device to configure." )
68 MODULE_CONFIG_STOP
69
70 MODULE_INIT_START
71     SET_DESCRIPTION( "Libmad MPEG 1/2/3 audio decoder library" )
72     ADD_CAPABILITY( DECODER, 50 )
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( probedata_t *p_data )
89 {
90     if( p_data->i_type == MPEG1_AUDIO_ES || p_data->i_type == MPEG2_AUDIO_ES )
91     {
92         return( 50 );
93     }
94     else
95     {
96         return( 0 );
97     }
98 }
99
100 /*****************************************************************************
101  * decoder_Run: this function is called just after the thread is created
102  *****************************************************************************/
103 static int decoder_Run ( decoder_config_t * p_config )
104 {
105     mad_adec_thread_t *   p_mad_adec;
106
107     intf_ErrMsg( "mad_adec debug: mad_adec thread launched, initializing" );
108
109     /* Allocate the memory needed to store the thread's structure */
110     p_mad_adec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t));
111
112     if (p_mad_adec == NULL)
113     {
114         intf_ErrMsg ( "mad_adec error: not enough memory "
115                       "for decoder_Run() to allocate p_mad_adec" );
116         DecoderError( p_config->p_decoder_fifo );
117         return( -1 );
118     }
119
120     /*
121      * Initialize the thread properties
122      */
123     p_mad_adec->p_config = p_config;
124     p_mad_adec->p_fifo = p_mad_adec->p_config->p_decoder_fifo;
125     if( InitThread( p_mad_adec ) )
126     {
127         intf_ErrMsg( "mad_adec error: could not initialize thread" );
128         DecoderError( p_config->p_decoder_fifo );
129         free( p_mad_adec );
130         return( -1 );
131     }
132
133     /* mad decoder thread's main loop */
134     while ((!p_mad_adec->p_fifo->b_die) && (!p_mad_adec->p_fifo->b_error))
135     {
136         intf_ErrMsg( "mad_adec: starting libmad decoder" );
137         if (mad_decoder_run(p_mad_adec->libmad_decoder, MAD_DECODER_MODE_SYNC)==-1)
138         {
139           intf_ErrMsg( "mad_adec error: libmad decoder returns abnormally");
140           DecoderError( p_mad_adec->p_fifo );
141           EndThread(p_mad_adec);
142           return( -1 );
143         }
144     }
145
146     /* If b_error is set, the mad decoder thread enters the error loop */
147     if (p_mad_adec->p_fifo->b_error)
148     {
149         DecoderError( p_mad_adec->p_fifo );
150     }
151
152     /* End of the ac3 decoder thread */
153     EndThread (p_mad_adec);
154
155     return( 0 );
156 }
157
158 /*****************************************************************************
159  * InitThread: initialize data before entering main loop
160  *****************************************************************************/
161 static int InitThread( mad_adec_thread_t * p_mad_adec )
162 {
163     /*
164      * Properties of audio for libmad
165      */
166         
167     /* Initialize the libmad decoder structures */
168     p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
169
170     /*
171      * Initialize bit stream
172      */
173     p_mad_adec->p_config->pf_init_bit_stream( &p_mad_adec->bit_stream,
174                                               p_mad_adec->p_config->p_decoder_fifo,
175                                               NULL,    /* pf_bitstream_callback */
176                                               NULL );  /* void **/
177
178     RealignBits( &p_mad_adec->bit_stream );
179
180     mad_decoder_init( p_mad_adec->libmad_decoder,
181                       p_mad_adec,       /* vlc's thread structure and p_fifo playbuffer */
182                       libmad_input,     /* input_func */
183                       libmad_header,    /* header_func */
184                       0,                /* filter */
185                       libmad_output,    /* output_func */
186                       0,        /* error */
187                       0);               /* message */
188
189     mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
190         
191     /*
192      * Initialize the output properties
193      */
194
195     /* Creating the audio output fifo */
196     p_mad_adec->p_aout_fifo = aout_CreateFifo(  AOUT_ADEC_STEREO_FIFO, /* fifo type */
197                                                 2,                     /* nr. of channels */
198                                                 48000,                 /* frame rate in Hz ?*/
199                                                 0,                     /* units */
200                                                 ADEC_FRAME_SIZE/2,     /* frame size */
201                                                 NULL  );               /* buffer */
202
203     if ( p_mad_adec->p_aout_fifo == NULL )
204     {
205         return( -1 );
206     }
207
208     intf_ErrMsg("mad_adec debug: mad decoder thread %p initialized", p_mad_adec);
209
210     return( 0 );
211 }
212
213 /*****************************************************************************
214  * EndThread : libmad decoder thread destruction
215  *****************************************************************************/
216 static void EndThread (mad_adec_thread_t * p_mad_adec)
217 {
218     intf_ErrMsg ("mad_adec debug: destroying mad decoder thread %p", p_mad_adec);
219
220     /* If the audio output fifo was created, we destroy it */
221     if (p_mad_adec->p_aout_fifo != NULL)
222     {
223         aout_DestroyFifo (p_mad_adec->p_aout_fifo);
224
225         /* Make sure the output thread leaves the NextFrame() function */
226         vlc_mutex_lock (&(p_mad_adec->p_aout_fifo->data_lock));
227         vlc_cond_signal (&(p_mad_adec->p_aout_fifo->data_wait));
228         vlc_mutex_unlock (&(p_mad_adec->p_aout_fifo->data_lock));
229     }
230
231     /* mad_decoder_finish releases the memory allocated inside the struct */
232     mad_decoder_finish( p_mad_adec->libmad_decoder );
233
234     /* Unlock the modules */
235     free( p_mad_adec->libmad_decoder );
236 //    free( p_mad_adec->p_config ); /* for now a reminder until integration with cvs */
237     free( p_mad_adec );
238
239     intf_ErrMsg ("mad_adec debug: mad decoder thread %p destroyed", p_mad_adec);
240 }
241