a271dea127d4721d8aa5fd7991ad198a52a1138b
[vlc.git] / modules / demux / au.c
1 /*****************************************************************************
2  * au.c : au file input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001-2007 VLC authors and VideoLAN
5  *
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
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 <limits.h>
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_demux.h>
35
36 /* TODO:
37  *  - all adpcm things (I _NEED_ samples)
38  *  - ...
39  */
40
41 /*****************************************************************************
42  * Module descriptor
43  *****************************************************************************/
44 static int  Open ( vlc_object_t * );
45
46 vlc_module_begin ()
47     set_category( CAT_INPUT )
48     set_subcategory( SUBCAT_INPUT_DEMUX )
49     set_description( N_("AU demuxer") )
50     set_capability( "demux", 10 )
51     set_callback( Open )
52     add_shortcut( "au" )
53     add_file_extension("au")
54 vlc_module_end ()
55
56 /*****************************************************************************
57  * Local prototypes
58  *****************************************************************************/
59 enum AuType_e
60 {
61     AU_UNKNOWN      =  0,
62     AU_MULAW_8      =  1,  /* 8-bit ISDN u-law */
63     AU_LINEAR_8     =  2,  /* 8-bit linear PCM */
64     AU_LINEAR_16    =  3,  /* 16-bit linear PCM */
65     AU_LINEAR_24    =  4,  /* 24-bit linear PCM */
66     AU_LINEAR_32    =  5,  /* 32-bit linear PCM */
67     AU_FLOAT        =  6,  /* 32-bit IEEE floating point */
68     AU_DOUBLE       =  7,  /* 64-bit IEEE floating point */
69     AU_ADPCM_G721   =  23, /* 4-bit CCITT g.721 ADPCM */
70     AU_ADPCM_G722   =  24, /* CCITT g.722 ADPCM */
71     AU_ADPCM_G723_3 =  25, /* CCITT g.723 3-bit ADPCM */
72     AU_ADPCM_G723_5 =  26, /* CCITT g.723 5-bit ADPCM */
73     AU_ALAW_8       =  27  /* 8-bit ISDN A-law */
74 };
75
76 enum AuCat_e
77 {
78     AU_CAT_UNKNOWN  = 0,
79     AU_CAT_PCM      = 1,
80     AU_CAT_ADPCM    = 2
81 };
82
83 typedef struct
84 {
85     es_format_t     fmt;
86     es_out_id_t     *es;
87
88     vlc_tick_t      i_time;
89
90     int             i_frame_size;
91     vlc_tick_t      i_frame_length;
92
93     uint32_t        i_header_size;
94 } demux_sys_t;
95
96 static int Demux( demux_t * );
97 static int Control ( demux_t *, int i_query, va_list args );
98
99 /*****************************************************************************
100  * Open: check file and initializes structures
101  *****************************************************************************/
102 static int Open( vlc_object_t *p_this )
103 {
104     demux_t     *p_demux = (demux_t*)p_this;
105
106     uint8_t      hdr[20];
107     const uint8_t *p_peek;
108     int          i_cat;
109
110     if( vlc_stream_Peek( p_demux->s , &p_peek, 4 ) < 4 )
111         return VLC_EGENERIC;
112
113     if( memcmp( p_peek, ".snd", 4 ) )
114         return VLC_EGENERIC;
115
116     /* skip signature */
117     if( vlc_stream_Read( p_demux->s, NULL, 4 ) < 4 )
118         return VLC_EGENERIC;
119
120     /* read header */
121     if( vlc_stream_Read( p_demux->s, hdr, 20 ) < 20 )
122     {
123         msg_Err( p_demux, "cannot read" );
124         return VLC_EGENERIC;
125     }
126
127     if( GetDWBE( &hdr[0]  ) < 24 )
128     {
129         msg_Err( p_demux, "invalid file" );
130         return VLC_EGENERIC;
131     }
132
133     demux_sys_t *p_sys = vlc_obj_malloc( p_this, sizeof (*p_sys) );
134     if( unlikely(p_sys == NULL) )
135         return VLC_ENOMEM;
136
137     p_sys->i_time = 0;
138     p_sys->i_header_size = GetDWBE( &hdr[0] );
139
140     /* skip extra header data */
141     if( p_sys->i_header_size > 24 )
142     {
143 #if (SSIZE_MAX <= INT32_MAX)
144         if( p_sys->i_header_size > SSIZE_MAX )
145             return VLC_EGENERIC;
146 #endif
147         size_t skip = p_sys->i_header_size - 24;
148         if( vlc_stream_Read( p_demux->s, NULL, skip ) < (ssize_t)skip )
149             return VLC_EGENERIC;
150     }
151
152     /* init fmt */
153     es_format_Init( &p_sys->fmt, AUDIO_ES, 0 );
154     p_sys->fmt.audio.i_rate     = GetDWBE( &hdr[12] );
155     p_sys->fmt.audio.i_channels = GetDWBE( &hdr[16] );
156
157 #if 0
158     p_sys->au.i_header_size   = GetDWBE( &p_sys->au.i_header_size );
159     p_sys->au.i_data_size     = GetDWBE( &p_sys->au.i_data_size );
160     p_sys->au.i_encoding      = GetDWBE( &p_sys->au.i_encoding );
161     p_sys->au.i_sample_rate   = GetDWBE( &p_sys->au.i_sample_rate );
162     p_sys->au.i_channels      = GetDWBE( &p_sys->au.i_channels );
163 #endif
164     switch( GetDWBE( &hdr[8] ) )
165     {
166         case AU_ALAW_8:        /* 8-bit ISDN A-law */
167             p_sys->fmt.i_codec               = VLC_CODEC_ALAW;
168             p_sys->fmt.audio.i_bitspersample = 8;
169             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
170             i_cat                    = AU_CAT_PCM;
171             break;
172
173         case AU_MULAW_8:       /* 8-bit ISDN u-law */
174             p_sys->fmt.i_codec               = VLC_CODEC_MULAW;
175             p_sys->fmt.audio.i_bitspersample = 8;
176             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
177             i_cat                    = AU_CAT_PCM;
178             break;
179
180         case AU_LINEAR_8:      /* 8-bit linear PCM */
181             p_sys->fmt.i_codec               = VLC_CODEC_S8;
182             p_sys->fmt.audio.i_bitspersample = 8;
183             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
184             i_cat                    = AU_CAT_PCM;
185             break;
186
187         case AU_LINEAR_16:     /* 16-bit linear PCM */
188             p_sys->fmt.i_codec               = VLC_CODEC_S16B;
189             p_sys->fmt.audio.i_bitspersample = 16;
190             p_sys->fmt.audio.i_blockalign    = 2 * p_sys->fmt.audio.i_channels;
191             i_cat                    = AU_CAT_PCM;
192             break;
193
194         case AU_LINEAR_24:     /* 24-bit linear PCM */
195             p_sys->fmt.i_codec               = VLC_CODEC_S24B;
196             p_sys->fmt.audio.i_bitspersample = 24;
197             p_sys->fmt.audio.i_blockalign    = 3 * p_sys->fmt.audio.i_channels;
198             i_cat                    = AU_CAT_PCM;
199             break;
200
201         case AU_LINEAR_32:     /* 32-bit linear PCM */
202             p_sys->fmt.i_codec               = VLC_CODEC_S32B;
203             p_sys->fmt.audio.i_bitspersample = 32;
204             p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
205             i_cat                    = AU_CAT_PCM;
206             break;
207
208         case AU_FLOAT:         /* 32-bit IEEE floating point */
209             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_FLOAT );
210             p_sys->fmt.audio.i_bitspersample = 32;
211             p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
212             i_cat                    = AU_CAT_PCM;
213             break;
214
215         case AU_DOUBLE:        /* 64-bit IEEE floating point */
216             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_DOUBLE );
217             p_sys->fmt.audio.i_bitspersample = 64;
218             p_sys->fmt.audio.i_blockalign    = 8 * p_sys->fmt.audio.i_channels;
219             i_cat                    = AU_CAT_PCM;
220             break;
221
222         case AU_ADPCM_G721:    /* 4-bit CCITT g.721 ADPCM */
223             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G721 );
224             p_sys->fmt.audio.i_bitspersample = 0;
225             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
226             i_cat                    = AU_CAT_ADPCM;
227             break;
228
229         case AU_ADPCM_G722:    /* CCITT g.722 ADPCM */
230             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G722 );
231             p_sys->fmt.audio.i_bitspersample = 0;
232             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
233             i_cat                    = AU_CAT_ADPCM;
234             break;
235
236         case AU_ADPCM_G723_3:  /* CCITT g.723 3-bit ADPCM */
237             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_3 );
238             p_sys->fmt.audio.i_bitspersample = 0;
239             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
240             i_cat                    = AU_CAT_ADPCM;
241             break;
242
243         case AU_ADPCM_G723_5:  /* CCITT g.723 5-bit ADPCM */
244             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_5 );
245             p_sys->fmt.audio.i_bitspersample = 0;
246             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
247             i_cat                    = AU_CAT_ADPCM;
248             break;
249
250         default:
251             msg_Warn( p_demux, "unknown encoding=0x%x", GetDWBE( &hdr[8] ) );
252             p_sys->fmt.audio.i_bitspersample = 0;
253             p_sys->fmt.audio.i_blockalign    = 0;
254             i_cat                    = AU_CAT_UNKNOWN;
255             break;
256     }
257
258     p_sys->fmt.i_bitrate = p_sys->fmt.audio.i_rate *
259                            p_sys->fmt.audio.i_channels *
260                            p_sys->fmt.audio.i_bitspersample;
261
262     if( i_cat == AU_CAT_UNKNOWN || i_cat == AU_CAT_ADPCM )
263     {
264         msg_Err( p_demux, "unsupported codec/type (Please report it)" );
265         return VLC_EGENERIC;
266     }
267
268     if( p_sys->fmt.audio.i_rate == 0 )
269     {
270         msg_Err( p_demux, "invalid samplerate: 0" );
271         return VLC_EGENERIC;
272     }
273
274     /* add the es */
275     p_sys->fmt.i_id = 0;
276     p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt );
277     if( unlikely(p_sys->es == NULL) )
278         return VLC_ENOMEM;
279
280     /* calculate 50ms frame size/time */
281     unsigned i_samples = __MAX( p_sys->fmt.audio.i_rate / 20, 1 );
282     p_sys->i_frame_size = i_samples * p_sys->fmt.audio.i_channels *
283                           ( (p_sys->fmt.audio.i_bitspersample + 7) / 8 );
284     if( p_sys->fmt.audio.i_blockalign > 0 )
285     {
286         unsigned mod = p_sys->i_frame_size % p_sys->fmt.audio.i_blockalign;
287         if( mod != 0 )
288         {
289             p_sys->i_frame_size += p_sys->fmt.audio.i_blockalign - mod;
290         }
291     }
292     p_sys->i_frame_length = vlc_tick_from_samples( i_samples,
293                                                    p_sys->fmt.audio.i_rate );
294
295     p_demux->p_sys = p_sys;
296     p_demux->pf_demux = Demux;
297     p_demux->pf_control = Control;
298     return VLC_SUCCESS;
299 }
300
301 /*****************************************************************************
302  * Demux: read packet and send them to decoders
303  *****************************************************************************
304  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
305  *****************************************************************************/
306 static int Demux( demux_t *p_demux )
307 {
308     demux_sys_t *p_sys = p_demux->p_sys;
309     block_t     *p_block;
310
311     /* set PCR */
312     es_out_SetPCR( p_demux->out, VLC_TICK_0 + p_sys->i_time );
313
314     p_block = vlc_stream_Block( p_demux->s, p_sys->i_frame_size );
315     if( p_block == NULL )
316     {
317         msg_Warn( p_demux, "cannot read data" );
318         return VLC_DEMUXER_EOF;
319     }
320
321     p_block->i_dts =
322     p_block->i_pts = VLC_TICK_0 + p_sys->i_time;
323     es_out_Send( p_demux->out, p_sys->es, p_block );
324
325     p_sys->i_time += p_sys->i_frame_length;
326
327     return VLC_DEMUXER_SUCCESS;
328 }
329
330 /*****************************************************************************
331  * Control:
332  *****************************************************************************/
333 static int Control( demux_t *p_demux, int i_query, va_list args )
334 {
335     demux_sys_t *p_sys = p_demux->p_sys;
336
337     return demux_vaControlHelper( p_demux->s, p_sys->i_header_size, -1,
338                                    p_sys->fmt.i_bitrate, p_sys->fmt.audio.i_blockalign,
339                                    i_query, args );
340 }
341