]> git.sesse.net Git - vlc/blob - plugins/mad/mad_adec.c
* ./src/misc/modules_plugin.h: exported input_ClockManageRef for fenrir.
[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 /*****************************************************************************
37  * Libmad include files                                                      *
38  *****************************************************************************/
39 #include <mad.h>
40 #include "mad_adec.h"
41 #include "mad_libmad.h"
42
43 /*****************************************************************************
44  * Local prototypes
45  *****************************************************************************/
46 static int  decoder_Probe  ( u8 * );
47 static int  decoder_Run    ( decoder_config_t * );
48 static int  InitThread     ( mad_adec_thread_t * p_mad_adec );
49 static void EndThread      ( mad_adec_thread_t * p_mad_adec );
50
51 /*****************************************************************************
52  * Capabilities
53  *****************************************************************************/
54 void _M( adec_getfunctions )( function_list_t * p_function_list )
55 {
56     p_function_list->functions.dec.pf_probe = decoder_Probe;
57     p_function_list->functions.dec.pf_run   = decoder_Run;
58 }
59
60 /*****************************************************************************
61  * Build configuration tree.
62  *****************************************************************************/
63 MODULE_CONFIG_START
64 MODULE_CONFIG_STOP
65
66 MODULE_INIT_START
67     SET_DESCRIPTION( _("libmad MPEG 1/2/3 audio decoder library") )
68     ADD_CAPABILITY( DECODER, 100 )
69     ADD_SHORTCUT( "mad" )
70 MODULE_INIT_STOP
71
72 MODULE_ACTIVATE_START
73     _M( adec_getfunctions )( &p_module->p_functions->dec );
74 MODULE_ACTIVATE_STOP
75
76 MODULE_DEACTIVATE_START
77 MODULE_DEACTIVATE_STOP
78
79 /*****************************************************************************
80  * decoder_Probe: probe the decoder and return score
81  *****************************************************************************
82  * Tries to launch a decoder and return score so that the interface is able
83  * to chose.
84  *****************************************************************************/
85 static int decoder_Probe( u8 *pi_type )
86 {
87     if( *pi_type == MPEG1_AUDIO_ES || *pi_type == MPEG2_AUDIO_ES )
88     {
89         return 0;
90     }
91
92     return -1;
93 }
94
95 /*****************************************************************************
96  * decoder_Run: this function is called just after the thread is created
97  *****************************************************************************/
98 static int decoder_Run ( decoder_config_t * p_config )
99 {
100     mad_adec_thread_t *   p_mad_adec;
101
102     intf_ErrMsg( "mad_adec debug: mad_adec thread launched, initializing" );
103
104     /* Allocate the memory needed to store the thread's structure */
105     p_mad_adec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t));
106
107     if (p_mad_adec == NULL)
108     {
109         intf_ErrMsg ( "mad_adec error: not enough memory "
110                       "for decoder_Run() to allocate p_mad_adec" );
111         DecoderError( p_config->p_decoder_fifo );
112         return( -1 );
113     }
114
115     /*
116      * Initialize the thread properties
117      */
118     p_mad_adec->p_config = p_config;
119     p_mad_adec->p_fifo = p_mad_adec->p_config->p_decoder_fifo;
120     if( InitThread( p_mad_adec ) )
121     {
122         intf_ErrMsg( "mad_adec error: could not initialize thread" );
123         DecoderError( p_config->p_decoder_fifo );
124         free( p_mad_adec );
125         return( -1 );
126     }
127
128     /* mad decoder thread's main loop */
129     while ((!p_mad_adec->p_fifo->b_die) && (!p_mad_adec->p_fifo->b_error))
130     {
131         intf_ErrMsg( "mad_adec: starting libmad decoder" );
132         if (mad_decoder_run(p_mad_adec->libmad_decoder, MAD_DECODER_MODE_SYNC)==-1)
133         {
134             intf_ErrMsg( "mad_adec error: libmad decoder returns abnormally");
135             DecoderError( p_mad_adec->p_fifo );
136             EndThread(p_mad_adec);
137             return( -1 );
138         }
139     }
140
141     /* If b_error is set, the mad decoder thread enters the error loop */
142     if (p_mad_adec->p_fifo->b_error)
143     {
144         DecoderError( p_mad_adec->p_fifo );
145     }
146
147     /* End of the mad decoder thread */
148     EndThread (p_mad_adec);
149
150     return( 0 );
151 }
152
153 /*****************************************************************************
154  * InitThread: initialize data before entering main loop
155  *****************************************************************************/
156 static int InitThread( mad_adec_thread_t * p_mad_adec )
157 {
158     decoder_fifo_t * p_fifo = p_mad_adec->p_fifo;
159
160     /*
161      * Properties of audio for libmad
162      */
163         
164     /* Initialize the libmad decoder structures */
165     p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
166     if (p_mad_adec->libmad_decoder == NULL)
167     {
168         intf_ErrMsg ( "mad_adec error: not enough memory "
169                       "for decoder_InitThread() to allocate p_mad_adec->libmad_decder" );
170         return -1;
171     }
172     p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
173
174     mad_decoder_init( p_mad_adec->libmad_decoder,
175                           p_mad_adec,         /* vlc's thread structure and p_fifo playbuffer */
176                       libmad_input,          /* input_func */
177                       0,                /* header_func */
178                       0,                /* filter */
179                       libmad_output,         /* output_func */
180                       0,                  /* error */
181                       0);                    /* message */
182
183     mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
184     mad_timer_reset(&p_mad_adec->libmad_timer);
185
186     /*
187      * Initialize the output properties
188      */
189     p_mad_adec->p_aout_fifo = NULL;
190
191     /*
192      * Initialize the input properties
193      */
194     /* Get the first data packet. */
195     vlc_mutex_lock( &p_fifo->data_lock );
196     while ( p_fifo->p_first == NULL )
197     {
198         if ( p_fifo->b_die )
199         {
200             vlc_mutex_unlock( &p_fifo->data_lock );
201             return( -1 );
202         }
203         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
204     }
205     vlc_mutex_unlock( &p_fifo->data_lock );
206     p_mad_adec->p_data = p_fifo->p_first->p_first;
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, p_mad_adec->p_config is released by the decoder subsystem  */
235     free( p_mad_adec->libmad_decoder );
236     free( p_mad_adec );
237
238     intf_ErrMsg ("mad_adec debug: mad decoder thread %p destroyed", p_mad_adec);
239 }
240