Adapted mad codec plugin to new aout3. Not tested yet.`
[vlc.git] / modules / codec / mad / decoder.c
1 /***************************************************************************
2               decoder.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 <vlc/vlc.h>
30 #include <vlc/aout.h>
31 #include <vlc/decoder.h>
32
33 /*****************************************************************************
34  * Libmad include files                                                      *
35  *****************************************************************************/
36 #include <mad.h>
37 #include "decoder.h"
38 #include "libmad.h"
39
40 /*****************************************************************************
41  * Local prototypes
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 );
47
48 /*****************************************************************************
49  * Module descriptor
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.")
55
56 vlc_module_begin();
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 );
62 vlc_module_end();
63
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
68  * to choose.
69  *****************************************************************************/
70 static int OpenDecoder( vlc_object_t *p_this )
71 {   
72     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
73
74     if( p_fifo->i_fourcc != VLC_FOURCC('m','p','g','a') )
75     {   
76         return VLC_EGENERIC; 
77     }
78     
79     p_fifo->pf_run = RunDecoder;
80     return VLC_SUCCESS;
81 }
82
83 /*****************************************************************************
84  * RunDecoder: this function is called just after the thread is created
85  *****************************************************************************/
86 static int RunDecoder( decoder_fifo_t *p_fifo )
87 {
88     mad_adec_thread_t *   p_mad_adec;
89
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));
92
93     if (p_mad_adec == NULL)
94     {
95         msg_Err( p_fifo, "out of memory" );
96         DecoderError( p_fifo );
97         return( -1 );
98     }
99
100     /*
101      * Initialize the thread properties
102      */
103     p_mad_adec->p_fifo = p_fifo;
104     if( InitThread( p_mad_adec ) )
105     {
106         msg_Err( p_fifo, "could not initialize thread" );
107         DecoderError( p_fifo );
108         free( p_mad_adec );
109         return( -1 );
110     }
111
112     /* mad decoder thread's main loop */
113     while ((!p_mad_adec->p_fifo->b_die) && (!p_mad_adec->p_fifo->b_error))
114     {
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)
117         {
118             msg_Err( p_mad_adec->p_fifo, "libmad decoder returned abnormally" );
119             DecoderError( p_mad_adec->p_fifo );
120             EndThread(p_mad_adec);
121             return( -1 );
122         }
123     }
124
125     /* If b_error is set, the mad decoder thread enters the error loop */
126     if (p_mad_adec->p_fifo->b_error)
127     {
128         DecoderError( p_mad_adec->p_fifo );
129     }
130
131     /* End of the mad decoder thread */
132     EndThread (p_mad_adec);
133
134     return( 0 );
135 }
136
137 /*****************************************************************************
138  * InitThread: initialize data before entering main loop
139  *****************************************************************************/
140 static int InitThread( mad_adec_thread_t * p_mad_adec )
141 {
142     decoder_fifo_t * p_fifo = p_mad_adec->p_fifo;
143     char *psz_downscale = NULL;
144
145     /* Initialize the thread properties */
146     p_mad_adec->p_aout = NULL;
147     p_mad_adec->p_aout_input = NULL;
148     p_mad_adec->output_format.i_format = AOUT_FMT_FIXED32;
149     p_mad_adec->output_format.i_channels = 2; /* FIXME ! */
150
151     /*
152      * Properties of audio for libmad
153      */
154
155     /* Look what scaling method was requested by the user */
156     psz_downscale = config_GetPsz( p_fifo, "downscale" );
157
158     if ( strncmp(psz_downscale,"fast",4)==0 )
159     {
160         p_mad_adec->audio_scaling = FAST_SCALING;
161         msg_Dbg( p_fifo, "downscale fast selected" );
162     }
163     else if ( strncmp(psz_downscale,"mpg321",7)==0 )
164     {
165         p_mad_adec->audio_scaling = MPG321_SCALING;
166         msg_Dbg( p_fifo, "downscale mpg321 selected" );
167     }
168     else
169     {
170         p_mad_adec->audio_scaling = FAST_SCALING;
171         msg_Dbg( p_fifo, "downscale default fast selected" );
172     }
173
174     if (psz_downscale) free(psz_downscale);
175
176     /* Initialize the libmad decoder structures */
177     p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
178     if (p_mad_adec->libmad_decoder == NULL)
179     {
180         msg_Err( p_mad_adec->p_fifo, "out of memory" );
181         return -1;
182     }
183     p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
184
185     mad_decoder_init( p_mad_adec->libmad_decoder,
186                       p_mad_adec,       /* vlc's thread structure and p_fifo playbuffer */
187                       libmad_input,     /* input_func */
188                       0,                /* header_func */
189                       0,                /* filter */
190                       libmad_output3,   /* output_func */
191                       0,                /* error */
192                       0);               /* message */
193
194     mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
195
196     /*
197      * Initialize the input properties
198      */
199     /* Get the first data packet. */
200     vlc_mutex_lock( &p_fifo->data_lock );
201     while ( p_fifo->p_first == NULL )
202     {
203         if ( p_fifo->b_die )
204         {
205             vlc_mutex_unlock( &p_fifo->data_lock );
206             return( -1 );
207         }
208         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
209     }
210     vlc_mutex_unlock( &p_fifo->data_lock );
211     p_mad_adec->p_data = p_fifo->p_first->p_first;
212
213     return( 0 );
214 }
215
216 /*****************************************************************************
217  * EndThread : libmad decoder thread destruction
218  *****************************************************************************/
219 static void EndThread (mad_adec_thread_t * p_mad_adec)
220 {
221     /* If the audio output fifo was created, we destroy it */
222     if (p_mad_adec->p_aout_fifo != NULL)
223     {
224         aout_InputDelete( p_mad_adec->p_aout, p_mad_adec->p_aout_input );
225
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));
230     }
231
232     /* mad_decoder_finish releases the memory allocated inside the struct */
233     mad_decoder_finish( p_mad_adec->libmad_decoder );
234
235     /* Unlock the modules, p_mad_adec->p_fifo is released by the decoder subsystem  */
236     free( p_mad_adec->libmad_decoder );
237     free( p_mad_adec );
238 }
239