]> git.sesse.net Git - vlc/blob - modules/demux/au.c
Remove stdlib.h
[vlc] / modules / demux / au.c
1 /*****************************************************************************
2  * au.c : au file input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001-2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #include <vlc/vlc.h>
29 #include <vlc_demux.h>
30
31 /* TODO:
32  *  - all adpcm things (I _NEED_ samples)
33  *  - ...
34  */
35
36 /*****************************************************************************
37  * Module descriptor
38  *****************************************************************************/
39 static int  Open ( vlc_object_t * );
40 static void Close( vlc_object_t * );
41
42 vlc_module_begin();
43     set_category( CAT_INPUT );
44     set_subcategory( SUBCAT_INPUT_DEMUX );
45     set_description( _("AU demuxer") );
46     set_capability( "demux2", 10 );
47     set_callbacks( Open, Close );
48     add_shortcut( "au" );
49 vlc_module_end();
50
51 /*****************************************************************************
52  * Local prototypes
53  *****************************************************************************/
54 enum AuType_e
55 {
56     AU_UNKNOWN      =  0,
57     AU_MULAW_8      =  1,  /* 8-bit ISDN u-law */
58     AU_LINEAR_8     =  2,  /* 8-bit linear PCM */
59     AU_LINEAR_16    =  3,  /* 16-bit linear PCM */
60     AU_LINEAR_24    =  4,  /* 24-bit linear PCM */
61     AU_LINEAR_32    =  5,  /* 32-bit linear PCM */
62     AU_FLOAT        =  6,  /* 32-bit IEEE floating point */
63     AU_DOUBLE       =  7,  /* 64-bit IEEE floating point */
64     AU_ADPCM_G721   =  23, /* 4-bit CCITT g.721 ADPCM */
65     AU_ADPCM_G722   =  24, /* CCITT g.722 ADPCM */
66     AU_ADPCM_G723_3 =  25, /* CCITT g.723 3-bit ADPCM */
67     AU_ADPCM_G723_5 =  26, /* CCITT g.723 5-bit ADPCM */
68     AU_ALAW_8       =  27  /* 8-bit ISDN A-law */
69 };
70
71 enum AuCat_e
72 {
73     AU_CAT_UNKNOWN  = 0,
74     AU_CAT_PCM      = 1,
75     AU_CAT_ADPCM    = 2
76 };
77
78 struct demux_sys_t
79 {
80     es_format_t     fmt;
81     es_out_id_t     *es;
82
83     mtime_t         i_time;
84
85     int             i_frame_size;
86     mtime_t         i_frame_length;
87
88     int             i_header_size;
89 };
90
91 static int Demux( demux_t * );
92 static int Control ( demux_t *, int i_query, va_list args );
93
94 /*****************************************************************************
95  * Open: check file and initializes structures
96  *****************************************************************************/
97 static int Open( vlc_object_t *p_this )
98 {
99     demux_t     *p_demux = (demux_t*)p_this;
100     demux_sys_t *p_sys;
101
102     uint8_t      hdr[20];
103     const uint8_t *p_peek;
104     int          i_cat;
105     int          i_samples, i_modulo;
106
107     CHECK_PEEK( p_peek, 4 );
108
109     if( memcmp( p_peek, ".snd", 4 ) )
110     {
111         return VLC_EGENERIC;
112     }
113
114     /* skip signature */
115     stream_Read( p_demux->s, NULL, 4 );   /* cannot fail */
116
117     /* read header */
118     if( stream_Read( p_demux->s, hdr, 20 ) < 20 )
119     {
120         msg_Err( p_demux, "cannot read" );
121         return VLC_EGENERIC;
122     }
123
124     if( GetDWBE( &hdr[0]  ) < 24 )
125     {
126         msg_Err( p_demux, "invalid file" );
127         return VLC_EGENERIC;
128     }
129
130     STANDARD_DEMUX_INIT; p_sys = p_demux->p_sys;
131     p_sys->i_time = 1;
132     p_sys->i_header_size = GetDWBE( &hdr[0] );
133
134     /* skip extra header data */
135     if( p_sys->i_header_size > 24 )
136     {
137         stream_Read( p_demux->s, NULL, p_sys->i_header_size - 24 );
138     }
139
140     /* init fmt */
141     es_format_Init( &p_sys->fmt, AUDIO_ES, 0 );
142     p_sys->fmt.audio.i_rate     = GetDWBE( &hdr[12] );
143     p_sys->fmt.audio.i_channels = GetDWBE( &hdr[16] );
144
145 #if 0
146     p_sys->au.i_header_size   = GetDWBE( &p_sys->au.i_header_size );
147     p_sys->au.i_data_size     = GetDWBE( &p_sys->au.i_data_size );
148     p_sys->au.i_encoding      = GetDWBE( &p_sys->au.i_encoding );
149     p_sys->au.i_sample_rate   = GetDWBE( &p_sys->au.i_sample_rate );
150     p_sys->au.i_channels      = GetDWBE( &p_sys->au.i_channels );
151 #endif
152     switch( GetDWBE( &hdr[8] ) )
153     {
154         case AU_ALAW_8:        /* 8-bit ISDN A-law */
155             p_sys->fmt.i_codec               = VLC_FOURCC( 'a','l','a','w' );
156             p_sys->fmt.audio.i_bitspersample = 8;
157             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
158             i_cat                    = AU_CAT_PCM;
159             break;
160
161         case AU_MULAW_8:       /* 8-bit ISDN u-law */
162             p_sys->fmt.i_codec               = VLC_FOURCC( 'u','l','a','w' );
163             p_sys->fmt.audio.i_bitspersample = 8;
164             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
165             i_cat                    = AU_CAT_PCM;
166             break;
167
168         case AU_LINEAR_8:      /* 8-bit linear PCM */
169             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
170             p_sys->fmt.audio.i_bitspersample = 8;
171             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
172             i_cat                    = AU_CAT_PCM;
173             break;
174
175         case AU_LINEAR_16:     /* 16-bit linear PCM */
176             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
177             p_sys->fmt.audio.i_bitspersample = 16;
178             p_sys->fmt.audio.i_blockalign    = 2 * p_sys->fmt.audio.i_channels;
179             i_cat                    = AU_CAT_PCM;
180             break;
181
182         case AU_LINEAR_24:     /* 24-bit linear PCM */
183             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
184             p_sys->fmt.audio.i_bitspersample = 24;
185             p_sys->fmt.audio.i_blockalign    = 3 * p_sys->fmt.audio.i_channels;
186             i_cat                    = AU_CAT_PCM;
187             break;
188
189         case AU_LINEAR_32:     /* 32-bit linear PCM */
190             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
191             p_sys->fmt.audio.i_bitspersample = 32;
192             p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
193             i_cat                    = AU_CAT_PCM;
194             break;
195
196         case AU_FLOAT:         /* 32-bit IEEE floating point */
197             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_FLOAT );
198             p_sys->fmt.audio.i_bitspersample = 32;
199             p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
200             i_cat                    = AU_CAT_PCM;
201             break;
202
203         case AU_DOUBLE:        /* 64-bit IEEE floating point */
204             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_DOUBLE );
205             p_sys->fmt.audio.i_bitspersample = 64;
206             p_sys->fmt.audio.i_blockalign    = 8 * p_sys->fmt.audio.i_channels;
207             i_cat                    = AU_CAT_PCM;
208             break;
209
210         case AU_ADPCM_G721:    /* 4-bit CCITT g.721 ADPCM */
211             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G721 );
212             p_sys->fmt.audio.i_bitspersample = 0;
213             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
214             i_cat                    = AU_CAT_ADPCM;
215             break;
216
217         case AU_ADPCM_G722:    /* CCITT g.722 ADPCM */
218             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G722 );
219             p_sys->fmt.audio.i_bitspersample = 0;
220             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
221             i_cat                    = AU_CAT_ADPCM;
222             break;
223
224         case AU_ADPCM_G723_3:  /* CCITT g.723 3-bit ADPCM */
225             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_3 );
226             p_sys->fmt.audio.i_bitspersample = 0;
227             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
228             i_cat                    = AU_CAT_ADPCM;
229             break;
230
231         case AU_ADPCM_G723_5:  /* CCITT g.723 5-bit ADPCM */
232             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_5 );
233             p_sys->fmt.audio.i_bitspersample = 0;
234             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
235             i_cat                    = AU_CAT_ADPCM;
236             break;
237
238         default:
239             msg_Warn( p_demux, "unknow encoding=0x%x", GetDWBE( &hdr[8] ) );
240             p_sys->fmt.audio.i_bitspersample = 0;
241             p_sys->fmt.audio.i_blockalign    = 0;
242             i_cat                    = AU_CAT_UNKNOWN;
243             break;
244     }
245
246     p_sys->fmt.i_bitrate = p_sys->fmt.audio.i_rate *
247                            p_sys->fmt.audio.i_channels *
248                            p_sys->fmt.audio.i_bitspersample;
249
250     if( i_cat == AU_CAT_UNKNOWN || i_cat == AU_CAT_ADPCM )
251     {
252         p_sys->i_frame_size = 0;
253         p_sys->i_frame_length = 0;
254
255         msg_Err( p_demux, "unsupported codec/type (Please report it)" );
256         free( p_sys );
257         return VLC_EGENERIC;
258     }
259
260     /* add the es */
261     p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt );
262
263     /* calculate 50ms frame size/time */
264     i_samples = __MAX( p_sys->fmt.audio.i_rate / 20, 1 );
265     p_sys->i_frame_size = i_samples * p_sys->fmt.audio.i_channels *
266                           ( (p_sys->fmt.audio.i_bitspersample + 7) / 8 );
267     if( p_sys->fmt.audio.i_blockalign > 0 )
268     {
269         if( ( i_modulo = p_sys->i_frame_size % p_sys->fmt.audio.i_blockalign ) != 0 )
270         {
271             p_sys->i_frame_size += p_sys->fmt.audio.i_blockalign - i_modulo;
272         }
273     }
274     p_sys->i_frame_length = (mtime_t)1000000 *
275                             (mtime_t)i_samples /
276                             (mtime_t)p_sys->fmt.audio.i_rate;
277
278     return VLC_SUCCESS;
279 }
280
281 /*****************************************************************************
282  * Demux: read packet and send them to decoders
283  *****************************************************************************
284  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
285  *****************************************************************************/
286 static int Demux( demux_t *p_demux )
287 {
288     demux_sys_t *p_sys = p_demux->p_sys;
289     block_t     *p_block;
290
291     /* set PCR */
292     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time );
293
294     if( ( p_block = stream_Block( p_demux->s, p_sys->i_frame_size ) ) == NULL )
295     {
296         msg_Warn( p_demux, "cannot read data" );
297         return 0;
298     }
299
300     p_block->i_dts =
301     p_block->i_pts = p_sys->i_time;
302
303     es_out_Send( p_demux->out, p_sys->es, p_block );
304
305     p_sys->i_time += p_sys->i_frame_length;
306
307     return 1;
308 }
309
310 /*****************************************************************************
311  * Close: frees unused data
312  *****************************************************************************/
313 static void Close( vlc_object_t * p_this )
314 {
315     demux_t     *p_demux = (demux_t*)p_this;
316     demux_sys_t *p_sys = p_demux->p_sys;
317
318     free( p_sys );
319 }
320
321 /*****************************************************************************
322  * Control:
323  *****************************************************************************/
324 static int Control( demux_t *p_demux, int i_query, va_list args )
325 {
326     demux_sys_t *p_sys = p_demux->p_sys;
327
328     return demux2_vaControlHelper( p_demux->s, p_sys->i_header_size, -1,
329                                    p_sys->fmt.i_bitrate, p_sys->fmt.audio.i_blockalign,
330                                    i_query, args );
331 }
332