]> git.sesse.net Git - vlc/blob - modules/demux/au.c
* all : demuxers *have to* set pf_demux_control. (demux_vaControlDefault
[vlc] / modules / demux / au.c
1 /*****************************************************************************
2  * au.c : au file input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001-2003 VideoLAN
5  * $Id: au.c,v 1.6 2003/09/07 22:48:29 fenrir Exp $
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28
29 #include <vlc/vlc.h>
30 #include <vlc/input.h>
31
32 #include <codecs.h>
33
34 /*****************************************************************************
35  * Module descriptor
36  *****************************************************************************/
37 static int  Open    ( vlc_object_t * );
38 static void Close  ( vlc_object_t * );
39
40 vlc_module_begin();
41     set_description( _("AU demuxer") );
42     set_capability( "demux", 142 );
43     set_callbacks( Open, Close );
44 vlc_module_end();
45
46 /*
47  * TODO:
48  *  - all adpcm things (I _NEED_ samples)
49  */
50
51 /*****************************************************************************
52  * Local prototypes
53  *****************************************************************************/
54 static int    DemuxPCM   ( input_thread_t * );
55 /* TODO static int    DemuxADPCM   ( input_thread_t * ); */
56
57 enum AuType_e
58 {
59     AU_UNKNOWN      =  0,
60     AU_MULAW_8      =  1,  /* 8-bit ISDN u-law */
61     AU_LINEAR_8     =  2,  /* 8-bit linear PCM */
62     AU_LINEAR_16    =  3,  /* 16-bit linear PCM */
63     AU_LINEAR_24    =  4,  /* 24-bit linear PCM */
64     AU_LINEAR_32    =  5,  /* 32-bit linear PCM */
65     AU_FLOAT        =  6,  /* 32-bit IEEE floating point */
66     AU_DOUBLE       =  7,  /* 64-bit IEEE floating point */
67     AU_ADPCM_G721   =  23, /* 4-bit CCITT g.721 ADPCM */
68     AU_ADPCM_G722   =  24, /* CCITT g.722 ADPCM */
69     AU_ADPCM_G723_3 =  25, /* CCITT g.723 3-bit ADPCM */
70     AU_ADPCM_G723_5 =  26, /* CCITT g.723 5-bit ADPCM */
71     AU_ALAW_8       =  27  /* 8-bit ISDN A-law */
72 };
73
74 enum AuCat_e
75 {
76     AU_CAT_UNKNOWN  = 0,
77     AU_CAT_PCM      = 1,
78     AU_CAT_ADPCM    = 2
79 };
80
81 typedef struct
82 #ifdef HAVE_ATTRIBUTE_PACKED
83     __attribute__((__packed__))
84 #endif
85 {
86     uint32_t    i_header_size;
87     uint32_t    i_data_size;
88     uint32_t    i_encoding;
89     uint32_t    i_sample_rate;
90     uint32_t    i_channels;
91 } au_t;
92
93 struct demux_sys_t
94 {
95     stream_t        *s;
96
97     au_t            au;
98     WAVEFORMATEX    wf;
99
100     mtime_t         i_time;
101
102     es_descriptor_t *p_es;
103
104     int             i_frame_size;
105     mtime_t         i_frame_length;
106 };
107
108
109 /*****************************************************************************
110  * Open: check file and initializes structures
111  *****************************************************************************/
112 static int Open( vlc_object_t * p_this )
113 {
114     input_thread_t *p_input = (input_thread_t *)p_this;
115     demux_sys_t    *p_sys;
116
117     uint8_t         *p_peek;
118
119     vlc_fourcc_t    i_fourcc;
120
121     int             i_cat;
122
123     /* a little test to see if it's a au file */
124     if( input_Peek( p_input, &p_peek, 4 ) < 4 )
125     {
126         msg_Warn( p_input, "AU module discarded (cannot peek)" );
127         return VLC_EGENERIC;
128     }
129     if( strncmp( p_peek, ".snd", 4 ) )
130     {
131         msg_Warn( p_input, "AU module discarded (not a valid file)" );
132         return VLC_EGENERIC;
133     }
134
135     p_input->p_demux_data = p_sys = malloc( sizeof( demux_sys_t ) );
136     p_sys->i_time = 0;
137
138
139     if( ( p_sys->s = stream_OpenInput( p_input ) ) == NULL )
140     {
141         msg_Err( p_input, "cannot create stream" );
142         goto error;
143     }
144
145     /* skip signature */
146     stream_Read( p_sys->s, NULL, 4 );   /* cannot fail */
147
148     /* read header */
149     if( stream_Read( p_sys->s, &p_sys->au, sizeof( au_t ) ) < (int)sizeof( au_t ) )
150     {
151         msg_Err( p_input, "cannot load header" );
152         goto error;
153     }
154     p_sys->au.i_header_size   = GetDWBE( &p_sys->au.i_header_size );
155     p_sys->au.i_data_size     = GetDWBE( &p_sys->au.i_data_size );
156     p_sys->au.i_encoding      = GetDWBE( &p_sys->au.i_encoding );
157     p_sys->au.i_sample_rate   = GetDWBE( &p_sys->au.i_sample_rate );
158     p_sys->au.i_channels      = GetDWBE( &p_sys->au.i_channels );
159
160     msg_Dbg( p_input,
161              "au file: header_size=%d data_size=%d encoding=0x%x sample_rate=%d channels=%d",
162              p_sys->au.i_header_size,
163              p_sys->au.i_data_size,
164              p_sys->au.i_encoding,
165              p_sys->au.i_sample_rate,
166              p_sys->au.i_channels );
167
168     if( p_sys->au.i_header_size < 24 )
169     {
170         msg_Warn( p_input, "AU module discarded (not a valid file)" );
171         goto error;
172     }
173
174     /* skip extra header data */
175     if( p_sys->au.i_header_size > 4 + sizeof( au_t ) )
176     {
177         stream_Read( p_sys->s, NULL, p_sys->au.i_header_size - 4 - sizeof( au_t ) );
178     }
179
180     /* Create WAVEFORMATEX structure */
181     p_sys->wf.nChannels     = p_sys->au.i_channels;
182     p_sys->wf.nSamplesPerSec= p_sys->au.i_sample_rate;
183     p_sys->wf.cbSize        = 0;
184
185     switch( p_sys->au.i_encoding )
186     {
187         case AU_ALAW_8:        /* 8-bit ISDN A-law */
188             p_sys->wf.wFormatTag     = WAVE_FORMAT_ALAW;   // FIXME ??
189             p_sys->wf.wBitsPerSample = 8;
190             p_sys->wf.nBlockAlign    = 1 * p_sys->wf.nChannels;
191             i_fourcc                 = VLC_FOURCC( 'a','l','a','w' );
192             i_cat                    = AU_CAT_PCM;
193             break;
194
195         case AU_MULAW_8:       /* 8-bit ISDN u-law */
196             p_sys->wf.wFormatTag     = WAVE_FORMAT_MULAW;   // FIXME ??
197             p_sys->wf.wBitsPerSample = 8;
198             p_sys->wf.nBlockAlign    = 1 * p_sys->wf.nChannels;
199             i_fourcc                 = VLC_FOURCC( 'u','l','a','w' );
200             i_cat                    = AU_CAT_PCM;
201             break;
202
203         case AU_LINEAR_8:      /* 8-bit linear PCM */
204             p_sys->wf.wFormatTag     = WAVE_FORMAT_PCM;
205             p_sys->wf.wBitsPerSample = 8;
206             p_sys->wf.nBlockAlign    = 1 * p_sys->wf.nChannels;
207             i_fourcc                 = VLC_FOURCC( 't','w','o','s' );
208             i_cat                    = AU_CAT_PCM;
209             break;
210
211         case AU_LINEAR_16:     /* 16-bit linear PCM */
212             p_sys->wf.wFormatTag     = WAVE_FORMAT_PCM;
213             p_sys->wf.wBitsPerSample = 16;
214             p_sys->wf.nBlockAlign    = 2 * p_sys->wf.nChannels;
215             i_fourcc                 = VLC_FOURCC( 't','w','o','s' );
216             i_cat                    = AU_CAT_PCM;
217             break;
218
219         case AU_LINEAR_24:     /* 24-bit linear PCM */
220             p_sys->wf.wFormatTag     = WAVE_FORMAT_PCM;
221             p_sys->wf.wBitsPerSample = 24;
222             p_sys->wf.nBlockAlign    = 3 * p_sys->wf.nChannels;
223             i_fourcc                 = VLC_FOURCC( 't','w','o','s' );
224             i_cat                    = AU_CAT_PCM;
225             break;
226
227         case AU_LINEAR_32:     /* 32-bit linear PCM */
228             p_sys->wf.wFormatTag     = WAVE_FORMAT_PCM;
229             p_sys->wf.wBitsPerSample = 32;
230             p_sys->wf.nBlockAlign    = 4 * p_sys->wf.nChannels;
231             i_fourcc                 = VLC_FOURCC( 't','w','o','s' );
232             i_cat                    = AU_CAT_PCM;
233             break;
234
235         case AU_FLOAT:         /* 32-bit IEEE floating point */
236             p_sys->wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
237             p_sys->wf.wBitsPerSample = 32;
238             p_sys->wf.nBlockAlign    = 4 * p_sys->wf.nChannels;
239             i_fourcc                  = VLC_FOURCC( 'a', 'u', 0, AU_FLOAT );
240             i_cat                    = AU_CAT_PCM;
241             break;
242
243         case AU_DOUBLE:        /* 64-bit IEEE floating point */
244             p_sys->wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
245             p_sys->wf.wBitsPerSample = 64;
246             p_sys->wf.nBlockAlign    = 8 * p_sys->wf.nChannels;
247             i_fourcc                 = VLC_FOURCC( 'a', 'u', 0, AU_DOUBLE );
248             i_cat                    = AU_CAT_PCM;
249             break;
250
251         case AU_ADPCM_G721:    /* 4-bit CCITT g.721 ADPCM */
252             p_sys->wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
253             p_sys->wf.wBitsPerSample = 0;
254             p_sys->wf.nBlockAlign    = 0 * p_sys->wf.nChannels;
255             i_fourcc                 = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G721 );
256             i_cat                    = AU_CAT_ADPCM;
257             break;
258
259         case AU_ADPCM_G722:    /* CCITT g.722 ADPCM */
260             p_sys->wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
261             p_sys->wf.wBitsPerSample = 0;
262             p_sys->wf.nBlockAlign    = 0 * p_sys->wf.nChannels;
263             i_fourcc                 = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G722 );
264             i_cat                    = AU_CAT_ADPCM;
265             break;
266
267         case AU_ADPCM_G723_3:  /* CCITT g.723 3-bit ADPCM */
268             p_sys->wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
269             p_sys->wf.wBitsPerSample = 0;
270             p_sys->wf.nBlockAlign    = 0 * p_sys->wf.nChannels;
271             i_fourcc                 = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_3 );
272             i_cat                    = AU_CAT_ADPCM;
273             break;
274
275         case AU_ADPCM_G723_5:  /* CCITT g.723 5-bit ADPCM */
276             p_sys->wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
277             p_sys->wf.wBitsPerSample = 0;
278             p_sys->wf.nBlockAlign    = 0 * p_sys->wf.nChannels;
279             i_fourcc                 = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_5 );
280             i_cat                    = AU_CAT_ADPCM;
281             break;
282
283         default:
284             msg_Warn( p_input, "unknow encoding=0x%x", p_sys->au.i_encoding );
285             i_cat                    = AU_CAT_UNKNOWN;
286             goto error;
287     }
288     p_sys->wf.nAvgBytesPerSec        = p_sys->wf.nSamplesPerSec * p_sys->wf.nChannels * p_sys->wf.wBitsPerSample / 8;
289
290
291
292     if( i_cat == AU_CAT_UNKNOWN || i_cat == AU_CAT_ADPCM )
293     {
294         p_sys->i_frame_size = 0;
295         p_sys->i_frame_length = 0;
296
297         msg_Err( p_input, "unsupported codec/type (Please report it)" );
298         goto error;
299     }
300     else
301     {
302         int i_samples, i_modulo;
303
304         /* read samples for 50ms of */
305         i_samples = __MAX( p_sys->wf.nSamplesPerSec / 20, 1 );
306
307         p_sys->i_frame_size = i_samples * p_sys->wf.nChannels * ( (p_sys->wf.wBitsPerSample + 7) / 8 );
308
309         if( p_sys->wf.nBlockAlign > 0 )
310         {
311             if( ( i_modulo = p_sys->i_frame_size % p_sys->wf.nBlockAlign ) != 0 )
312             {
313                 p_sys->i_frame_size += p_sys->wf.nBlockAlign - i_modulo;
314             }
315         }
316
317         p_sys->i_frame_length = (mtime_t)1000000 *
318                                 (mtime_t)i_samples /
319                                 (mtime_t)p_sys->wf.nSamplesPerSec;
320
321         p_input->pf_demux = DemuxPCM;
322         p_input->pf_demux_control = demux_vaControlDefault;
323     }
324
325     /*  create one program */
326     vlc_mutex_lock( &p_input->stream.stream_lock );
327     if( input_InitStream( p_input, 0 ) == -1)
328     {
329         vlc_mutex_unlock( &p_input->stream.stream_lock );
330         msg_Err( p_input, "cannot init stream" );
331         goto error;
332     }
333     if( input_AddProgram( p_input, 0, 0) == NULL )
334     {
335         vlc_mutex_unlock( &p_input->stream.stream_lock );
336         msg_Err( p_input, "cannot add program" );
337         goto error;
338     }
339
340     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
341     p_input->stream.i_mux_rate =  p_sys->wf.nAvgBytesPerSec / 50;
342
343     p_sys->p_es = input_AddES( p_input, p_input->stream.p_selected_program,
344                                0x01, AUDIO_ES, NULL, 0 );
345
346     p_sys->p_es->i_stream_id   = 0x01;
347     p_sys->p_es->i_fourcc      = i_fourcc;
348     p_sys->p_es->p_waveformatex= malloc( sizeof( WAVEFORMATEX ) );
349     memcpy( p_sys->p_es->p_waveformatex, &p_sys->wf, sizeof( WAVEFORMATEX ) );
350
351     input_SelectES( p_input, p_sys->p_es );
352
353     p_input->stream.p_selected_program->b_is_ok = 1;
354     vlc_mutex_unlock( &p_input->stream.stream_lock );
355
356     return VLC_SUCCESS;
357
358 error:
359     if( p_sys->s )
360     {
361         stream_Release( p_sys->s );
362     }
363     free( p_sys );
364     return VLC_EGENERIC;
365 }
366
367 /*****************************************************************************
368  * DemuxPCM: read packet and send them to decoders
369  *****************************************************************************
370  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
371  *****************************************************************************/
372 static int DemuxPCM( input_thread_t *p_input )
373 {
374     demux_sys_t  *p_sys = p_input->p_demux_data;
375     pes_packet_t *p_pes;
376
377     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
378     {
379         int64_t i_pos = stream_Tell( p_sys->s );
380
381         if( p_sys->wf.nBlockAlign != 0 )
382         {
383             i_pos += p_sys->wf.nBlockAlign - i_pos % p_sys->wf.nBlockAlign;
384             if( stream_Seek( p_sys->s, i_pos ) )
385             {
386                 msg_Err( p_input, "Seek failed(cannot resync)" );
387             }
388         }
389     }
390
391     input_ClockManageRef( p_input,
392                           p_input->stream.p_selected_program,
393                           p_sys->i_time * 9 / 100 );
394
395     if( ( p_pes = stream_PesPacket( p_sys->s, p_sys->i_frame_size ) ) == NULL )
396     {
397         msg_Warn( p_input, "cannot read data" );
398         return 0;
399     }
400     p_pes->i_dts =
401     p_pes->i_pts = input_ClockGetTS( p_input,
402                                      p_input->stream.p_selected_program,
403                                      p_sys->i_time * 9 / 100 );
404
405     if( !p_sys->p_es->p_decoder_fifo )
406     {
407         msg_Err( p_input, "no audio decoder" );
408         input_DeletePES( p_input->p_method_data, p_pes );
409         return( -1 );
410     }
411
412     input_DecodePES( p_sys->p_es->p_decoder_fifo, p_pes );
413     p_sys->i_time += p_sys->i_frame_length;
414     return( 1 );
415 }
416
417 /*****************************************************************************
418  * Close: frees unused data
419  *****************************************************************************/
420 static void Close( vlc_object_t * p_this )
421 {
422     input_thread_t *p_input = (input_thread_t *)p_this;
423     demux_sys_t    *p_sys = p_input->p_demux_data;
424
425     stream_Release( p_sys->s );
426     free( p_sys );
427 }
428