]> git.sesse.net Git - vlc/blob - modules/codec/mpg123.c
mediacodec: fix warning
[vlc] / modules / codec / mpg123.c
1 /*****************************************************************************
2  * mpg123.c: MPEG-1 & 2 audio layer I, II, III + MPEG 2.5 decoder
3  *****************************************************************************
4  * Copyright (C) 2001-2014 VLC authors and VideoLAN
5  *
6  * Authors: Ludovic Fauvet <etix@videolan.org>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24 * Preamble
25 *****************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <mpg123.h>
32
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_aout.h>
36 #include <vlc_block.h>
37 #include <vlc_codec.h>
38
39 /*****************************************************************************
40  * Local prototypes
41  *****************************************************************************/
42 static int      OpenDecoder( vlc_object_t * );
43 static void     CloseDecoder( vlc_object_t * );
44 static block_t *DecodeBlock( decoder_t *, block_t ** );
45 static int      InitMPG123( void );
46 static void     ExitMPG123( void );
47
48 static unsigned int mpg123_refcount = 0;
49 static vlc_mutex_t mpg123_mutex = VLC_STATIC_MUTEX;
50
51 /*****************************************************************************
52  * Local structures
53  *****************************************************************************/
54 struct decoder_sys_t
55 {
56     mpg123_handle * p_handle;
57     date_t          end_date;
58
59     struct mpg123_frameinfo frame_info;
60 };
61
62 /*****************************************************************************
63  * Module descriptor
64  *****************************************************************************/
65 vlc_module_begin ()
66     set_category( CAT_INPUT )
67     set_subcategory( SUBCAT_INPUT_ACODEC )
68     set_description( N_("MPEG audio decoder using mpg123") )
69     set_capability( "decoder", 99 )
70     set_shortname( "mpg123" )
71     set_callbacks( OpenDecoder, CloseDecoder )
72 vlc_module_end ()
73
74 /****************************************************************************
75  * DecodeBlock: the whole thing
76  ****************************************************************************/
77 static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
78 {
79     int i_err;
80     block_t *p_block = pp_block ? *pp_block : NULL;
81     decoder_sys_t *p_sys = p_dec->p_sys;
82
83     if( !pp_block || !p_block )
84         return NULL;
85
86     if( p_block->i_buffer == 0 )
87         return NULL;
88
89     if( !date_Get( &p_sys->end_date ) && p_block->i_pts <= VLC_TS_INVALID )
90     {
91         /* We've just started the stream, wait for the first PTS. */
92         msg_Dbg( p_dec, "waiting for PTS" );
93         goto error;
94     }
95
96     if( p_block->i_flags & ( BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED ) )
97     {
98         date_Set( &p_sys->end_date, 0 );
99         goto error;
100     }
101
102     /* Feed mpg123 with raw data */
103     i_err = mpg123_feed( p_sys->p_handle, p_block->p_buffer,
104                          p_block->i_buffer );
105
106     if( i_err != MPG123_OK )
107     {
108         msg_Err( p_dec, "mpg123_feed failed: %s", mpg123_plain_strerror( i_err ) );
109         goto error;
110     }
111
112     /* Get details about the stream */
113     i_err = mpg123_info( p_sys->p_handle, &p_sys->frame_info );
114
115     if( i_err == MPG123_NEED_MORE )
116     {
117         /* Need moar data */
118         goto error;
119     }
120     else if( i_err != MPG123_OK )
121     {
122         msg_Err( p_dec, "mpg123_info failed: %s", mpg123_plain_strerror( i_err ) );
123         goto error;
124     }
125
126     /* Configure the output */
127     p_block->i_nb_samples = mpg123_spf( p_sys->p_handle );
128     p_dec->fmt_out.i_bitrate = p_sys->frame_info.bitrate * 1000;
129
130     switch( p_sys->frame_info.mode )
131     {
132         case MPG123_M_STEREO:
133         case MPG123_M_JOINT:
134             p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
135             break;
136         case MPG123_M_DUAL:
137             p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
138                                                      | AOUT_CHAN_DUALMONO;
139             break;
140         case MPG123_M_MONO:
141             p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_CENTER;
142             break;
143         default:
144             msg_Err( p_dec, "Unknown mode");
145             goto error;
146     }
147
148     p_dec->fmt_out.audio.i_physical_channels =
149         p_dec->fmt_out.audio.i_original_channels & AOUT_CHAN_PHYSMASK;
150
151     /* Date management */
152     if( p_dec->fmt_out.audio.i_rate != p_sys->frame_info.rate )
153     {
154         p_dec->fmt_out.audio.i_rate = p_sys->frame_info.rate;
155         date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
156         date_Set( &p_sys->end_date, 0 );
157     }
158
159     if( p_block->i_pts > VLC_TS_INVALID &&
160         p_block->i_pts != date_Get( &p_sys->end_date ) )
161     {
162         date_Set( &p_sys->end_date, p_block->i_pts );
163     }
164
165     /* Request a new audio buffer */
166     block_t *p_out = decoder_NewAudioBuffer( p_dec, p_block->i_nb_samples );
167     if( unlikely( !p_out ) )
168         goto error;
169
170     /* Configure the buffer */
171     p_out->i_nb_samples = p_block->i_nb_samples;
172     p_out->i_dts = p_out->i_pts = date_Get( &p_sys->end_date );
173     p_out->i_length = date_Increment( &p_sys->end_date, p_block->i_nb_samples )
174         - p_out->i_pts;
175
176     /* Make mpg123 write directly into the VLC output buffer */
177     i_err = mpg123_replace_buffer( p_sys->p_handle, p_out->p_buffer, p_out->i_buffer );
178     if( i_err != MPG123_OK )
179     {
180         msg_Err( p_dec, "could not replace buffer: %s", mpg123_plain_strerror( i_err ) );
181         block_Release( p_out );
182         goto error;
183     }
184
185     *pp_block = NULL; /* avoid being fed the same packet again */
186
187     /* Do the actual decoding now */
188     i_err = mpg123_decode_frame( p_sys->p_handle, NULL, NULL, NULL );
189     if( i_err != MPG123_OK )
190     {
191         if( i_err != MPG123_NEW_FORMAT )
192             msg_Err( p_dec, "mpg123_decode_frame error: %s", mpg123_plain_strerror( i_err ) );
193         block_Release( p_out );
194         goto error;
195     }
196
197     block_Release( p_block );
198     return p_out;
199
200 error:
201     block_Release( p_block );
202     return NULL;
203 }
204
205 /*****************************************************************************
206  * OpenDecoder :
207  *****************************************************************************/
208 static int OpenDecoder( vlc_object_t *p_this )
209 {
210     decoder_t *p_dec = (decoder_t *)p_this;
211     decoder_sys_t *p_sys;
212
213     if( p_dec->fmt_in.i_codec != VLC_CODEC_MPGA &&
214         p_dec->fmt_in.i_codec != VLC_CODEC_MP3 )
215         return VLC_EGENERIC;
216
217     p_dec->fmt_out.i_cat = AUDIO_ES;
218     p_dec->fmt_out.i_codec = VLC_CODEC_FL32;
219
220     /* Initialize libmpg123 */
221     if( InitMPG123() != MPG123_OK )
222         return VLC_EGENERIC;
223
224     /* Allocate the memory needed to store the module's structure */
225     p_sys = p_dec->p_sys = malloc( sizeof(decoder_sys_t) );
226     if( p_sys == NULL )
227         return VLC_ENOMEM;
228
229     /* Create our mpg123 handle */
230     if( ( p_sys->p_handle = mpg123_new( NULL, NULL ) ) == NULL )
231         goto error;
232
233     /* Open a new bitstream */
234     if( mpg123_open_feed( p_sys->p_handle ) != MPG123_OK )
235     {
236         msg_Err( p_this, "mpg123 error: can't open feed" );
237         goto error;
238     }
239
240     /* Disable resync stream after error */
241     mpg123_param( p_sys->p_handle, MPG123_ADD_FLAGS, MPG123_NO_RESYNC, 0 );
242
243     /* Setup output format */
244     mpg123_format_none( p_sys->p_handle );
245
246     if( MPG123_OK != mpg123_format( p_sys->p_handle,
247                                     p_dec->fmt_in.audio.i_rate,
248                                     MPG123_MONO | MPG123_STEREO,
249                                     MPG123_ENC_FLOAT_32 ) )
250     {
251         msg_Err( p_this, "mpg123 error: %s",
252                 mpg123_strerror( p_sys->p_handle ) );
253         mpg123_close( p_sys->p_handle );
254         goto error;
255     }
256
257     p_dec->fmt_out.audio.i_rate = 0; /* So end_date gets initialized */
258     p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
259     p_dec->pf_decode_audio = DecodeBlock;
260
261     msg_Dbg( p_this, "%4.4s->%4.4s, bits per sample: %i",
262              (char *)&p_dec->fmt_in.i_codec,
263              (char *)&p_dec->fmt_out.i_codec,
264              aout_BitsPerSample( p_dec->fmt_out.i_codec ) );
265
266     return VLC_SUCCESS;
267 error:
268     mpg123_delete( p_sys->p_handle );
269     ExitMPG123();
270     free( p_sys );
271     return VLC_EGENERIC;
272 }
273
274 /*****************************************************************************
275  * CloseDecoder : deallocate data structures
276  *****************************************************************************/
277 static void CloseDecoder( vlc_object_t *p_this )
278 {
279     decoder_t *p_dec = (decoder_t *)p_this;
280     decoder_sys_t *p_sys = p_dec->p_sys;
281
282     mpg123_close( p_sys->p_handle );
283     mpg123_delete( p_sys->p_handle );
284     ExitMPG123();
285     free( p_sys );
286 }
287
288 /*****************************************************************************
289  * InitMPG123 : initialize the mpg123 library (reentrant)
290  *****************************************************************************/
291 static int InitMPG123( void )
292 {
293     int i_ret;
294     vlc_mutex_lock( &mpg123_mutex );
295     if( mpg123_refcount > 0 )
296     {
297         mpg123_refcount++;
298         vlc_mutex_unlock( &mpg123_mutex );
299         return MPG123_OK;
300     }
301     if( ( i_ret = mpg123_init() ) == MPG123_OK )
302         mpg123_refcount++;
303     vlc_mutex_unlock( &mpg123_mutex );
304     return i_ret;
305 }
306
307 /*****************************************************************************
308  * ExitMPG123 : close down the mpg123 library (reentrant)
309  *****************************************************************************/
310 static void ExitMPG123( void )
311 {
312     vlc_mutex_lock( &mpg123_mutex );
313     mpg123_refcount--;
314     if( mpg123_refcount == 0 )
315         mpg123_exit();
316     vlc_mutex_unlock( &mpg123_mutex );
317 }