]> git.sesse.net Git - vlc/blob - modules/codec/mad/decoder.c
* ./modules/*: moved plugins to the new tree. Yet untested builds include
[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 * 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     /*
146      * Properties of audio for libmad
147      */
148                 
149                 /* Look what scaling method was requested by the user */
150     psz_downscale = config_GetPsz( p_fifo, "downscale" );
151
152     if ( strncmp(psz_downscale,"fast",4)==0 )
153     {
154         p_mad_adec->audio_scaling = FAST_SCALING;
155         msg_Dbg( p_fifo, "downscale fast selected" );
156     }
157     else if ( strncmp(psz_downscale,"mpg321",7)==0 )
158     {
159         p_mad_adec->audio_scaling = MPG321_SCALING;
160         msg_Dbg( p_fifo, "downscale mpg321 selected" );
161     }
162     else
163     {
164         p_mad_adec->audio_scaling = FAST_SCALING;
165         msg_Dbg( p_fifo, "downscale default fast selected" );
166     }
167
168                 if (psz_downscale) free(psz_downscale);
169
170     /* Initialize the libmad decoder structures */
171     p_mad_adec->libmad_decoder = (struct mad_decoder*) malloc(sizeof(struct mad_decoder));
172     if (p_mad_adec->libmad_decoder == NULL)
173     {
174         msg_Err( p_mad_adec->p_fifo, "out of memory" );
175         return -1;
176     }
177     p_mad_adec->i_current_pts = p_mad_adec->i_next_pts = 0;
178
179     mad_decoder_init( p_mad_adec->libmad_decoder,
180                       p_mad_adec,         /* vlc's thread structure and p_fifo playbuffer */
181                       libmad_input,          /* input_func */
182                       0,                /* header_func */
183                       0,                /* filter */
184                       libmad_output,         /* output_func */
185                       0,                  /* error */
186                       0);                    /* message */
187
188     mad_decoder_options(p_mad_adec->libmad_decoder, MAD_OPTION_IGNORECRC);
189 //    mad_timer_reset(&p_mad_adec->libmad_timer);
190
191     /*
192      * Initialize the output properties
193      */
194     p_mad_adec->p_aout_fifo = NULL;
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_DestroyFifo (p_mad_adec->p_aout_fifo);
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