* modules/codec/mad/*: don't let mad drop corrupted mpeg frames without telling us...
[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 * );
46 static void EndThread      ( mad_adec_thread_t * );
47
48 /*****************************************************************************
49  * Module descriptor
50  *****************************************************************************/
51 vlc_module_begin();
52     add_category_hint( N_("Libmad"), NULL );
53     set_description( _("libmad MPEG 1/2/3 audio decoder") );
54     set_capability( "decoder", 100 );
55     set_callbacks( OpenDecoder, NULL );
56 vlc_module_end();
57
58 /*****************************************************************************
59  * OpenDecoder: probe the decoder and return score
60  *****************************************************************************
61  * Tries to launch a decoder and return score so that the interface is able
62  * to choose.
63  *****************************************************************************/
64 static int OpenDecoder( vlc_object_t *p_this )
65 {   
66     decoder_fifo_t *p_fifo = (decoder_fifo_t*) p_this;
67
68     if( p_fifo->i_fourcc != VLC_FOURCC('m','p','g','a') )
69     {   
70         return VLC_EGENERIC; 
71     }
72     
73     p_fifo->pf_run = RunDecoder;
74     return VLC_SUCCESS;
75 }
76
77 /*****************************************************************************
78  * RunDecoder: this function is called just after the thread is created
79  *****************************************************************************/
80 static int RunDecoder( decoder_fifo_t *p_fifo )
81 {
82     mad_adec_thread_t *   p_dec;
83     int i_ret;
84
85     /* Allocate the memory needed to store the thread's structure */
86     p_dec = (mad_adec_thread_t *) malloc(sizeof(mad_adec_thread_t));
87
88     if (p_dec == NULL)
89     {
90         msg_Err( p_fifo, "out of memory" );
91         DecoderError( p_fifo );
92         return VLC_ENOMEM;
93     }
94
95     /*
96      * Initialize the thread properties
97      */
98     p_dec->p_fifo = p_fifo;
99     if( InitThread( p_dec ) )
100     {
101         msg_Err( p_fifo, "could not initialize thread" );
102         DecoderError( p_fifo );
103         free( p_dec );
104         return VLC_ETHREAD;
105     }
106
107     /* mad decoder thread's main loop */
108     while( !p_dec->p_fifo->b_die && !p_dec->p_fifo->b_error )
109     {
110         msg_Dbg( p_dec->p_fifo, "starting libmad decoder" );
111         i_ret = mad_decoder_run( &p_dec->libmad_decoder,
112                                  MAD_DECODER_MODE_SYNC );
113         if( i_ret == -1 )
114         {
115             msg_Err( p_dec->p_fifo, "libmad decoder returned abnormally" );
116             DecoderError( p_dec->p_fifo );
117             EndThread(p_dec);
118             return VLC_EGENERIC;
119         }
120     }
121
122     /* If b_error is set, the mad decoder thread enters the error loop */
123     if (p_dec->p_fifo->b_error)
124     {
125         DecoderError( p_dec->p_fifo );
126     }
127
128     /* End of the mad decoder thread */
129     EndThread (p_dec);
130
131     return VLC_SUCCESS;
132 }
133
134 /*****************************************************************************
135  * InitThread: initialize data before entering main loop
136  *****************************************************************************/
137 static int InitThread( mad_adec_thread_t * p_dec )
138 {
139     /* Initialize the thread properties */
140     p_dec->p_aout = NULL;
141     p_dec->p_aout_input = NULL;
142     p_dec->output_format.i_format = VLC_FOURCC('f','i','3','2');
143
144     /*
145      * Properties of audio for libmad
146      */
147
148     /* Initialize the libmad decoder structures */
149     p_dec->i_current_pts = p_dec->i_next_pts = 0;
150
151     mad_decoder_init( &p_dec->libmad_decoder,
152                       p_dec, /* vlc's thread structure and p_fifo playbuffer */
153                       libmad_input,    /* input_func */
154                       NULL,           /* header_func */
155                       NULL,                /* filter */
156                       libmad_output,  /* output_func */
157                       libmad_error,         /* error */
158                       NULL );             /* message */
159
160     mad_decoder_options( &p_dec->libmad_decoder, MAD_OPTION_IGNORECRC );
161
162     /*
163      * Initialize the input properties
164      */
165
166     return InitBitstream( &p_dec->bit_stream, p_dec->p_fifo, NULL, NULL );
167 }
168
169 /*****************************************************************************
170  * EndThread : libmad decoder thread destruction
171  *****************************************************************************/
172 static void EndThread (mad_adec_thread_t * p_dec)
173 {
174     /* If the audio output fifo was created, we destroy it */
175     if (p_dec->p_aout_input != NULL)
176     {
177         aout_DecDelete( p_dec->p_aout, p_dec->p_aout_input );
178     }
179
180     /* mad_decoder_finish releases the memory allocated inside the struct */
181     mad_decoder_finish( &p_dec->libmad_decoder );
182
183     CloseBitstream( &p_dec->bit_stream );
184     free( p_dec );
185 }