]> git.sesse.net Git - vlc/blob - modules/codec/mad/decoder.c
e7b25d489eb57ff9ed6d093d52b521da48f3c14b
[vlc] / 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 * );
46 static void EndThread      ( mad_adec_thread_t * );
47
48 /*****************************************************************************
49  * Module descriptor
50  *****************************************************************************/
51 #define DOWNSCALE_TEXT N_("mad audio downscale routine (fast,mpg321)")
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_("Libmad"), 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_dec;
89     int i_ret;
90
91     /* Allocate the memory needed to store the thread's structure */
92     p_dec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t));
93
94     if (p_dec == NULL)
95     {
96         msg_Err( p_fifo, "out of memory" );
97         DecoderError( p_fifo );
98         return VLC_ENOMEM;
99     }
100
101     /*
102      * Initialize the thread properties
103      */
104     p_dec->p_fifo = p_fifo;
105     if( InitThread( p_dec ) )
106     {
107         msg_Err( p_fifo, "could not initialize thread" );
108         DecoderError( p_fifo );
109         free( p_dec );
110         return VLC_ETHREAD;
111     }
112
113     /* mad decoder thread's main loop */
114     while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
115     {
116         msg_Dbg( p_dec->p_fifo, "starting libmad decoder" );
117         i_ret = mad_decoder_run( &p_dec->libmad_decoder,
118                                  MAD_DECODER_MODE_SYNC );
119         if( i_ret == -1 )
120         {
121             msg_Err( p_dec->p_fifo, "libmad decoder returned abnormally" );
122             DecoderError( p_dec->p_fifo );
123             EndThread(p_dec);
124             return VLC_EGENERIC;
125         }
126     }
127
128     /* If b_error is set, the mad decoder thread enters the error loop */
129     if (p_dec->p_fifo->b_error)
130     {
131         DecoderError( p_dec->p_fifo );
132     }
133
134     /* End of the mad decoder thread */
135     EndThread (p_dec);
136
137     return VLC_SUCCESS;
138 }
139
140 /*****************************************************************************
141  * InitThread: initialize data before entering main loop
142  *****************************************************************************/
143 static int InitThread( mad_adec_thread_t * p_dec )
144 {
145     decoder_fifo_t * p_fifo = p_dec->p_fifo;
146     char *psz_downscale = NULL;
147
148     /* Initialize the thread properties */
149     p_dec->p_aout = NULL;
150     p_dec->p_aout_input = NULL;
151     p_dec->output_format.i_format = AOUT_FMT_FIXED32;
152     p_dec->output_format.i_channels = 2; /* FIXME ! */
153
154     /*
155      * Properties of audio for libmad
156      */
157
158     /* Look what scaling method was requested by the user */
159     psz_downscale = config_GetPsz( p_fifo, "downscale" );
160
161     if ( strncmp(psz_downscale,"fast",4)==0 )
162     {
163         p_dec->audio_scaling = FAST_SCALING;
164         msg_Dbg( p_fifo, "downscale fast selected" );
165     }
166     else if ( strncmp(psz_downscale,"mpg321",7)==0 )
167     {
168         p_dec->audio_scaling = MPG321_SCALING;
169         msg_Dbg( p_fifo, "downscale mpg321 selected" );
170     }
171     else
172     {
173         p_dec->audio_scaling = FAST_SCALING;
174         msg_Dbg( p_fifo, "downscale default fast selected" );
175     }
176
177     if (psz_downscale) free(psz_downscale);
178
179     /* Initialize the libmad decoder structures */
180     p_dec->i_current_pts = p_dec->i_next_pts = 0;
181
182     mad_decoder_init( &p_dec->libmad_decoder,
183                       p_dec, /* vlc's thread structure and p_fifo playbuffer */
184                       libmad_input,    /* input_func */
185                       NULL,           /* header_func */
186                       NULL,                /* filter */
187                       libmad_output,  /* output_func */
188                       NULL,                 /* error */
189                       NULL );             /* message */
190
191     mad_decoder_options( &p_dec->libmad_decoder, MAD_OPTION_IGNORECRC );
192
193     /*
194      * Initialize the input properties
195      */
196
197     /* Init the Bitstream */
198     InitBitstream( &p_dec->bit_stream, p_dec->p_fifo, NULL, NULL );
199
200     /* Get the first data packet. */
201     vlc_mutex_lock( &p_fifo->data_lock );
202     while ( p_fifo->p_first == NULL )
203     {
204         if ( p_fifo->b_die )
205         {
206             vlc_mutex_unlock( &p_fifo->data_lock );
207             return VLC_EGENERIC;
208         }
209         vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
210     }
211     vlc_mutex_unlock( &p_fifo->data_lock );
212     p_dec->p_data = p_fifo->p_first->p_first;
213
214     return VLC_SUCCESS;
215 }
216
217 /*****************************************************************************
218  * EndThread : libmad decoder thread destruction
219  *****************************************************************************/
220 static void EndThread (mad_adec_thread_t * p_dec)
221 {
222     /* If the audio output fifo was created, we destroy it */
223     if (p_dec->p_aout_input != NULL)
224     {
225         aout_InputDelete( p_dec->p_aout, p_dec->p_aout_input );
226     }
227
228     /* mad_decoder_finish releases the memory allocated inside the struct */
229     mad_decoder_finish( &p_dec->libmad_decoder );
230
231     free( p_dec );
232 }
233