]> git.sesse.net Git - vlc/blob - modules/demux/au.c
254332a679d0ff0a4490b4af8f10783344ffa2f4
[vlc] / modules / demux / au.c
1 /*****************************************************************************
2  * au.c : au file input module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: au.c,v 1.1 2003/03/11 07:03:16 fenrir Exp $
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 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 General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /*****************************************************************************
24  * Preamble
25  *****************************************************************************/
26 #include <stdlib.h>                                      /* malloc(), free() */
27 #include <string.h>                                              /* strdup() */
28
29 #include <vlc/vlc.h>
30 #include <vlc/input.h>
31
32 #include <codecs.h>
33
34 /*****************************************************************************
35  * Local prototypes
36  *****************************************************************************/
37 static int    AUInit       ( vlc_object_t * );
38 static void   AUEnd        ( vlc_object_t * );
39 static int    AUDemux      ( input_thread_t * );
40
41 static int    AUDemuxPCM   ( input_thread_t * );
42
43 /*****************************************************************************
44  * Module descriptor
45  *****************************************************************************/
46 vlc_module_begin();
47     set_description( _("AU demuxer") );
48     set_capability( "demux", 142 );
49     set_callbacks( AUInit, AUEnd );
50 vlc_module_end();
51
52
53 #define AUDIO_FILE_ENCODING_MULAW_8         1  /* 8-bit ISDN u-law */
54 #define AUDIO_FILE_ENCODING_LINEAR_8        2  /* 8-bit linear PCM */
55 #define AUDIO_FILE_ENCODING_LINEAR_16       3  /* 16-bit linear PCM */
56 #define AUDIO_FILE_ENCODING_LINEAR_24       4  /* 24-bit linear PCM */
57 #define AUDIO_FILE_ENCODING_LINEAR_32       5  /* 32-bit linear PCM */
58 #define AUDIO_FILE_ENCODING_FLOAT           6  /* 32-bit IEEE floating point */
59 #define AUDIO_FILE_ENCODING_DOUBLE          7  /* 64-bit IEEE floating point */
60 #define AUDIO_FILE_ENCODING_ADPCM_G721      23 /* 4-bit CCITT g.721 ADPCM */
61 #define AUDIO_FILE_ENCODING_ADPCM_G722      24 /* CCITT g.722 ADPCM */
62 #define AUDIO_FILE_ENCODING_ADPCM_G723_3    25 /* CCITT g.723 3-bit ADPCM */
63 #define AUDIO_FILE_ENCODING_ADPCM_G723_5    26 /* CCITT g.723 5-bit ADPCM */
64 #define AUDIO_FILE_ENCODING_ALAW_8          27 /* 8-bit ISDN A-law */
65
66 typedef struct
67 {
68     uint32_t    i_header_size;
69     uint32_t    i_data_size;
70     uint32_t    i_encoding;
71     uint32_t    i_sample_rate;
72     uint32_t    i_channels;
73 } au_t;
74
75 #define AU_DEMUX_PCM        0x01
76 #define AU_DEMUX_ADPCM      0x02
77 struct demux_sys_t
78 {
79     au_t            au;
80     WAVEFORMATEX    wf;
81
82     mtime_t         i_time;
83
84     es_descriptor_t *p_es;
85
86     int             i_demux;
87 };
88
89 /*****************************************************************************
90  * Declaration of local function
91  *****************************************************************************/
92
93 #define FREE( p ) if( p ) { free( p ); (p) = NULL; }
94
95 static uint32_t GetDWBE( uint8_t *p_buff )
96 {
97     return( ( p_buff[0] << 24 ) + ( p_buff[1] << 16 ) +
98             ( p_buff[2] <<  8 ) + p_buff[3] );
99 }
100
101
102 static off_t TellAbsolute( input_thread_t *p_input )
103 {
104     off_t i_pos;
105
106     vlc_mutex_lock( &p_input->stream.stream_lock );
107
108     i_pos= p_input->stream.p_selected_area->i_tell;
109
110     vlc_mutex_unlock( &p_input->stream.stream_lock );
111
112     return( i_pos );
113 }
114
115 /* return 1 if success, 0 if fail */
116 static int ReadData( input_thread_t *p_input, uint8_t *p_buff, int i_size )
117 {
118     data_packet_t *p_data;
119
120     int i_count = 0;
121
122     if( !i_size )
123     {
124         return( 0 );
125     }
126
127     do
128     {
129         int i_read;
130
131         i_read = input_SplitBuffer(p_input, &p_data, __MIN( i_size, 1024 ) );
132         if( i_read <= 0 )
133         {
134             return( i_count );
135         }
136         memcpy( p_buff, p_data->p_payload_start, i_read );
137         input_DeletePacket( p_input->p_method_data, p_data );
138
139         p_buff += i_read;
140         i_size -= i_read;
141         i_count += i_read;
142
143     } while( i_size );
144
145     return( i_count );
146 }
147
148 static int SeekAbsolute( input_thread_t *p_input,
149                          off_t i_pos)
150 {
151     int         i_skip;
152
153     i_skip    = i_pos - TellAbsolute( p_input );
154     if( i_skip == 0 )
155     {
156         return( VLC_SUCCESS );
157     }
158     if( i_skip < 0 && !p_input->stream.b_seekable )
159     {
160         return( VLC_EGENERIC );
161     }
162     else if( !p_input->stream.b_seekable ||
163              ( i_skip > 0 && i_skip < 1024 && p_input->stream.i_method != INPUT_METHOD_FILE ) )
164     {
165         while( i_skip > 0 )
166         {
167             uint8_t dummy[1024];
168             int     i_read;
169
170             i_read = ReadData( p_input, dummy, __MIN( i_skip, 1024 ) );
171             if( i_read <= 0 )
172             {
173                 return( VLC_EGENERIC );
174             }
175             i_skip -= i_read;
176         }
177         return( VLC_SUCCESS );
178     }
179     else
180     {
181             input_AccessReinit( p_input );
182             p_input->pf_seek( p_input, i_pos );
183             return( VLC_SUCCESS );
184     }
185 }
186
187 static int SkipBytes( input_thread_t *p_input, int i_skip )
188 {
189     return( SeekAbsolute( p_input, TellAbsolute( p_input ) + i_skip ) );
190 }
191
192 static int ReadPES( input_thread_t *p_input,
193                     pes_packet_t **pp_pes,
194                     int i_size )
195 {
196     pes_packet_t *p_pes;
197
198     *pp_pes = NULL;
199
200     if( !(p_pes = input_NewPES( p_input->p_method_data )) )
201     {
202         msg_Err( p_input, "cannot allocate new PES" );
203         return( VLC_EGENERIC );
204     }
205
206     while( i_size > 0 )
207     {
208         data_packet_t   *p_data;
209         int i_read;
210
211         if( (i_read = input_SplitBuffer( p_input,
212                                          &p_data,
213                                          __MIN( i_size, 1024 ) ) ) <= 0 )
214         {
215             input_DeletePES( p_input->p_method_data, p_pes );
216             return( VLC_EGENERIC );
217         }
218         if( !p_pes->p_first )
219         {
220             p_pes->p_first = p_data;
221             p_pes->i_nb_data = 1;
222             p_pes->i_pes_size = i_read;
223         }
224         else
225         {
226             p_pes->p_last->p_next  = p_data;
227             p_pes->i_nb_data++;
228             p_pes->i_pes_size += i_read;
229         }
230         p_pes->p_last  = p_data;
231         i_size -= i_read;
232     }
233     *pp_pes = p_pes;
234     return( VLC_SUCCESS );
235 }
236
237 /*****************************************************************************
238  * AUInit: check file and initializes structures
239  *****************************************************************************/
240 static int AUInit( vlc_object_t * p_this )
241 {
242     input_thread_t *p_input = (input_thread_t *)p_this;
243     uint8_t  *p_peek;
244
245     au_t            au;
246     WAVEFORMATEX    wf;
247     vlc_fourcc_t    i_codec;
248
249     demux_sys_t     *p_demux;
250     es_descriptor_t *p_es;
251
252
253     /* Initialize access plug-in structures. */
254     if( p_input->i_mtu == 0 )
255     {
256         /* Improve speed. */
257         p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE ;
258     }
259
260     /* a little test to see if it's a wav file */
261     if( input_Peek( p_input, &p_peek, 24 ) < 24 )
262     {
263         msg_Warn( p_input, "AU plugin discarded (cannot peek)" );
264         return( -1 );
265     }
266
267     /* read header */
268     if( strcmp( p_peek, ".snd" ) )
269     {
270         msg_Warn( p_input, "AU plugin discarded (not a valid file)" );
271         return( VLC_EGENERIC );
272     }
273     au.i_header_size   = GetDWBE( &p_peek[0x04] );
274     au.i_data_size     = GetDWBE( &p_peek[0x08] );
275     au.i_encoding      = GetDWBE( &p_peek[0x0c] );
276     au.i_sample_rate   = GetDWBE( &p_peek[0x10] );
277     au.i_channels      = GetDWBE( &p_peek[0x14] );
278     msg_Dbg( p_input,
279              "au file: header_size=%d data_size=%d encoding=0x%x sample_rate=%d channels=%d",
280              au.i_header_size,
281              au.i_data_size,
282              au.i_encoding,
283              au.i_sample_rate,
284              au.i_channels );
285     if( au.i_header_size < 24 )
286     {
287         msg_Warn( p_input, "AU plugin discarded (not a valid file)" );
288         return( VLC_EGENERIC );
289     }
290
291     /* Create WAVEFORMATEX structure */
292     wf.nChannels     = au.i_channels;
293     wf.nSamplesPerSec= au.i_sample_rate;
294     wf.cbSize        = 0;
295
296     switch( au.i_encoding )
297     {
298         case AUDIO_FILE_ENCODING_MULAW_8:       /* 8-bit ISDN u-law */
299             wf.wFormatTag     = WAVE_FORMAT_MULAW;   // FIXME ??
300             wf.wBitsPerSample = 8;
301             wf.nBlockAlign    = 1 * wf.nChannels;
302             i_codec              = VLC_FOURCC( 'u','l','a','w' );
303             break;
304         case AUDIO_FILE_ENCODING_LINEAR_8:      /* 8-bit linear PCM */
305             wf.wFormatTag     = WAVE_FORMAT_PCM;
306             wf.wBitsPerSample = 8;
307             wf.nBlockAlign    = 1 * wf.nChannels;
308             i_codec              = VLC_FOURCC( 't','w','o','s' );
309             break;
310
311         case AUDIO_FILE_ENCODING_LINEAR_16:     /* 16-bit linear PCM */
312             wf.wFormatTag     = WAVE_FORMAT_PCM;
313             wf.wBitsPerSample = 16;
314             wf.nBlockAlign    = 2 * wf.nChannels;
315             i_codec              = VLC_FOURCC( 't','w','o','s' );
316             break;
317
318         case AUDIO_FILE_ENCODING_LINEAR_24:     /* 24-bit linear PCM */
319             wf.wFormatTag     = WAVE_FORMAT_PCM;
320             wf.wBitsPerSample = 24;
321             wf.nBlockAlign    = 3 * wf.nChannels;
322             i_codec              = VLC_FOURCC( 't','w','o','s' );
323             break;
324
325         case AUDIO_FILE_ENCODING_LINEAR_32:     /* 32-bit linear PCM */
326             wf.wFormatTag     = WAVE_FORMAT_PCM;
327             wf.wBitsPerSample = 32;
328             wf.nBlockAlign    = 4 * wf.nChannels;
329             i_codec              = VLC_FOURCC( 't','w','o','s' );
330             break;
331
332         case AUDIO_FILE_ENCODING_FLOAT:         /* 32-bit IEEE floating point */
333             wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
334             wf.wBitsPerSample = 32;
335             wf.nBlockAlign    = 4 * wf.nChannels;
336             i_codec              = VLC_FOURCC( 'a', 'u', 0, AUDIO_FILE_ENCODING_FLOAT );
337             break;
338
339         case AUDIO_FILE_ENCODING_DOUBLE:        /* 64-bit IEEE floating point */
340             wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
341             wf.wBitsPerSample = 64;
342             wf.nBlockAlign    = 8 * wf.nChannels;
343             i_codec              = VLC_FOURCC( 'a', 'u', 0, AUDIO_FILE_ENCODING_DOUBLE );
344             break;
345
346         case AUDIO_FILE_ENCODING_ADPCM_G721:    /* 4-bit CCITT g.721 ADPCM */
347             wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
348             wf.wBitsPerSample = 0;
349             wf.nBlockAlign    = 0 * wf.nChannels;
350             i_codec              = VLC_FOURCC( 'a', 'u', 0, AUDIO_FILE_ENCODING_ADPCM_G721 );
351             break;
352
353         case AUDIO_FILE_ENCODING_ADPCM_G722:    /* CCITT g.722 ADPCM */
354             wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
355             wf.wBitsPerSample = 0;
356             wf.nBlockAlign    = 0 * wf.nChannels;
357             i_codec              = VLC_FOURCC( 'a', 'u', 0, AUDIO_FILE_ENCODING_ADPCM_G722 );
358             break;
359
360         case AUDIO_FILE_ENCODING_ADPCM_G723_3:  /* CCITT g.723 3-bit ADPCM */
361             wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
362             wf.wBitsPerSample = 0;
363             wf.nBlockAlign    = 0 * wf.nChannels;
364             i_codec              = VLC_FOURCC( 'a', 'u', 0, AUDIO_FILE_ENCODING_ADPCM_G723_3 );
365             break;
366
367         case AUDIO_FILE_ENCODING_ADPCM_G723_5:  /* CCITT g.723 5-bit ADPCM */
368             wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
369             wf.wBitsPerSample = 0;
370             wf.nBlockAlign    = 0 * wf.nChannels;
371             i_codec              = VLC_FOURCC( 'a', 'u', 0, AUDIO_FILE_ENCODING_ADPCM_G723_5 );
372             break;
373
374         case AUDIO_FILE_ENCODING_ALAW_8:        /* 8-bit ISDN A-law */
375             wf.wFormatTag     = WAVE_FORMAT_ALAW;   // FIXME ??
376             wf.wBitsPerSample = 8;
377             wf.nBlockAlign    = 1 * wf.nChannels;
378             i_codec              = VLC_FOURCC( 'a','l','a','w' );
379             break;
380
381         default:
382             msg_Warn( p_input, "unknow encoding=0x%x", au.i_encoding );
383             wf.wFormatTag     = WAVE_FORMAT_UNKNOWN;
384             wf.wBitsPerSample = 0;
385             wf.nBlockAlign    = 0 * wf.nChannels;
386             i_codec              = VLC_FOURCC( 'a','u', 0, au.i_encoding );
387             break;
388     }
389     wf.nAvgBytesPerSec        = wf.nSamplesPerSec * wf.nChannels * wf.wBitsPerSample / 8;
390
391     /*  create one program */
392     vlc_mutex_lock( &p_input->stream.stream_lock );
393     if( input_InitStream( p_input, 0 ) == -1)
394     {
395         vlc_mutex_unlock( &p_input->stream.stream_lock );
396         msg_Err( p_input, "cannot init stream" );
397         return( VLC_EGENERIC );
398     }
399     if( input_AddProgram( p_input, 0, 0) == NULL )
400     {
401         vlc_mutex_unlock( &p_input->stream.stream_lock );
402         msg_Err( p_input, "cannot add program" );
403         return( VLC_EGENERIC );
404     }
405
406     p_input->stream.p_selected_program = p_input->stream.pp_programs[0];
407     p_input->stream.i_mux_rate =  wf.nAvgBytesPerSec / 50;
408
409     p_es = input_AddES( p_input,
410                         p_input->stream.p_selected_program,
411                         0x01,
412                         0 );
413
414     p_es->i_stream_id   = 0x01;
415     p_es->i_cat         = AUDIO_ES;
416     p_es->i_fourcc      = i_codec;
417     p_es->p_waveformatex= malloc( sizeof( WAVEFORMATEX ) );
418     memcpy( p_es->p_waveformatex,
419             &wf,
420             sizeof( WAVEFORMATEX ) );
421
422     input_SelectES( p_input, p_es );
423     p_input->stream.p_selected_program->b_is_ok = 1;
424     vlc_mutex_unlock( &p_input->stream.stream_lock );
425
426     /* create our structure that will contains all data */
427     if( ( p_demux = malloc( sizeof( demux_sys_t ) ) ) == NULL )
428     {
429         msg_Err( p_input, "out of memory" );
430         return( VLC_EGENERIC );
431     }
432     p_demux->p_es   = p_es;
433     p_demux->i_time = 0;
434     memcpy( &p_demux->au, &au, sizeof( au_t ) );
435     memcpy( &p_demux->wf, &wf, sizeof( WAVEFORMATEX ) );
436     switch( au.i_encoding )
437     {
438         case AUDIO_FILE_ENCODING_MULAW_8:
439         case AUDIO_FILE_ENCODING_LINEAR_8:
440         case AUDIO_FILE_ENCODING_LINEAR_16:
441         case AUDIO_FILE_ENCODING_LINEAR_24:
442         case AUDIO_FILE_ENCODING_LINEAR_32:
443         case AUDIO_FILE_ENCODING_FLOAT:
444         case AUDIO_FILE_ENCODING_DOUBLE:
445         case AUDIO_FILE_ENCODING_ALAW_8:
446             p_demux->i_demux = AU_DEMUX_PCM;
447             break;
448
449         case AUDIO_FILE_ENCODING_ADPCM_G721:
450         case AUDIO_FILE_ENCODING_ADPCM_G722:
451         case AUDIO_FILE_ENCODING_ADPCM_G723_3:
452         case AUDIO_FILE_ENCODING_ADPCM_G723_5:
453             p_demux->i_demux = AU_DEMUX_ADPCM;
454             break;
455
456         default:
457             p_demux->i_demux = 0;
458             break;
459     }
460
461     p_input->p_demux_data = p_demux;
462     p_input->pf_demux = AUDemux;
463
464     /* skip header*/
465     SkipBytes( p_input, au.i_header_size );
466
467     return( VLC_SUCCESS );
468 }
469
470 /*****************************************************************************
471  * AUDemux: read packet and send them to decoders
472  *****************************************************************************
473  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
474  *****************************************************************************/
475 static int AUDemux( input_thread_t *p_input )
476 {
477     demux_sys_t  *p_demux = p_input->p_demux_data;
478
479     if( p_input->stream.p_selected_program->i_synchro_state == SYNCHRO_REINIT )
480     {
481         off_t   i_offset;
482
483         i_offset = TellAbsolute( p_input ) - p_demux->au.i_header_size;
484         if( i_offset < 0 )
485         {
486             i_offset = 0;
487         }
488         if( p_demux->wf.nBlockAlign != 0 )
489         {
490             i_offset += p_demux->wf.nBlockAlign -
491                                 i_offset % p_demux->wf.nBlockAlign;
492         }
493         SeekAbsolute( p_input, p_demux->au.i_header_size + i_offset );
494     }
495
496     input_ClockManageRef( p_input,
497                           p_input->stream.p_selected_program,
498                           p_demux->i_time * 9 / 100 );
499
500     switch( p_demux->i_demux )
501     {
502         case AU_DEMUX_PCM:
503             return( AUDemuxPCM( p_input ) );
504         case AU_DEMUX_ADPCM:
505         default:
506             msg_Err( p_input, "Internal error (p_demux->i_demux invalid/unsported)" );
507             return( 0 );
508     }
509 }
510 static int AUDemuxPCM( input_thread_t *p_input )
511 {
512     demux_sys_t  *p_demux = p_input->p_demux_data;
513     pes_packet_t *p_pes;
514
515     int i_samples;
516
517     int i_bytes;
518     int i_modulo;
519
520     /* read samples for 50ms of */
521     i_samples = __MAX( p_demux->wf.nSamplesPerSec / 20, 1 );
522
523
524
525     i_bytes = i_samples * p_demux->wf.nChannels * ( (p_demux->wf.wBitsPerSample + 7) / 8 );
526
527     if( p_demux->wf.nBlockAlign > 0 )
528     {
529         if( ( i_modulo = i_bytes % p_demux->wf.nBlockAlign ) != 0 )
530         {
531             i_bytes += p_demux->wf.nBlockAlign - i_modulo;
532         }
533     }
534
535     if( ReadPES( p_input, &p_pes, i_bytes ) )
536     {
537         msg_Warn( p_input, "failed to get one frame" );
538         return( 0 );
539     }
540
541     p_pes->i_dts =
542         p_pes->i_pts = input_ClockGetTS( p_input,
543                                          p_input->stream.p_selected_program,
544                                          p_demux->i_time * 9 / 100 );
545
546     if( !p_demux->p_es->p_decoder_fifo )
547     {
548         msg_Err( p_input, "no audio decoder" );
549         input_DeletePES( p_input->p_method_data, p_pes );
550         return( -1 );
551     }
552     else
553     {
554         input_DecodePES( p_demux->p_es->p_decoder_fifo, p_pes );
555     }
556
557     p_demux->i_time += (mtime_t)1000000 *
558                        (mtime_t)i_samples /
559                        (mtime_t)p_demux->wf.nSamplesPerSec;
560
561     return( 1 );
562 }
563
564 /*****************************************************************************
565  * AUEnd: frees unused data
566  *****************************************************************************/
567 static void AUEnd ( vlc_object_t * p_this )
568 {
569     input_thread_t *  p_input = (input_thread_t *)p_this;
570
571     FREE( p_input->p_demux_data );
572 }
573