/src/vlc/modules/demux/voc.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * voc.c : Creative Voice File (.VOC) demux module for vlc |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2005 Rémi Denis-Courmont |
5 | | * |
6 | | * Authors: Rémi Denis-Courmont |
7 | | * |
8 | | * This program is free software; you can redistribute it and/or modify it |
9 | | * under the terms of the GNU Lesser General Public License as published by |
10 | | * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU Lesser General Public License |
19 | | * along with this program; if not, write to the Free Software Foundation, |
20 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
21 | | *****************************************************************************/ |
22 | | |
23 | | /***************************************************************************** |
24 | | * Preamble |
25 | | *****************************************************************************/ |
26 | | |
27 | | #ifdef HAVE_CONFIG_H |
28 | | # include "config.h" |
29 | | #endif |
30 | | |
31 | | #include <assert.h> |
32 | | |
33 | | #include <vlc_common.h> |
34 | | #include <vlc_plugin.h> |
35 | | #include <vlc_demux.h> |
36 | | |
37 | | /***************************************************************************** |
38 | | * Module descriptor |
39 | | *****************************************************************************/ |
40 | | static int Open ( vlc_object_t * ); |
41 | | |
42 | 108 | vlc_module_begin () |
43 | 54 | set_description( N_("VOC demuxer") ) |
44 | 54 | set_subcategory( SUBCAT_INPUT_DEMUX ) |
45 | 54 | set_capability( "demux", 10 ) |
46 | 54 | set_callback( Open ) |
47 | 54 | add_file_extension("voc") |
48 | 54 | vlc_module_end () |
49 | | |
50 | | /***************************************************************************** |
51 | | * Local prototypes |
52 | | *****************************************************************************/ |
53 | | static int Demux ( demux_t * ); |
54 | | static int Control( demux_t *, int i_query, va_list args ); |
55 | | |
56 | | typedef struct |
57 | | { |
58 | | es_format_t fmt; |
59 | | es_out_id_t *p_es; |
60 | | |
61 | | int64_t i_block_start; |
62 | | int64_t i_block_end; |
63 | | |
64 | | int64_t i_loop_offset; |
65 | | unsigned i_loop_count; |
66 | | unsigned i_silence_countdown; |
67 | | |
68 | | date_t pts; |
69 | | } demux_sys_t; |
70 | | |
71 | | static const char ct_header[] = "Creative Voice File\x1a"; |
72 | | |
73 | | /***************************************************************************** |
74 | | * Open: check file and initializes structures |
75 | | *****************************************************************************/ |
76 | | static int Open( vlc_object_t * p_this ) |
77 | 1.53k | { |
78 | 1.53k | demux_t *p_demux = (demux_t*)p_this; |
79 | 1.53k | const uint8_t *p_buf; |
80 | 1.53k | uint16_t i_data_offset, i_version; |
81 | | |
82 | 1.53k | if( vlc_stream_Peek( p_demux->s, &p_buf, 26 ) < 26 ) |
83 | 11 | return VLC_EGENERIC; |
84 | | |
85 | 1.52k | if( memcmp( p_buf, ct_header, 20 ) ) |
86 | 398 | return VLC_EGENERIC; |
87 | 1.13k | p_buf += 20; |
88 | | |
89 | 1.13k | i_data_offset = GetWLE( p_buf ); |
90 | 1.13k | if ( i_data_offset < 26 /* not enough room for full VOC header */ ) |
91 | 5 | return VLC_EGENERIC; |
92 | 1.12k | p_buf += 2; |
93 | | |
94 | 1.12k | i_version = GetWLE( p_buf ); |
95 | 1.12k | if( ( i_version != 0x10A ) && ( i_version != 0x114 ) ) |
96 | 25 | return VLC_EGENERIC; /* unknown VOC version */ |
97 | 1.10k | p_buf += 2; |
98 | | |
99 | 1.10k | if( GetWLE( p_buf ) != (uint16_t)(0x1234 + ~i_version) ) |
100 | 24 | return VLC_EGENERIC; |
101 | | |
102 | | /* We have a valid VOC header */ |
103 | 1.07k | msg_Dbg( p_demux, "CT Voice file v%d.%d", i_version >> 8, |
104 | 1.07k | i_version & 0xff ); |
105 | | |
106 | | /* skip VOC header */ |
107 | 1.07k | if( vlc_stream_Read( p_demux->s, NULL, i_data_offset ) != i_data_offset ) |
108 | 37 | return VLC_EGENERIC; |
109 | | |
110 | 1.03k | demux_sys_t *p_sys = vlc_obj_malloc( p_this, sizeof (*p_sys) ); |
111 | 1.03k | if( unlikely(p_sys == NULL) ) |
112 | 0 | return VLC_ENOMEM; |
113 | | |
114 | 1.03k | p_sys->i_silence_countdown = p_sys->i_block_start = p_sys->i_block_end = |
115 | 1.03k | p_sys->i_loop_count = 0; |
116 | 1.03k | p_sys->p_es = NULL; |
117 | | |
118 | 1.03k | date_Init( &p_sys->pts, 1, 1 ); |
119 | 1.03k | date_Set( &p_sys->pts, VLC_TICK_0 ); |
120 | | |
121 | 1.03k | es_format_Init( &p_sys->fmt, AUDIO_ES, 0 ); |
122 | 1.03k | p_demux->pf_demux = Demux; |
123 | 1.03k | p_demux->pf_control = Control; |
124 | 1.03k | p_demux->p_sys = p_sys; |
125 | | |
126 | 1.03k | return VLC_SUCCESS; |
127 | 1.03k | } |
128 | | |
129 | | static int fmtcmp( es_format_t *ofmt, es_format_t *nfmt ) |
130 | 5.77M | { |
131 | 5.77M | return (ofmt->audio.i_bitspersample != nfmt->audio.i_bitspersample) |
132 | 4.41M | || (ofmt->audio.i_rate != nfmt->audio.i_rate) |
133 | 2.62M | || (ofmt->audio.i_channels != nfmt->audio.i_channels); |
134 | 5.77M | } |
135 | | |
136 | | |
137 | | /* |
138 | | * Converts old-style VOC sample rates to commonly used ones |
139 | | * so as not to confuse sound card drivers. |
140 | | * (I assume 16k, 24k and 32k are never found in .VOC files) |
141 | | */ |
142 | | static unsigned int fix_voc_sr( unsigned int sr ) |
143 | 5.32M | { |
144 | 5.32M | switch( sr ) |
145 | 5.32M | { |
146 | | /*case 8000: |
147 | | return 8000;*/ |
148 | 512k | case 11111: |
149 | 512k | return 11025; |
150 | | |
151 | 315k | case 22222: |
152 | 315k | return 22050; |
153 | | |
154 | 0 | case 44444: |
155 | 0 | return 44100; |
156 | 5.32M | } |
157 | 4.49M | return sr; |
158 | 5.32M | } |
159 | | |
160 | | static int ReadBlockHeader( demux_t *p_demux ) |
161 | 12.2M | { |
162 | 12.2M | es_format_t new_fmt; |
163 | 12.2M | uint8_t buf[8]; |
164 | 12.2M | int32_t i_block_size; |
165 | 12.2M | demux_sys_t *p_sys = p_demux->p_sys; |
166 | | |
167 | 12.2M | if( vlc_stream_Read( p_demux->s, buf, 4 ) < 4 ) |
168 | 367 | return VLC_EGENERIC; /* EOF */ |
169 | | |
170 | 12.2M | i_block_size = GetDWLE( buf ) >> 8; |
171 | 12.2M | msg_Dbg( p_demux, "new block: type: %u, size: %u", |
172 | 12.2M | (unsigned)*buf, i_block_size ); |
173 | | |
174 | 12.2M | es_format_Init( &new_fmt, AUDIO_ES, 0 ); |
175 | | |
176 | 12.2M | switch( *buf ) |
177 | 12.2M | { |
178 | 10 | case 0: /* not possible : caught with earlier vlc_stream_Read */ |
179 | 10 | goto corrupt; |
180 | | |
181 | 2.73M | case 1: |
182 | 2.73M | if( i_block_size < 2 ) |
183 | 2 | goto corrupt; |
184 | 2.73M | i_block_size -= 2; |
185 | | |
186 | 2.73M | if( vlc_stream_Read( p_demux->s, buf, 2 ) < 2 ) |
187 | 27 | goto corrupt; |
188 | | |
189 | 2.73M | switch( buf[1] ) /* codec id */ |
190 | 2.73M | { |
191 | 275k | case 0x0: |
192 | 275k | new_fmt.i_codec = VLC_CODEC_U8; |
193 | 275k | new_fmt.audio.i_bytes_per_frame = 1; |
194 | 275k | new_fmt.audio.i_bitspersample = 8; |
195 | 275k | break; |
196 | 306k | case 0x1: |
197 | 306k | new_fmt.i_codec = VLC_CODEC_ADPCM_SBPRO_4; |
198 | 306k | new_fmt.audio.i_bytes_per_frame = 1; |
199 | 306k | new_fmt.audio.i_bitspersample = 4; |
200 | 306k | break; |
201 | 221k | case 0x2: |
202 | 221k | new_fmt.i_codec = VLC_CODEC_ADPCM_SBPRO_3; |
203 | 221k | new_fmt.audio.i_bytes_per_frame = 3; |
204 | 221k | new_fmt.audio.i_bitspersample = 3; |
205 | 221k | break; |
206 | 425k | case 0x3: |
207 | 425k | new_fmt.i_codec = VLC_CODEC_ADPCM_SBPRO_2; |
208 | 425k | new_fmt.audio.i_bytes_per_frame = 1; |
209 | 425k | new_fmt.audio.i_bitspersample = 2; |
210 | 425k | break; |
211 | 226k | case 0x4: |
212 | 226k | new_fmt.i_codec = VLC_CODEC_S16L; |
213 | 226k | new_fmt.audio.i_bytes_per_frame = 2; |
214 | 226k | new_fmt.audio.i_bitspersample = 16; |
215 | 226k | break; |
216 | 753k | case 0x6: |
217 | 753k | new_fmt.i_codec = VLC_CODEC_ALAW; |
218 | 753k | new_fmt.audio.i_bytes_per_frame = 1; |
219 | 753k | new_fmt.audio.i_bitspersample = 8; |
220 | 753k | break; |
221 | 527k | case 0x7: |
222 | 527k | new_fmt.i_codec = VLC_CODEC_MULAW; |
223 | 527k | new_fmt.audio.i_bytes_per_frame = 1; |
224 | 527k | new_fmt.audio.i_bitspersample = 8; |
225 | 527k | break; |
226 | 5 | default: |
227 | 5 | msg_Err( p_demux, "unsupported compression 0x%"PRIx8, buf[1] ); |
228 | 5 | return VLC_EGENERIC; |
229 | 2.73M | } |
230 | | |
231 | 2.73M | new_fmt.audio.i_channels = 1; |
232 | 2.73M | new_fmt.audio.i_blockalign = new_fmt.audio.i_bytes_per_frame; |
233 | | |
234 | 2.73M | new_fmt.audio.i_frame_length = new_fmt.audio.i_bytes_per_frame * 8 |
235 | 2.73M | / new_fmt.audio.i_bitspersample; |
236 | | |
237 | 2.73M | new_fmt.audio.i_rate = fix_voc_sr( 1000000L / (256L - buf[0]) ); |
238 | 2.73M | new_fmt.i_bitrate = new_fmt.audio.i_rate * new_fmt.audio.i_bitspersample; |
239 | | |
240 | 2.73M | break; |
241 | | |
242 | 182k | case 2: /* data block with same format as the previous one */ |
243 | 182k | if( p_sys->p_es == NULL ) |
244 | 3 | goto corrupt; /* no previous block! */ |
245 | | |
246 | 182k | memcpy( &new_fmt, &p_sys->fmt, sizeof( new_fmt ) ); |
247 | 182k | break; |
248 | | |
249 | 2.58M | case 3: /* silence block */ |
250 | 2.58M | if( ( i_block_size != 3 ) |
251 | 2.58M | || ( vlc_stream_Read( p_demux->s, buf, 3 ) < 3 ) ) |
252 | 31 | goto corrupt; |
253 | | |
254 | 2.58M | i_block_size = 0; |
255 | 2.58M | p_sys->i_silence_countdown = GetWLE( buf ); |
256 | | |
257 | 2.58M | new_fmt.i_codec = VLC_CODEC_U8; |
258 | 2.58M | new_fmt.audio.i_rate = fix_voc_sr( 1000000L / (256L - buf[0]) ); |
259 | 2.58M | new_fmt.audio.i_bytes_per_frame = 1; |
260 | 2.58M | new_fmt.audio.i_frame_length = 1; |
261 | 2.58M | new_fmt.audio.i_channels = 1; |
262 | 2.58M | new_fmt.audio.i_blockalign = 1; |
263 | 2.58M | new_fmt.audio.i_bitspersample = 8; |
264 | 2.58M | new_fmt.i_bitrate = new_fmt.audio.i_rate * 8; |
265 | 2.58M | break; |
266 | | |
267 | 560 | case 6: /* repeat block */ |
268 | 560 | if( ( i_block_size != 2 ) |
269 | 536 | || ( vlc_stream_Read( p_demux->s, buf, 2 ) < 2 ) ) |
270 | 27 | goto corrupt; |
271 | | |
272 | 533 | i_block_size = 0; |
273 | 533 | p_sys->i_loop_count = GetWLE( buf ); |
274 | 533 | p_sys->i_loop_offset = vlc_stream_Tell( p_demux->s ); |
275 | 533 | break; |
276 | | |
277 | 5.31M | case 7: /* repeat end block */ |
278 | 5.31M | if( i_block_size != 0 ) |
279 | 26 | goto corrupt; |
280 | | |
281 | 5.31M | if( p_sys->i_loop_count > 0 ) |
282 | 5.31M | { |
283 | 5.31M | if( vlc_stream_Seek( p_demux->s, p_sys->i_loop_offset ) ) |
284 | 5.31M | msg_Warn( p_demux, "cannot loop: seek failed" ); |
285 | 5.31M | else |
286 | 5.31M | p_sys->i_loop_count--; |
287 | 5.31M | } |
288 | 5.31M | break; |
289 | | |
290 | 30.2k | case 8: |
291 | | /* |
292 | | * Block 8 is a big kludge to add stereo support to block 1 : |
293 | | * A block of type 8 is always followed by a block of type 1 |
294 | | * and specifies the number of channels in that 1-block |
295 | | * (normally block 1 are always mono). In practice, block type 9 |
296 | | * is used for stereo rather than 8 |
297 | | */ |
298 | 30.2k | if( ( i_block_size != 4 ) |
299 | 30.2k | || ( vlc_stream_Read( p_demux->s, buf, 4 ) < 4 ) ) |
300 | 26 | goto corrupt; |
301 | | |
302 | 30.2k | if( buf[2] ) |
303 | 8 | { |
304 | 8 | msg_Err( p_demux, "unsupported compression" ); |
305 | 8 | return VLC_EGENERIC; |
306 | 8 | } |
307 | | |
308 | 30.2k | new_fmt.i_codec = VLC_CODEC_U8; |
309 | 30.2k | static_assert( INPUT_CHAN_MAX > 32, "INPUT_CHAN_MAX too small" ); |
310 | 30.2k | if (buf[3] >= 32) |
311 | 3 | goto corrupt; |
312 | 30.2k | new_fmt.audio.i_channels = buf[3] + 1; /* can't be nul */ |
313 | 30.2k | new_fmt.audio.i_rate = 256000000L / |
314 | 30.2k | ((65536L - GetWLE(buf)) * new_fmt.audio.i_channels); |
315 | 30.2k | new_fmt.audio.i_bytes_per_frame = new_fmt.audio.i_channels; |
316 | 30.2k | new_fmt.audio.i_frame_length = 1; |
317 | 30.2k | new_fmt.audio.i_blockalign = new_fmt.audio.i_bytes_per_frame; |
318 | 30.2k | new_fmt.audio.i_bitspersample = 8 * new_fmt.audio.i_bytes_per_frame; |
319 | 30.2k | new_fmt.i_bitrate = new_fmt.audio.i_rate * 8; |
320 | | |
321 | | /* read subsequent block 1 */ |
322 | 30.2k | if( vlc_stream_Read( p_demux->s, buf, 4 ) < 4 ) |
323 | 9 | return VLC_EGENERIC; /* EOF */ |
324 | | |
325 | 30.2k | i_block_size = GetDWLE( buf ) >> 8; |
326 | 30.2k | msg_Dbg( p_demux, "new block: type: %u, size: %u", |
327 | 30.2k | (unsigned)*buf, i_block_size ); |
328 | 30.2k | if( i_block_size < 2 ) |
329 | 10 | goto corrupt; |
330 | 30.2k | i_block_size -= 2; |
331 | | |
332 | 30.2k | if( vlc_stream_Read( p_demux->s, buf, 2 ) < 2 ) |
333 | 31 | goto corrupt; |
334 | | |
335 | 30.1k | if( buf[1] ) |
336 | 8 | { |
337 | 8 | msg_Err( p_demux, "unsupported compression" ); |
338 | 8 | return VLC_EGENERIC; |
339 | 8 | } |
340 | | |
341 | 30.1k | break; |
342 | | |
343 | 747k | case 9: /* newer data block with channel number and bits resolution */ |
344 | 747k | if( i_block_size < 12 ) |
345 | 6 | goto corrupt; |
346 | 747k | i_block_size -= 12; |
347 | | |
348 | 747k | if( ( vlc_stream_Read( p_demux->s, buf, 8 ) < 8 ) |
349 | 747k | || vlc_stream_Read( p_demux->s, NULL, 4 ) != 4 ) |
350 | 32 | goto corrupt; |
351 | | |
352 | 747k | new_fmt.audio.i_rate = GetDWLE( buf ); |
353 | 747k | if( new_fmt.audio.i_rate == 0 || new_fmt.audio.i_rate > 768000 ) |
354 | 37 | goto corrupt; |
355 | 747k | new_fmt.audio.i_bitspersample = buf[4]; |
356 | 747k | new_fmt.audio.i_channels = buf[5]; |
357 | | |
358 | 747k | switch( GetWLE( &buf[6] ) ) /* format */ |
359 | 747k | { |
360 | 285k | case 0x0000: /* PCM */ |
361 | 285k | switch( new_fmt.audio.i_bitspersample ) |
362 | 285k | { |
363 | 34.3k | case 8: |
364 | 34.3k | new_fmt.i_codec = VLC_CODEC_U8; |
365 | 34.3k | break; |
366 | | |
367 | 250k | case 16: |
368 | 250k | new_fmt.i_codec = VLC_CODEC_U16L; |
369 | 250k | break; |
370 | | |
371 | 5 | default: |
372 | 5 | msg_Err( p_demux, "unsupported bit res.: %u bits", |
373 | 5 | new_fmt.audio.i_bitspersample ); |
374 | 5 | return VLC_EGENERIC; |
375 | 285k | } |
376 | 285k | break; |
377 | | |
378 | 462k | case 0x0004: /* signed */ |
379 | 462k | switch( new_fmt.audio.i_bitspersample ) |
380 | 462k | { |
381 | 303k | case 8: |
382 | 303k | new_fmt.i_codec = VLC_CODEC_S8; |
383 | 303k | break; |
384 | | |
385 | 158k | case 16: |
386 | 158k | new_fmt.i_codec = VLC_CODEC_S16L; |
387 | 158k | break; |
388 | | |
389 | 2 | default: |
390 | 2 | msg_Err( p_demux, "unsupported bit res.: %u bits", |
391 | 2 | new_fmt.audio.i_bitspersample ); |
392 | 2 | return VLC_EGENERIC; |
393 | 462k | } |
394 | 462k | break; |
395 | | |
396 | 462k | default: |
397 | 9 | msg_Err( p_demux, "unsupported compression" ); |
398 | 9 | return VLC_EGENERIC; |
399 | 747k | } |
400 | | |
401 | 747k | if( new_fmt.audio.i_channels == 0 ) |
402 | 2 | { |
403 | 2 | msg_Err( p_demux, "0 channels detected" ); |
404 | 2 | return VLC_EGENERIC; |
405 | 2 | } |
406 | 747k | if ( new_fmt.audio.i_channels > INPUT_CHAN_MAX ) |
407 | 4 | { |
408 | 4 | msg_Err( p_demux, "too many channels detected %" PRIu8, new_fmt.audio.i_channels ); |
409 | 4 | return VLC_EGENERIC; |
410 | 4 | } |
411 | | |
412 | 747k | new_fmt.audio.i_bytes_per_frame = new_fmt.audio.i_channels |
413 | 747k | * (new_fmt.audio.i_bitspersample / 8); |
414 | 747k | new_fmt.audio.i_frame_length = 1; |
415 | 747k | new_fmt.audio.i_blockalign = new_fmt.audio.i_bytes_per_frame; |
416 | 747k | new_fmt.i_bitrate = 8 * new_fmt.audio.i_rate |
417 | 747k | * new_fmt.audio.i_bytes_per_frame; |
418 | 747k | break; |
419 | | |
420 | 403k | default: |
421 | 403k | msg_Dbg( p_demux, "unknown block type %u - skipping block", |
422 | 403k | (unsigned)*buf); |
423 | | /* fall through */ |
424 | 469k | case 4: /* blocks of non-audio types can be skipped */ |
425 | 625k | case 5: |
426 | 625k | if(vlc_stream_Read( p_demux->s, NULL, i_block_size ) != i_block_size) |
427 | 48 | goto corrupt; |
428 | 625k | i_block_size = 0; |
429 | 625k | break; |
430 | 12.2M | } |
431 | | |
432 | 12.2M | p_sys->i_block_start = vlc_stream_Tell( p_demux->s ); |
433 | 12.2M | p_sys->i_block_end = p_sys->i_block_start + i_block_size; |
434 | | |
435 | 12.2M | if( i_block_size || p_sys->i_silence_countdown ) |
436 | 5.77M | { |
437 | | /* we've read a block with data in it - update decoder */ |
438 | 5.77M | msg_Dbg( p_demux, "fourcc: %4.4s, channels: %d, " |
439 | 5.77M | "freq: %d Hz, bitrate: %dKo/s, blockalign: %d, " |
440 | 5.77M | "bits/samples: %d", (char *)&new_fmt.i_codec, |
441 | 5.77M | new_fmt.audio.i_channels, new_fmt.audio.i_rate, |
442 | 5.77M | new_fmt.i_bitrate / 8192, new_fmt.audio.i_blockalign, |
443 | 5.77M | new_fmt.audio.i_bitspersample ); |
444 | | |
445 | 5.77M | if( ( p_sys->p_es != NULL ) && fmtcmp( &p_sys->fmt, &new_fmt ) ) |
446 | 3.16M | { |
447 | 3.16M | msg_Dbg( p_demux, "codec change needed" ); |
448 | 3.16M | es_out_Del( p_demux->out, p_sys->p_es ); |
449 | 3.16M | p_sys->p_es = NULL; |
450 | 3.16M | } |
451 | | |
452 | 5.77M | if( p_sys->p_es == NULL ) |
453 | 3.16M | { |
454 | 3.16M | memcpy( &p_sys->fmt, &new_fmt, sizeof( p_sys->fmt ) ); |
455 | 3.16M | date_Change( &p_sys->pts, p_sys->fmt.audio.i_rate, 1 ); |
456 | 3.16M | p_sys->p_es = es_out_Add( p_demux->out, &p_sys->fmt ); |
457 | 3.16M | if( unlikely(p_sys->p_es == NULL) ) |
458 | 0 | return VLC_ENOMEM; |
459 | 3.16M | } |
460 | 5.77M | } |
461 | | |
462 | 12.2M | return VLC_SUCCESS; |
463 | | |
464 | 319 | corrupt: |
465 | 319 | msg_Err( p_demux, "corrupted file - halting demux" ); |
466 | 319 | return VLC_EGENERIC; |
467 | 12.2M | } |
468 | | |
469 | | /***************************************************************************** |
470 | | * Demux: read packet and send them to decoders |
471 | | ***************************************************************************** |
472 | | * Returns -1 in case of error, 0 in case of EOF, 1 otherwise |
473 | | *****************************************************************************/ |
474 | 115M | #define MAX_READ_FRAME 1000 |
475 | | static int Demux( demux_t *p_demux ) |
476 | 72.9M | { |
477 | 72.9M | demux_sys_t *p_sys = p_demux->p_sys; |
478 | 72.9M | block_t *p_block; |
479 | 72.9M | int64_t i_read_frames; |
480 | | |
481 | 72.9M | if( p_sys->i_silence_countdown == 0 ) |
482 | 16.4M | { |
483 | 16.4M | int64_t i_offset = vlc_stream_Tell( p_demux->s ); |
484 | 16.4M | if( i_offset >= p_sys->i_block_end ) |
485 | 12.2M | { |
486 | 12.2M | if( ReadBlockHeader( p_demux ) != VLC_SUCCESS ) |
487 | 738 | return VLC_DEMUXER_EOF; |
488 | 12.2M | return VLC_DEMUXER_SUCCESS; |
489 | 12.2M | } |
490 | | |
491 | 4.27M | i_read_frames = ( p_sys->i_block_end - i_offset ) |
492 | 4.27M | / p_sys->fmt.audio.i_bytes_per_frame; |
493 | | |
494 | 4.27M | if( i_read_frames > MAX_READ_FRAME ) |
495 | 1.07M | i_read_frames = MAX_READ_FRAME; |
496 | | |
497 | 4.27M | p_block = vlc_stream_Block( p_demux->s, |
498 | 4.27M | p_sys->fmt.audio.i_bytes_per_frame |
499 | 4.27M | * i_read_frames ); |
500 | 4.27M | if( p_block == NULL ) |
501 | 301 | { |
502 | 301 | msg_Warn( p_demux, "cannot read data" ); |
503 | 301 | return VLC_DEMUXER_EOF; |
504 | 301 | } |
505 | 4.27M | } |
506 | 56.4M | else |
507 | 56.4M | { /* emulates silence from the stream */ |
508 | 56.4M | i_read_frames = p_sys->i_silence_countdown; |
509 | 56.4M | if( i_read_frames > MAX_READ_FRAME ) |
510 | 53.8M | i_read_frames = MAX_READ_FRAME; |
511 | | |
512 | 56.4M | p_block = block_Alloc( i_read_frames ); |
513 | 56.4M | if( p_block == NULL ) |
514 | 0 | return VLC_ENOMEM; |
515 | | |
516 | 56.4M | memset( p_block->p_buffer, 0, i_read_frames ); |
517 | 56.4M | p_sys->i_silence_countdown -= i_read_frames; |
518 | 56.4M | } |
519 | | |
520 | 60.6M | p_block->i_dts = p_block->i_pts = VLC_TICK_0 + date_Get( &p_sys->pts ); |
521 | 60.6M | p_block->i_nb_samples = i_read_frames * p_sys->fmt.audio.i_frame_length; |
522 | 60.6M | date_Increment( &p_sys->pts, p_block->i_nb_samples ); |
523 | 60.6M | es_out_SetPCR( p_demux->out, p_block->i_pts ); |
524 | 60.6M | assert(p_sys->p_es != NULL); |
525 | 60.6M | es_out_Send( p_demux->out, p_sys->p_es, p_block ); |
526 | | |
527 | 60.6M | return VLC_DEMUXER_SUCCESS; |
528 | 60.6M | } |
529 | | |
530 | | /***************************************************************************** |
531 | | * Control: |
532 | | *****************************************************************************/ |
533 | | static int Control( demux_t *p_demux, int i_query, va_list args ) |
534 | 0 | { |
535 | 0 | demux_sys_t *p_sys = p_demux->p_sys; |
536 | |
|
537 | 0 | return demux_vaControlHelper( p_demux->s, p_sys->i_block_start, |
538 | 0 | p_sys->i_block_end, |
539 | 0 | p_sys->fmt.i_bitrate, |
540 | 0 | p_sys->fmt.audio.i_blockalign, |
541 | 0 | i_query, args ); |
542 | 0 | } |