1 /*****************************************************************************
2 * wav.c : wav file input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001-2003 the VideoLAN team
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
30 #include <vlc_demux.h>
32 #include <vlc_codecs.h>
34 /*****************************************************************************
36 *****************************************************************************/
37 static int Open ( vlc_object_t
* );
38 static void Close( vlc_object_t
* );
41 set_description( _("WAV demuxer") );
42 set_category( CAT_INPUT
);
43 set_subcategory( SUBCAT_INPUT_DEMUX
);
44 set_capability( "demux2", 142 );
45 set_callbacks( Open
, Close
);
48 /*****************************************************************************
50 *****************************************************************************/
51 static int Demux ( demux_t
* );
52 static int Control( demux_t
*, int i_query
, va_list args
);
60 unsigned int i_data_size
;
62 unsigned int i_frame_size
;
67 uint32_t i_channel_mask
;
68 vlc_bool_t b_chan_reorder
; /* do we need channel reordering */
69 int pi_chan_table
[AOUT_CHAN_MAX
];
72 #define __EVEN( x ) ( ( (x)%2 != 0 ) ? ((x)+1) : (x) )
74 static int ChunkFind( demux_t
*, const char *, unsigned int * );
76 static void FrameInfo_IMA_ADPCM( demux_t
*, unsigned int *, int * );
77 static void FrameInfo_MS_ADPCM ( demux_t
*, unsigned int *, int * );
78 static void FrameInfo_PCM ( demux_t
*, unsigned int *, int * );
80 static const uint32_t pi_channels_src
[] =
81 { WAVE_SPEAKER_FRONT_LEFT
, WAVE_SPEAKER_FRONT_RIGHT
,
82 WAVE_SPEAKER_FRONT_CENTER
, WAVE_SPEAKER_LOW_FREQUENCY
,
83 WAVE_SPEAKER_BACK_LEFT
, WAVE_SPEAKER_BACK_RIGHT
,
84 WAVE_SPEAKER_SIDE_LEFT
, WAVE_SPEAKER_SIDE_RIGHT
, 0 };
85 static const uint32_t pi_channels_in
[] =
86 { AOUT_CHAN_LEFT
, AOUT_CHAN_RIGHT
,
87 AOUT_CHAN_CENTER
, AOUT_CHAN_LFE
,
88 AOUT_CHAN_REARLEFT
, AOUT_CHAN_REARRIGHT
,
89 AOUT_CHAN_MIDDLELEFT
, AOUT_CHAN_MIDDLERIGHT
, 0 };
90 static const uint32_t pi_channels_out
[] =
91 { AOUT_CHAN_LEFT
, AOUT_CHAN_RIGHT
,
92 AOUT_CHAN_MIDDLELEFT
, AOUT_CHAN_MIDDLERIGHT
,
93 AOUT_CHAN_REARLEFT
, AOUT_CHAN_REARRIGHT
,
94 AOUT_CHAN_CENTER
, AOUT_CHAN_LFE
, 0 };
96 /*****************************************************************************
97 * Open: check file and initializes structures
98 *****************************************************************************/
99 static int Open( vlc_object_t
* p_this
)
101 demux_t
*p_demux
= (demux_t
*)p_this
;
105 unsigned int i_size
, i_extended
;
108 WAVEFORMATEXTENSIBLE
*p_wf_ext
;
111 /* Is it a wav file ? */
112 if( stream_Peek( p_demux
->s
, &p_peek
, 12 ) < 12 ) return VLC_EGENERIC
;
114 if( memcmp( p_peek
, "RIFF", 4 ) || memcmp( &p_peek
[8], "WAVE", 4 ) )
119 p_demux
->pf_demux
= Demux
;
120 p_demux
->pf_control
= Control
;
121 p_demux
->p_sys
= p_sys
= malloc( sizeof( demux_sys_t
) );
123 p_sys
->b_chan_reorder
= 0;
124 p_sys
->i_channel_mask
= 0;
126 /* skip riff header */
127 stream_Read( p_demux
->s
, NULL
, 12 ); /* cannot fail as peek succeed */
129 /* search fmt chunk */
130 if( ChunkFind( p_demux
, "fmt ", &i_size
) )
132 msg_Err( p_demux
, "cannot find 'fmt ' chunk" );
135 if( i_size
< sizeof( WAVEFORMATEX
) - 2 ) /* XXX -2 isn't a typo */
137 msg_Err( p_demux
, "invalid 'fmt ' chunk" );
140 stream_Read( p_demux
->s
, NULL
, 8 ); /* Cannot fail */
142 /* load waveformatex */
143 p_wf_ext
= malloc( __EVEN( i_size
) + 2 );
144 p_wf
= (WAVEFORMATEX
*)p_wf_ext
;
146 if( stream_Read( p_demux
->s
,
147 p_wf
, __EVEN( i_size
) ) < (int)__EVEN( i_size
) )
149 msg_Err( p_demux
, "cannot load 'fmt ' chunk" );
153 es_format_Init( &p_sys
->fmt
, AUDIO_ES
, 0 );
154 wf_tag_to_fourcc( GetWLE( &p_wf
->wFormatTag
), &p_sys
->fmt
.i_codec
,
156 p_sys
->fmt
.audio
.i_channels
= GetWLE ( &p_wf
->nChannels
);
157 p_sys
->fmt
.audio
.i_rate
= GetDWLE( &p_wf
->nSamplesPerSec
);
158 p_sys
->fmt
.audio
.i_blockalign
= GetWLE( &p_wf
->nBlockAlign
);
159 p_sys
->fmt
.i_bitrate
= GetDWLE( &p_wf
->nAvgBytesPerSec
) * 8;
160 p_sys
->fmt
.audio
.i_bitspersample
= GetWLE( &p_wf
->wBitsPerSample
);
161 p_sys
->fmt
.i_extra
= GetWLE( &p_wf
->cbSize
);
164 /* Handle new WAVE_FORMAT_EXTENSIBLE wav files */
165 /* see the following link for more information:
166 * http://www.microsoft.com/whdc/device/audio/multichaud.mspx#EFAA */
167 if( GetWLE( &p_wf
->wFormatTag
) == WAVE_FORMAT_EXTENSIBLE
&&
168 i_size
>= sizeof( WAVEFORMATEXTENSIBLE
) )
170 unsigned i
, i_channel_mask
;
173 guid_subformat
= p_wf_ext
->SubFormat
;
174 guid_subformat
.Data1
= GetDWLE( &p_wf_ext
->SubFormat
.Data1
);
175 guid_subformat
.Data2
= GetWLE( &p_wf_ext
->SubFormat
.Data2
);
176 guid_subformat
.Data3
= GetWLE( &p_wf_ext
->SubFormat
.Data3
);
178 sf_tag_to_fourcc( &guid_subformat
, &p_sys
->fmt
.i_codec
, &psz_name
);
180 i_extended
= sizeof( WAVEFORMATEXTENSIBLE
) - sizeof( WAVEFORMATEX
);
181 p_sys
->fmt
.i_extra
-= i_extended
;
183 i_channel_mask
= GetDWLE( &p_wf_ext
->dwChannelMask
);
186 for( i
= 0; i
< sizeof(pi_channels_src
)/sizeof(uint32_t); i
++ )
188 if( i_channel_mask
& pi_channels_src
[i
] )
189 p_sys
->i_channel_mask
|= pi_channels_in
[i
];
192 if( p_sys
->fmt
.i_codec
== VLC_FOURCC('a','r','a','w') ||
193 p_sys
->fmt
.i_codec
== VLC_FOURCC('p','c','m',' ') ||
194 p_sys
->fmt
.i_codec
== VLC_FOURCC('a','f','l','t') )
196 p_sys
->b_chan_reorder
=
197 aout_CheckChannelReorder( pi_channels_in
, pi_channels_out
,
198 p_sys
->i_channel_mask
,
199 p_sys
->fmt
.audio
.i_channels
,
200 p_sys
->pi_chan_table
);
202 msg_Dbg( p_demux
, "channel mask: %x, reordering: %i",
203 p_sys
->i_channel_mask
, (int)p_sys
->b_chan_reorder
);
205 p_sys
->fmt
.audio
.i_physical_channels
=
206 p_sys
->fmt
.audio
.i_original_channels
=
207 p_sys
->i_channel_mask
;
210 if( p_sys
->fmt
.i_extra
> 0 )
212 p_sys
->fmt
.p_extra
= malloc( p_sys
->fmt
.i_extra
);
213 memcpy( p_sys
->fmt
.p_extra
, ((uint8_t *)p_wf
) + i_extended
,
214 p_sys
->fmt
.i_extra
);
217 msg_Dbg( p_demux
, "format: 0x%4.4x, fourcc: %4.4s, channels: %d, "
218 "freq: %d Hz, bitrate: %dKo/s, blockalign: %d, bits/samples: %d, "
220 GetWLE( &p_wf
->wFormatTag
), (char *)&p_sys
->fmt
.i_codec
,
221 p_sys
->fmt
.audio
.i_channels
, p_sys
->fmt
.audio
.i_rate
,
222 p_sys
->fmt
.i_bitrate
/ 8 / 1024, p_sys
->fmt
.audio
.i_blockalign
,
223 p_sys
->fmt
.audio
.i_bitspersample
, p_sys
->fmt
.i_extra
);
227 switch( p_sys
->fmt
.i_codec
)
229 case VLC_FOURCC( 'a', 'r', 'a', 'w' ):
230 case VLC_FOURCC( 'a', 'f', 'l', 't' ):
231 case VLC_FOURCC( 'u', 'l', 'a', 'w' ):
232 case VLC_FOURCC( 'a', 'l', 'a', 'w' ):
233 case VLC_FOURCC( 'm', 'l', 'a', 'w' ):
234 case VLC_FOURCC( 'p', 'c', 'm', ' ' ):
235 FrameInfo_PCM( p_demux
, &p_sys
->i_frame_size
,
236 &p_sys
->i_frame_samples
);
238 case VLC_FOURCC( 'm', 's', 0x00, 0x02 ):
239 FrameInfo_MS_ADPCM( p_demux
, &p_sys
->i_frame_size
,
240 &p_sys
->i_frame_samples
);
242 case VLC_FOURCC( 'm', 's', 0x00, 0x11 ):
243 FrameInfo_IMA_ADPCM( p_demux
, &p_sys
->i_frame_size
,
244 &p_sys
->i_frame_samples
);
246 case VLC_FOURCC( 'm', 's', 0x00, 0x61 ):
247 case VLC_FOURCC( 'm', 's', 0x00, 0x62 ):
248 /* FIXME not sure at all FIXME */
249 FrameInfo_MS_ADPCM( p_demux
, &p_sys
->i_frame_size
,
250 &p_sys
->i_frame_samples
);
252 case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
253 case VLC_FOURCC( 'a', '5', '2', ' ' ):
254 /* FIXME set end of area FIXME */
257 msg_Err( p_demux
, "unsupported codec (%4.4s)",
258 (char*)&p_sys
->fmt
.i_codec
);
262 msg_Dbg( p_demux
, "found %s audio format", psz_name
);
264 if( ChunkFind( p_demux
, "data", &p_sys
->i_data_size
) )
266 msg_Err( p_demux
, "cannot find 'data' chunk" );
269 stream_Read( p_demux
->s
, NULL
, 8 ); /* Cannot fail */
270 p_sys
->i_data_pos
= stream_Tell( p_demux
->s
);
272 if( p_sys
->fmt
.i_bitrate
<= 0 )
274 p_sys
->fmt
.i_bitrate
= (mtime_t
)p_sys
->i_frame_size
*
275 p_sys
->fmt
.audio
.i_rate
* 8 / p_sys
->i_frame_samples
;
278 p_sys
->p_es
= es_out_Add( p_demux
->out
, &p_sys
->fmt
);
280 date_Init( &p_sys
->pts
, p_sys
->fmt
.audio
.i_rate
, 1 );
281 date_Set( &p_sys
->pts
, 1 );
291 /*****************************************************************************
292 * Demux: read packet and send them to decoders
293 *****************************************************************************
294 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
295 *****************************************************************************/
296 static int Demux( demux_t
*p_demux
)
298 demux_sys_t
*p_sys
= p_demux
->p_sys
;
302 i_pos
= stream_Tell( p_demux
->s
);
304 if( p_sys
->i_data_size
> 0 &&
305 i_pos
>= p_sys
->i_data_pos
+ p_sys
->i_data_size
)
311 if( ( p_block
= stream_Block( p_demux
->s
, p_sys
->i_frame_size
) ) == NULL
)
313 msg_Warn( p_demux
, "cannot read data" );
317 p_block
->i_dts
= p_block
->i_pts
=
318 date_Increment( &p_sys
->pts
, p_sys
->i_frame_samples
);
321 es_out_Control( p_demux
->out
, ES_OUT_SET_PCR
, p_block
->i_pts
);
323 /* Do the channel reordering */
324 if( p_sys
->b_chan_reorder
)
325 aout_ChannelReorder( p_block
->p_buffer
, p_block
->i_buffer
,
326 p_sys
->fmt
.audio
.i_channels
,
327 p_sys
->pi_chan_table
,
328 p_sys
->fmt
.audio
.i_bitspersample
);
330 es_out_Send( p_demux
->out
, p_sys
->p_es
, p_block
);
335 /*****************************************************************************
336 * Close: frees unused data
337 *****************************************************************************/
338 static void Close ( vlc_object_t
* p_this
)
340 demux_t
*p_demux
= (demux_t
*)p_this
;
341 demux_sys_t
*p_sys
= p_demux
->p_sys
;
346 /*****************************************************************************
348 *****************************************************************************/
349 static int Control( demux_t
*p_demux
, int i_query
, va_list args
)
351 demux_sys_t
*p_sys
= p_demux
->p_sys
;
354 if( p_sys
->i_data_size
> 0 )
356 i_end
= p_sys
->i_data_pos
+ p_sys
->i_data_size
;
359 return demux2_vaControlHelper( p_demux
->s
, p_sys
->i_data_pos
, i_end
,
360 p_sys
->fmt
.i_bitrate
,
361 p_sys
->fmt
.audio
.i_blockalign
,
365 /*****************************************************************************
367 *****************************************************************************/
368 static int ChunkFind( demux_t
*p_demux
, const char *fcc
, unsigned int *pi_size
)
376 if( stream_Peek( p_demux
->s
, &p_peek
, 8 ) < 8 )
378 msg_Err( p_demux
, "cannot peek()" );
382 i_size
= GetDWLE( p_peek
+ 4 );
384 msg_Dbg( p_demux
, "chunk: fcc=`%4.4s` size=%d", p_peek
, i_size
);
386 if( !memcmp( p_peek
, fcc
, 4 ) )
395 i_size
= __EVEN( i_size
) + 8;
396 if( stream_Read( p_demux
->s
, NULL
, i_size
) != i_size
)
403 static void FrameInfo_PCM( demux_t
*p_demux
, unsigned int *pi_size
,
406 demux_sys_t
*p_sys
= p_demux
->p_sys
;
407 int i_bytes
, i_modulo
;
409 /* read samples for 50ms of */
410 *pi_samples
= __MAX( p_sys
->fmt
.audio
.i_rate
/ 20, 1 );
412 i_bytes
= *pi_samples
* p_sys
->fmt
.audio
.i_channels
*
413 ( (p_sys
->fmt
.audio
.i_bitspersample
+ 7) / 8 );
415 if( p_sys
->fmt
.audio
.i_blockalign
> 0 )
417 if( ( i_modulo
= i_bytes
% p_sys
->fmt
.audio
.i_blockalign
) != 0 )
419 i_bytes
+= p_sys
->fmt
.audio
.i_blockalign
- i_modulo
;
426 static void FrameInfo_MS_ADPCM( demux_t
*p_demux
, unsigned int *pi_size
,
429 demux_sys_t
*p_sys
= p_demux
->p_sys
;
431 *pi_samples
= 2 + 2 * ( p_sys
->fmt
.audio
.i_blockalign
-
432 7 * p_sys
->fmt
.audio
.i_channels
) / p_sys
->fmt
.audio
.i_channels
;
434 *pi_size
= p_sys
->fmt
.audio
.i_blockalign
;
437 static void FrameInfo_IMA_ADPCM( demux_t
*p_demux
, unsigned int *pi_size
,
440 demux_sys_t
*p_sys
= p_demux
->p_sys
;
442 *pi_samples
= 2 * ( p_sys
->fmt
.audio
.i_blockalign
-
443 4 * p_sys
->fmt
.audio
.i_channels
) / p_sys
->fmt
.audio
.i_channels
;
445 *pi_size
= p_sys
->fmt
.audio
.i_blockalign
;