]> git.sesse.net Git - vlc/blob - modules/demux/au.c
* include/input_ext-intf.h : added stream_t member to input_thread_t.
[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.7 2003/09/12 16:26:40 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     au_t            au;
96     WAVEFORMATEX    wf;
97
98     mtime_t         i_time;
99
100     es_descriptor_t *p_es;
101
102     int             i_frame_size;
103     mtime_t         i_frame_length;
104 };
105
106
107 /*****************************************************************************
108  * Open: check file and initializes structures
109  *****************************************************************************/
110 static int Open( vlc_object_t * p_this )
111 {
112     input_thread_t *p_input = (input_thread_t *)p_this;
113     demux_sys_t    *p_sys;
114
115     uint8_t         *p_peek;
116
117     vlc_fourcc_t    i_fourcc;
118
119     int             i_cat;
120
121     /* a little test to see if it's a au file */
122     if( input_Peek( p_input, &p_peek, 4 ) < 4 )
123     {
124         msg_Warn( p_input, "AU module discarded (cannot peek)" );
125         return VLC_EGENERIC;
126     }
127     if( strncmp( p_peek, ".snd", 4 ) )
128     {
129         msg_Warn( p_input, "AU module discarded (not a valid file)" );
130         return VLC_EGENERIC;
131     }
132
133     p_input->p_demux_data = p_sys = malloc( sizeof( demux_sys_t ) );
134     p_sys->i_time = 0;
135
136     /* skip signature */
137     stream_Read( p_input->s, NULL, 4 );   /* cannot fail */
138
139     /* read header */
140     if( stream_Read( p_input->s, &p_sys->au, sizeof(au_t) )<(int)sizeof(au_t) )
141     {
142         msg_Err( p_input, "cannot load header" );
143         goto error;
144     }
145     p_sys->au.i_header_size   = GetDWBE( &p_sys->au.i_header_size );
146     p_sys->au.i_data_size     = GetDWBE( &p_sys->au.i_data_size );
147     p_sys->au.i_encoding      = GetDWBE( &p_sys->au.i_encoding );
148     p_sys->au.i_sample_rate   = GetDWBE( &p_sys->au.i_sample_rate );
149     p_sys->au.i_channels      = GetDWBE( &p_sys->au.i_channels );
150
151     msg_Dbg( p_input,
152              "au file: header_size=%d data_size=%d encoding=0x%x sample_rate=%d channels=%d",
153              p_sys->au.i_header_size,
154              p_sys->au.i_data_size,
155              p_sys->au.i_encoding,
156              p_sys->au.i_sample_rate,
157              p_sys->au.i_channels );
158
159     if( p_sys->au.i_header_size < 24 )
160     {
161         msg_Warn( p_input, "AU module discarded (not a valid file)" );
162         goto error;
163     }
164
165     /* skip extra header data */
166     if( p_sys->au.i_header_size > 4 + sizeof( au_t ) )
167     {
168         stream_Read( p_input->s,
169                      NULL, p_sys->au.i_header_size - 4 - sizeof( au_t ) );
170     }
171
172     /* Create WAVEFORMATEX structure */
173     p_sys->wf.nChannels     = p_sys->au.i_channels;
174     p_sys->wf.nSamplesPerSec= p_sys->au.i_sample_rate;
175     p_sys->wf.cbSize        = 0;
176
177     switch( p_sys->au.i_encoding )
178     {
179         case AU_ALAW_8:        /* 8-bit ISDN A-law */
180             p_sys->wf.wFormatTag     = WAVE_FORMAT_ALAW;   // FIXME ??
181             p_sys->wf.wBitsPerSample = 8;
182             p_sys->wf.nBlockAlign    = 1 * p_sys->wf.nChannels;
183             i_fourcc                 = VLC_FOURCC( 'a','l','a','w' );
184             i_cat                    = AU_CAT_PCM;
185             break;
186
187         case AU_MULAW_8:       /* 8-bit ISDN u-law */
188             p_sys->wf.wFormatTag     = WAVE_FORMAT_MULAW;   // FIXME ??
189             p_sys->wf.wBitsPerSample = 8;
190             p_sys->wf.nBlockAlign    = 1 * p_sys->wf.nChannels;
191             i_fourcc                 = VLC_FOURCC( 'u','l','a','w' );
192             i_cat                    = AU_CAT_PCM;
193             break;
194
195         case AU_LINEAR_8:      /* 8-bit linear PCM */
196             p_sys->wf.wFormatTag     = WAVE_FORMAT_PCM;
197             p_sys->wf.wBitsPerSample = 8;
198             p_sys->wf.nBlockAlign    = 1 * p_sys->wf.nChannels;
199             i_fourcc                 = VLC_FOURCC( 't','w','o','s' );
200             i_cat                    = AU_CAT_PCM;
201             break;
202
203         case AU_LINEAR_16:     /* 16-bit linear PCM */
204             p_sys->wf.wFormatTag     = WAVE_FORMAT_PCM;
205             p_sys->wf.wBitsPerSample = 16;
206             p_sys->wf.nBlockAlign    = 2 * 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_24:     /* 24-bit linear PCM */
212             p_sys->wf.wFormatTag     = WAVE_FORMAT_PCM;
213             p_sys->wf.wBitsPerSample = 24;
214             p_sys->wf.nBlockAlign    = 3 * 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_32:     /* 32-bit linear PCM */
220             p_sys->wf.wFormatTag     = WAVE_FORMAT_PCM;
221             p_sys->wf.wBitsPerSample = 32;
222             p_sys->wf.nBlockAlign    = 4 * 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_FLOAT:         /* 32-bit IEEE floating point */
228             p_sys->wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
229             p_sys->wf.wBitsPerSample = 32;
230             p_sys->wf.nBlockAlign    = 4 * p_sys->wf.nChannels;
231             i_fourcc                  = VLC_FOURCC( 'a', 'u', 0, AU_FLOAT );
232             i_cat                    = AU_CAT_PCM;
233             break;
234
235         case AU_DOUBLE:        /* 64-bit IEEE floating point */
236             p_sys->wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
237             p_sys->wf.wBitsPerSample = 64;
238             p_sys->wf.nBlockAlign    = 8 * p_sys->wf.nChannels;
239             i_fourcc                 = VLC_FOURCC( 'a', 'u', 0, AU_DOUBLE );
240             i_cat                    = AU_CAT_PCM;
241             break;
242
243         case AU_ADPCM_G721:    /* 4-bit CCITT g.721 ADPCM */
244             p_sys->wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
245             p_sys->wf.wBitsPerSample = 0;
246             p_sys->wf.nBlockAlign    = 0 * p_sys->wf.nChannels;
247             i_fourcc                 = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G721 );
248             i_cat                    = AU_CAT_ADPCM;
249             break;
250
251         case AU_ADPCM_G722:    /* CCITT g.722 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_G722 );
256             i_cat                    = AU_CAT_ADPCM;
257             break;
258
259         case AU_ADPCM_G723_3:  /* CCITT g.723 3-bit 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_G723_3 );
264             i_cat                    = AU_CAT_ADPCM;
265             break;
266
267         case AU_ADPCM_G723_5:  /* CCITT g.723 5-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_5 );
272             i_cat                    = AU_CAT_ADPCM;
273             break;
274
275         default:
276             msg_Warn( p_input, "unknow encoding=0x%x", p_sys->au.i_encoding );
277             i_cat                    = AU_CAT_UNKNOWN;
278             goto error;
279     }
280     p_sys->wf.nAvgBytesPerSec        = p_sys->wf.nSamplesPerSec * p_sys->wf.nChannels * p_sys->wf.wBitsPerSample / 8;
281
282
283
284     if( i_cat == AU_CAT_UNKNOWN || i_cat == AU_CAT_ADPCM )
285     {
286         p_sys->i_frame_size = 0;
287         p_sys->i_frame_length = 0;
288
289         msg_Err( p_input, "unsupported codec/type (Please report it)" );
290         goto error;
291     }
292     else
293     {
294         int i_samples, i_modulo;
295
296         /* read samples for 50ms of */
297         i_samples = __MAX( p_sys->wf.nSamplesPerSec / 20, 1 );
298
299         p_sys->i_frame_size = i_samples * p_sys->wf.nChannels * ( (p_sys->wf.wBitsPerSample + 7) / 8 );
300
301         if( p_sys->wf.nBlockAlign > 0 )
302         {
303             if( ( i_modulo = p_sys->i_frame_size % p_sys->wf.nBlockAlign ) != 0 )
304             {
305                 p_sys->i_frame_size += p_sys->wf.nBlockAlign - i_modulo;
306             }
307         }
308
309         p_sys->i_frame_length = (mtime_t)1000000 *
310                                 (mtime_t)i_samples /
311                                 (mtime_t)p_sys->wf.nSamplesPerSec;
312
313         p_input->pf_demux = DemuxPCM;
314         p_input->pf_demux_control = demux_vaControlDefault;
315     }
316
317     /*  create one program */
318     vlc_mutex_lock( &p_input->stream.stream_lock );
319     if( input_InitStream( p_input, 0 ) == -1)
320     {
321         vlc_mutex_unlock( &p_input->stream.stream_lock );
322         msg_Err( p_input, "cannot init stream" );
323         goto error;
324     }
325     if( input_AddProgram( p_input, 0, 0) == NULL )
326     {
327         vlc_mutex_unlock( &p_input->stream.stream_lock );
328         msg_Err( p_input, "cannot add program" );
329         goto error;
330     }
331
332     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
333     p_input->stream.i_mux_rate =  p_sys->wf.nAvgBytesPerSec / 50;
334
335     p_sys->p_es = input_AddES( p_input, p_input->stream.p_selected_program,
336                                0x01, AUDIO_ES, NULL, 0 );
337
338     p_sys->p_es->i_stream_id   = 0x01;
339     p_sys->p_es->i_fourcc      = i_fourcc;
340     p_sys->p_es->p_waveformatex= malloc( sizeof( WAVEFORMATEX ) );
341     memcpy( p_sys->p_es->p_waveformatex, &p_sys->wf, sizeof( WAVEFORMATEX ) );
342
343     input_SelectES( p_input, p_sys->p_es );
344
345     p_input->stream.p_selected_program->b_is_ok = 1;
346     vlc_mutex_unlock( &p_input->stream.stream_lock );
347
348     return VLC_SUCCESS;
349
350 error:
351     free( p_sys );
352     return VLC_EGENERIC;
353 }
354
355 /*****************************************************************************
356  * DemuxPCM: read packet and send them to decoders
357  *****************************************************************************
358  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
359  *****************************************************************************/
360 static int DemuxPCM( input_thread_t *p_input )
361 {
362     demux_sys_t  *p_sys = p_input->p_demux_data;
363     pes_packet_t *p_pes;
364
365     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
366     {
367         int64_t i_pos = stream_Tell( p_input->s );
368
369         if( p_sys->wf.nBlockAlign != 0 )
370         {
371             i_pos += p_sys->wf.nBlockAlign - i_pos % p_sys->wf.nBlockAlign;
372             if( stream_Seek( p_input->s, i_pos ) )
373             {
374                 msg_Err( p_input, "Seek failed(cannot resync)" );
375             }
376         }
377     }
378
379     input_ClockManageRef( p_input,
380                           p_input->stream.p_selected_program,
381                           p_sys->i_time * 9 / 100 );
382
383     if( ( p_pes = stream_PesPacket( p_input->s, p_sys->i_frame_size ) )==NULL )
384     {
385         msg_Warn( p_input, "cannot read data" );
386         return 0;
387     }
388     p_pes->i_dts =
389     p_pes->i_pts = input_ClockGetTS( p_input,
390                                      p_input->stream.p_selected_program,
391                                      p_sys->i_time * 9 / 100 );
392
393     if( !p_sys->p_es->p_decoder_fifo )
394     {
395         msg_Err( p_input, "no audio decoder" );
396         input_DeletePES( p_input->p_method_data, p_pes );
397         return( -1 );
398     }
399
400     input_DecodePES( p_sys->p_es->p_decoder_fifo, p_pes );
401     p_sys->i_time += p_sys->i_frame_length;
402     return( 1 );
403 }
404
405 /*****************************************************************************
406  * Close: frees unused data
407  *****************************************************************************/
408 static void Close( vlc_object_t * p_this )
409 {
410     input_thread_t *p_input = (input_thread_t *)p_this;
411     demux_sys_t    *p_sys = p_input->p_demux_data;
412
413     free( p_sys );
414 }
415