demux: hls: add adaptative based hls demuxer
[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  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
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 static void Close( vlc_object_t * );
46
47 vlc_module_begin ()
48     set_category( CAT_INPUT )
49     set_subcategory( SUBCAT_INPUT_DEMUX )
50     set_description( N_("AU demuxer") )
51     set_capability( "demux", 10 )
52     set_callbacks( Open, Close )
53     add_shortcut( "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 struct demux_sys_t
84 {
85     es_format_t     fmt;
86     es_out_id_t     *es;
87
88     mtime_t         i_time;
89
90     int             i_frame_size;
91     mtime_t         i_frame_length;
92
93     int             i_header_size;
94 };
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     demux_sys_t *p_sys;
106
107     uint8_t      hdr[20];
108     const uint8_t *p_peek;
109     int          i_cat;
110     int          i_samples, i_modulo;
111
112     if( stream_Peek( p_demux->s , &p_peek, 4 ) < 4 )
113         return VLC_EGENERIC;
114
115     if( memcmp( p_peek, ".snd", 4 ) )
116         return VLC_EGENERIC;
117
118     /* skip signature */
119     stream_Read( p_demux->s, NULL, 4 );   /* cannot fail */
120
121     /* read header */
122     if( stream_Read( p_demux->s, hdr, 20 ) < 20 )
123     {
124         msg_Err( p_demux, "cannot read" );
125         return VLC_EGENERIC;
126     }
127
128     if( GetDWBE( &hdr[0]  ) < 24 )
129     {
130         msg_Err( p_demux, "invalid file" );
131         return VLC_EGENERIC;
132     }
133
134     DEMUX_INIT_COMMON(); p_sys = p_demux->p_sys;
135     p_sys->i_time = 0;
136     p_sys->i_header_size = GetDWBE( &hdr[0] );
137
138     /* skip extra header data */
139     if( p_sys->i_header_size > 24 )
140     {
141         stream_Read( p_demux->s, NULL, p_sys->i_header_size - 24 );
142     }
143
144     /* init fmt */
145     es_format_Init( &p_sys->fmt, AUDIO_ES, 0 );
146     p_sys->fmt.audio.i_rate     = GetDWBE( &hdr[12] );
147     p_sys->fmt.audio.i_channels = GetDWBE( &hdr[16] );
148
149 #if 0
150     p_sys->au.i_header_size   = GetDWBE( &p_sys->au.i_header_size );
151     p_sys->au.i_data_size     = GetDWBE( &p_sys->au.i_data_size );
152     p_sys->au.i_encoding      = GetDWBE( &p_sys->au.i_encoding );
153     p_sys->au.i_sample_rate   = GetDWBE( &p_sys->au.i_sample_rate );
154     p_sys->au.i_channels      = GetDWBE( &p_sys->au.i_channels );
155 #endif
156     switch( GetDWBE( &hdr[8] ) )
157     {
158         case AU_ALAW_8:        /* 8-bit ISDN A-law */
159             p_sys->fmt.i_codec               = VLC_CODEC_ALAW;
160             p_sys->fmt.audio.i_bitspersample = 8;
161             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
162             i_cat                    = AU_CAT_PCM;
163             break;
164
165         case AU_MULAW_8:       /* 8-bit ISDN u-law */
166             p_sys->fmt.i_codec               = VLC_CODEC_MULAW;
167             p_sys->fmt.audio.i_bitspersample = 8;
168             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
169             i_cat                    = AU_CAT_PCM;
170             break;
171
172         case AU_LINEAR_8:      /* 8-bit linear PCM */
173             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
174             p_sys->fmt.audio.i_bitspersample = 8;
175             p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
176             i_cat                    = AU_CAT_PCM;
177             break;
178
179         case AU_LINEAR_16:     /* 16-bit linear PCM */
180             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
181             p_sys->fmt.audio.i_bitspersample = 16;
182             p_sys->fmt.audio.i_blockalign    = 2 * p_sys->fmt.audio.i_channels;
183             i_cat                    = AU_CAT_PCM;
184             break;
185
186         case AU_LINEAR_24:     /* 24-bit linear PCM */
187             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
188             p_sys->fmt.audio.i_bitspersample = 24;
189             p_sys->fmt.audio.i_blockalign    = 3 * p_sys->fmt.audio.i_channels;
190             i_cat                    = AU_CAT_PCM;
191             break;
192
193         case AU_LINEAR_32:     /* 32-bit linear PCM */
194             p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
195             p_sys->fmt.audio.i_bitspersample = 32;
196             p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
197             i_cat                    = AU_CAT_PCM;
198             break;
199
200         case AU_FLOAT:         /* 32-bit IEEE floating point */
201             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_FLOAT );
202             p_sys->fmt.audio.i_bitspersample = 32;
203             p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
204             i_cat                    = AU_CAT_PCM;
205             break;
206
207         case AU_DOUBLE:        /* 64-bit IEEE floating point */
208             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_DOUBLE );
209             p_sys->fmt.audio.i_bitspersample = 64;
210             p_sys->fmt.audio.i_blockalign    = 8 * p_sys->fmt.audio.i_channels;
211             i_cat                    = AU_CAT_PCM;
212             break;
213
214         case AU_ADPCM_G721:    /* 4-bit CCITT g.721 ADPCM */
215             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G721 );
216             p_sys->fmt.audio.i_bitspersample = 0;
217             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
218             i_cat                    = AU_CAT_ADPCM;
219             break;
220
221         case AU_ADPCM_G722:    /* CCITT g.722 ADPCM */
222             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G722 );
223             p_sys->fmt.audio.i_bitspersample = 0;
224             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
225             i_cat                    = AU_CAT_ADPCM;
226             break;
227
228         case AU_ADPCM_G723_3:  /* CCITT g.723 3-bit ADPCM */
229             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_3 );
230             p_sys->fmt.audio.i_bitspersample = 0;
231             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
232             i_cat                    = AU_CAT_ADPCM;
233             break;
234
235         case AU_ADPCM_G723_5:  /* CCITT g.723 5-bit ADPCM */
236             p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_5 );
237             p_sys->fmt.audio.i_bitspersample = 0;
238             p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
239             i_cat                    = AU_CAT_ADPCM;
240             break;
241
242         default:
243             msg_Warn( p_demux, "unknow encoding=0x%x", GetDWBE( &hdr[8] ) );
244             p_sys->fmt.audio.i_bitspersample = 0;
245             p_sys->fmt.audio.i_blockalign    = 0;
246             i_cat                    = AU_CAT_UNKNOWN;
247             break;
248     }
249
250     p_sys->fmt.i_bitrate = p_sys->fmt.audio.i_rate *
251                            p_sys->fmt.audio.i_channels *
252                            p_sys->fmt.audio.i_bitspersample;
253
254     if( i_cat == AU_CAT_UNKNOWN || i_cat == AU_CAT_ADPCM )
255     {
256         p_sys->i_frame_size = 0;
257         p_sys->i_frame_length = 0;
258
259         msg_Err( p_demux, "unsupported codec/type (Please report it)" );
260         free( p_sys );
261         return VLC_EGENERIC;
262     }
263
264     if( p_sys->fmt.audio.i_rate == 0 )
265     {
266         msg_Err( p_demux, "invalid samplerate: 0" );
267         free( p_sys );
268         return VLC_EGENERIC;
269     }
270
271     /* add the es */
272     p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt );
273
274     /* calculate 50ms frame size/time */
275     i_samples = __MAX( p_sys->fmt.audio.i_rate / 20, 1 );
276     p_sys->i_frame_size = i_samples * p_sys->fmt.audio.i_channels *
277                           ( (p_sys->fmt.audio.i_bitspersample + 7) / 8 );
278     if( p_sys->fmt.audio.i_blockalign > 0 )
279     {
280         if( ( i_modulo = p_sys->i_frame_size % p_sys->fmt.audio.i_blockalign ) != 0 )
281         {
282             p_sys->i_frame_size += p_sys->fmt.audio.i_blockalign - i_modulo;
283         }
284     }
285     p_sys->i_frame_length = (mtime_t)1000000 *
286                             (mtime_t)i_samples /
287                             (mtime_t)p_sys->fmt.audio.i_rate;
288
289     return VLC_SUCCESS;
290 }
291
292 /*****************************************************************************
293  * Demux: read packet and send them to decoders
294  *****************************************************************************
295  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
296  *****************************************************************************/
297 static int Demux( demux_t *p_demux )
298 {
299     demux_sys_t *p_sys = p_demux->p_sys;
300     block_t     *p_block;
301
302     /* set PCR */
303     es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_time );
304
305     if( ( p_block = stream_Block( p_demux->s, p_sys->i_frame_size ) ) == NULL )
306     {
307         msg_Warn( p_demux, "cannot read data" );
308         return 0;
309     }
310
311     p_block->i_dts =
312     p_block->i_pts = VLC_TS_0 + p_sys->i_time;
313
314     es_out_Send( p_demux->out, p_sys->es, p_block );
315
316     p_sys->i_time += p_sys->i_frame_length;
317
318     return 1;
319 }
320
321 /*****************************************************************************
322  * Close: frees unused data
323  *****************************************************************************/
324 static void Close( vlc_object_t * p_this )
325 {
326     demux_t     *p_demux = (demux_t*)p_this;
327     demux_sys_t *p_sys = p_demux->p_sys;
328
329     free( p_sys );
330 }
331
332 /*****************************************************************************
333  * Control:
334  *****************************************************************************/
335 static int Control( demux_t *p_demux, int i_query, va_list args )
336 {
337     demux_sys_t *p_sys = p_demux->p_sys;
338
339     return demux_vaControlHelper( p_demux->s, p_sys->i_header_size, -1,
340                                    p_sys->fmt.i_bitrate, p_sys->fmt.audio.i_blockalign,
341                                    i_query, args );
342 }
343