demux: libavi: force chunk type check
[vlc.git] / modules / demux / flac.c
blob33de6aacbcb3d4303b15b899162470bdfa028004
1 /*****************************************************************************
2 * flac.c : FLAC demux module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001-2008 VLC authors and VideoLAN
5 * $Id$
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
8 * Laurent Aimar <fenrir@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
26 * Preamble
27 *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_demux.h>
35 #include <vlc_meta.h> /* vlc_meta_* */
36 #include <vlc_input.h> /* vlc_input_attachment, vlc_seekpoint */
37 #include <vlc_codec.h> /* decoder_t */
38 #include <vlc_charset.h> /* EnsureUTF8 */
40 #include <assert.h>
41 #include "xiph_metadata.h" /* vorbis comments */
43 /*****************************************************************************
44 * Module descriptor
45 *****************************************************************************/
46 static int Open ( vlc_object_t * );
47 static void Close ( vlc_object_t * );
49 vlc_module_begin ()
50 set_description( N_("FLAC demuxer") )
51 set_capability( "demux", 155 )
52 set_category( CAT_INPUT )
53 set_subcategory( SUBCAT_INPUT_DEMUX )
54 set_callbacks( Open, Close )
55 add_shortcut( "flac" )
56 vlc_module_end ()
58 /*****************************************************************************
59 * Local prototypes
60 *****************************************************************************/
61 static int Demux ( demux_t * );
62 static int Control( demux_t *, int, va_list );
64 static int ParseHeaders( demux_t *, es_format_t * );
66 typedef struct
68 mtime_t i_time_offset;
69 uint64_t i_byte_offset;
70 } flac_seekpoint_t;
72 struct demux_sys_t
74 bool b_start;
75 int i_next_block_flags;
76 es_out_id_t *p_es;
77 block_t *p_current_block;
79 /* Packetizer */
80 decoder_t *p_packetizer;
82 vlc_meta_t *p_meta;
84 int64_t i_pts;
86 int64_t i_length; /* Length from stream info */
87 uint64_t i_data_pos;
89 /* */
90 int i_seekpoint;
91 flac_seekpoint_t **seekpoint;
93 /* title/chapters seekpoints */
94 int i_title_seekpoints;
95 seekpoint_t **pp_title_seekpoints;
97 /* */
98 int i_attachments;
99 input_attachment_t **attachments;
100 int i_cover_idx;
101 int i_cover_score;
104 #define STREAMINFO_SIZE 34
105 #define FLAC_PACKET_SIZE 16384
106 #define FLAC_MAX_PREROLL (CLOCK_FREQ * 4)
107 #define FLAC_MAX_SLOW_PREROLL (CLOCK_FREQ * 45)
108 #define FLAC_MIN_FRAME_SIZE ((48+(8 + 4 + 1*4)+16)/8)
110 /*****************************************************************************
111 * Open: initializes ES structures
112 *****************************************************************************/
113 static int Open( vlc_object_t * p_this )
115 demux_t *p_demux = (demux_t*)p_this;
116 demux_sys_t *p_sys;
117 const uint8_t *p_peek;
118 es_format_t fmt;
120 /* Have a peep at the show. */
121 if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;
123 if( p_peek[0]!='f' || p_peek[1]!='L' || p_peek[2]!='a' || p_peek[3]!='C' )
125 if( !p_demux->obj.force
126 && !demux_IsContentType( p_demux, "audio/flac" ) )
127 return VLC_EGENERIC;
129 /* User forced */
130 msg_Err( p_demux, "this doesn't look like a flac stream, "
131 "continuing anyway" );
134 p_sys = malloc( sizeof( demux_sys_t ) );
135 if( unlikely(p_sys == NULL) )
136 return VLC_ENOMEM;
138 p_demux->pf_demux = Demux;
139 p_demux->pf_control = Control;
140 p_demux->p_sys = p_sys;
141 p_sys->b_start = true;
142 p_sys->i_next_block_flags = 0;
143 p_sys->p_packetizer = NULL;
144 p_sys->p_meta = NULL;
145 p_sys->i_length = 0;
146 p_sys->i_pts = VLC_TS_INVALID;
147 p_sys->p_es = NULL;
148 p_sys->p_current_block = NULL;
149 TAB_INIT( p_sys->i_seekpoint, p_sys->seekpoint );
150 TAB_INIT( p_sys->i_attachments, p_sys->attachments);
151 TAB_INIT( p_sys->i_title_seekpoints, p_sys->pp_title_seekpoints );
152 p_sys->i_cover_idx = 0;
153 p_sys->i_cover_score = 0;
155 es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_FLAC );
157 /* We need to read and store the STREAMINFO metadata into fmt extra */
158 if( ParseHeaders( p_demux, &fmt ) )
159 goto error;
161 /* Load the FLAC packetizer */
162 p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "flac" );
163 if( !p_sys->p_packetizer )
164 goto error;
166 if( p_sys->i_cover_idx < p_sys->i_attachments )
168 char psz_url[128];
169 if( !p_sys->p_meta )
170 p_sys->p_meta = vlc_meta_New();
171 snprintf( psz_url, sizeof(psz_url), "attachment://%s",
172 p_sys->attachments[p_sys->i_cover_idx]->psz_name );
173 vlc_meta_Set( p_sys->p_meta, vlc_meta_ArtworkURL, psz_url );
176 p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_in );
177 if( !p_sys->p_es )
178 goto error;
180 return VLC_SUCCESS;
181 error:
182 Close( p_this );
183 return VLC_EGENERIC;
186 /*****************************************************************************
187 * Close: frees unused data
188 *****************************************************************************/
189 static void Close( vlc_object_t * p_this )
191 demux_t *p_demux = (demux_t*)p_this;
192 demux_sys_t *p_sys = p_demux->p_sys;
194 if( p_sys->p_current_block )
195 block_Release( p_sys->p_current_block );
197 for( int i = 0; i < p_sys->i_seekpoint; i++ )
198 free(p_sys->seekpoint[i]);
199 TAB_CLEAN( p_sys->i_seekpoint, p_sys->seekpoint );
201 for( int i = 0; i < p_sys->i_attachments; i++ )
202 vlc_input_attachment_Delete( p_sys->attachments[i] );
203 TAB_CLEAN( p_sys->i_attachments, p_sys->attachments);
205 for( int i = 0; i < p_sys->i_title_seekpoints; i++ )
206 vlc_seekpoint_Delete( p_sys->pp_title_seekpoints[i] );
207 TAB_CLEAN( p_sys->i_title_seekpoints, p_sys->pp_title_seekpoints );
209 /* Delete the decoder */
210 if( p_sys->p_packetizer )
211 demux_PacketizerDestroy( p_sys->p_packetizer );
213 if( p_sys->p_meta )
214 vlc_meta_Delete( p_sys->p_meta );
215 free( p_sys );
218 static void FlushPacketizer( decoder_t *p_packetizer )
220 if( p_packetizer->pf_flush )
221 p_packetizer->pf_flush( p_packetizer );
222 else
224 block_t *p_block_out;
225 while( (p_block_out = p_packetizer->pf_packetize( p_packetizer, NULL )) )
226 block_Release( p_block_out );
230 static void Reset( demux_sys_t *p_sys )
232 p_sys->i_pts = VLC_TS_INVALID;
234 FlushPacketizer( p_sys->p_packetizer );
235 if( p_sys->p_current_block )
237 block_Release( p_sys->p_current_block );
238 p_sys->p_current_block = NULL;
242 static int RefineSeek( demux_t *p_demux, mtime_t i_time, double i_bytemicrorate,
243 uint64_t i_lowpos, uint64_t i_highpos )
245 demux_sys_t *p_sys = p_demux->p_sys;
246 bool b_found = false;
247 block_t *p_block_out;
248 block_t *p_block_in;
250 unsigned i_frame_size = FLAC_MIN_FRAME_SIZE;
252 bool b_canfastseek = false;
253 (int) vlc_stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b_canfastseek );
255 uint64_t i_start_pos = vlc_stream_Tell( p_demux->s );
257 while( !b_found )
259 FlushPacketizer( p_sys->p_packetizer );
261 p_block_out = NULL;
262 p_block_in = NULL;
264 while( !p_block_out )
266 if( !p_block_in )
268 if( !(p_block_in = vlc_stream_Block( p_demux->s, i_frame_size )) )
269 break;
272 p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer, &p_block_in );
275 if( !p_block_out )
277 if( p_block_in )
278 block_Release( p_block_in );
279 break;
282 if( p_block_out->i_buffer > i_frame_size )
283 i_frame_size = p_block_out->i_buffer;
285 /* If we are further than wanted block */
286 if( p_block_out->i_dts >= i_time )
288 mtime_t i_diff = p_block_out->i_dts - i_time;
289 /* Not in acceptable approximation range */
290 if( i_diff > CLOCK_FREQ / 10 && i_diff / i_bytemicrorate > i_frame_size )
292 i_highpos = i_start_pos;
293 i_start_pos -= ( i_diff / i_bytemicrorate );
294 i_start_pos = __MAX(i_start_pos, i_lowpos + i_frame_size);
296 else b_found = true;
298 else if( p_block_out->i_dts < i_time )
300 mtime_t i_diff = i_time - p_block_out->i_dts;
301 /* Not in acceptable NEXT_TIME demux range */
302 if( i_diff >= ((b_canfastseek) ? FLAC_MAX_PREROLL : FLAC_MAX_SLOW_PREROLL) &&
303 i_diff / i_bytemicrorate > i_frame_size )
305 i_lowpos = i_start_pos;
306 i_start_pos += ( i_diff / i_bytemicrorate );
307 i_start_pos = __MIN(i_start_pos, i_highpos - i_frame_size);
309 else b_found = true;
312 if( p_block_out )
313 block_Release( p_block_out );
314 if( p_block_in )
315 block_Release( p_block_in );
317 if( !b_found )
319 if( i_highpos < i_lowpos || i_highpos - i_lowpos < i_frame_size )
320 break;
322 if( VLC_SUCCESS != vlc_stream_Seek( p_demux->s, i_start_pos ) )
323 break;
327 return b_found ? VLC_SUCCESS : VLC_EGENERIC;
330 /*****************************************************************************
331 * Demux: reads and demuxes data packets
332 *****************************************************************************
333 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
334 *****************************************************************************/
335 static int Demux( demux_t *p_demux )
337 demux_sys_t *p_sys = p_demux->p_sys;
338 block_t *p_block_out;
340 bool b_eof = false;
341 if( p_sys->p_current_block == NULL )
343 p_sys->p_current_block = vlc_stream_Block( p_demux->s, FLAC_PACKET_SIZE );
344 b_eof = (p_sys->p_current_block == NULL);
347 if ( p_sys->p_current_block )
349 p_sys->p_current_block->i_flags = p_sys->i_next_block_flags;
350 p_sys->i_next_block_flags = 0;
351 p_sys->p_current_block->i_pts =
352 p_sys->p_current_block->i_dts = p_sys->b_start ? VLC_TS_0 : VLC_TS_INVALID;
355 while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer,
356 (p_sys->p_current_block) ? &p_sys->p_current_block : NULL )) )
358 /* Only clear on output when packet is accepted as sync #17111 */
359 p_sys->b_start = false;
360 while( p_block_out )
362 block_t *p_next = p_block_out->p_next;
364 p_block_out->p_next = NULL;
366 /* set PCR */
367 if( unlikely(p_sys->i_pts == VLC_TS_INVALID) )
368 es_out_SetPCR( p_demux->out, __MAX(p_block_out->i_dts - 1, VLC_TS_0) );
370 p_sys->i_pts = p_block_out->i_dts;
372 es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
374 es_out_SetPCR( p_demux->out, p_sys->i_pts );
376 p_block_out = p_next;
378 break;
381 return b_eof ? VLC_DEMUXER_EOF : VLC_DEMUXER_SUCCESS;
384 /*****************************************************************************
385 * Control:
386 *****************************************************************************/
387 static int64_t ControlGetLength( demux_t *p_demux )
389 demux_sys_t *p_sys = p_demux->p_sys;
390 const uint64_t i_size = stream_Size(p_demux->s) - p_sys->i_data_pos;
391 int64_t i_length = p_sys->i_length;
392 int i;
394 /* Try to fix length using seekpoint and current size for truncated file */
395 for( i = p_sys->i_seekpoint-1; i >= 0; i-- )
397 flac_seekpoint_t *s = p_sys->seekpoint[i];
398 if( s->i_byte_offset <= i_size )
400 if( i+1 < p_sys->i_seekpoint )
402 /* Broken file */
403 flac_seekpoint_t *n = p_sys->seekpoint[i+1];
404 assert( n->i_byte_offset != s->i_byte_offset); /* Should be ensured by ParseSeekTable */
405 i_length = s->i_time_offset + (n->i_time_offset-s->i_time_offset) * (i_size-s->i_byte_offset) / (n->i_byte_offset-s->i_byte_offset);
407 break;
410 return i_length;
413 static int64_t ControlGetTime( demux_t *p_demux )
415 demux_sys_t *p_sys = p_demux->p_sys;
416 return p_sys->i_pts;
419 static int ControlSetTime( demux_t *p_demux, int64_t i_time )
421 demux_sys_t *p_sys = p_demux->p_sys;
422 bool b_seekable;
423 int i;
425 /* */
426 vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_seekable );
427 if( !b_seekable )
428 return VLC_EGENERIC;
430 const mtime_t i_length = ControlGetLength( p_demux );
431 if( i_length <= 0 )
432 return VLC_EGENERIC;
434 const uint64_t i_stream_size = stream_Size( p_demux->s );
435 if( i_stream_size <= p_sys->i_data_pos )
436 return VLC_EGENERIC;
438 const double i_bytemicrorate = (double) i_length / (i_stream_size - p_sys->i_data_pos);
439 if( i_bytemicrorate == 0 )
440 return VLC_EGENERIC;
442 uint64_t i_lower = p_sys->i_data_pos;
443 uint64_t i_upper = i_stream_size;
444 uint64_t i_start_pos;
446 assert( p_sys->i_seekpoint > 0 ); /* ReadMeta ensure at least (0,0) */
447 if( p_sys->i_seekpoint > 1 )
449 /* lookup base offset */
450 for( i = p_sys->i_seekpoint-1; i >= 0; i-- )
452 if( p_sys->seekpoint[i]->i_time_offset <= i_time )
453 break;
456 i_lower = p_sys->seekpoint[0]->i_byte_offset + p_sys->i_data_pos;
457 if( i+1 < p_sys->i_seekpoint )
458 i_upper = p_sys->seekpoint[i+1]->i_byte_offset + p_sys->i_data_pos;
460 i_start_pos = i_lower;
462 else
464 i_start_pos = i_time / i_bytemicrorate;
467 if( VLC_SUCCESS != vlc_stream_Seek( p_demux->s, i_start_pos ) )
468 return VLC_EGENERIC;
470 int i_ret = RefineSeek( p_demux, i_time, i_bytemicrorate, i_lower, i_upper );
471 if( i_ret == VLC_SUCCESS )
473 p_sys->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
474 Reset( p_sys );
475 es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_time );
478 return i_ret;
481 static int Control( demux_t *p_demux, int i_query, va_list args )
483 demux_sys_t *p_sys = p_demux->p_sys;
485 if( i_query == DEMUX_GET_META )
487 vlc_meta_t *p_meta = va_arg( args, vlc_meta_t * );
488 if( p_demux->p_sys->p_meta )
489 vlc_meta_Merge( p_meta, p_demux->p_sys->p_meta );
490 return VLC_SUCCESS;
492 else if( i_query == DEMUX_HAS_UNSUPPORTED_META )
494 bool *pb_bool = va_arg( args, bool* );
495 *pb_bool = true;
496 return VLC_SUCCESS;
498 else if( i_query == DEMUX_GET_LENGTH )
500 int64_t *pi64 = va_arg( args, int64_t * );
501 *pi64 = ControlGetLength( p_demux );
502 return VLC_SUCCESS;
504 else if( i_query == DEMUX_SET_TIME )
506 int64_t i_time = va_arg( args, int64_t );
507 return ControlSetTime( p_demux, i_time );
509 else if( i_query == DEMUX_SET_POSITION )
511 const double f = va_arg( args, double );
512 int64_t i_length = ControlGetLength( p_demux );
513 if( i_length > 0 )
514 return ControlSetTime( p_demux, i_length * f );
515 /* just byte pos seek */
516 int i_ret = vlc_stream_Seek( p_demux->s, (int64_t) (f * stream_Size( p_demux->s )) );
517 if( i_ret == VLC_SUCCESS )
519 p_sys->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
520 Reset( p_sys );
522 return i_ret;
524 else if( i_query == DEMUX_GET_TIME )
526 int64_t *pi64 = va_arg( args, int64_t * );
527 *pi64 = ControlGetTime( p_demux );
528 return VLC_SUCCESS;
530 else if( i_query == DEMUX_GET_POSITION )
532 const int64_t i_length = ControlGetLength(p_demux);
533 if( i_length > 0 )
535 double *pf = va_arg( args, double * );
536 double current = ControlGetTime(p_demux);
537 *pf = current / (double)i_length;
538 return VLC_SUCCESS;
540 /* Else fallback on byte position */
542 else if( i_query == DEMUX_GET_ATTACHMENTS )
544 input_attachment_t ***ppp_attach =
545 va_arg( args, input_attachment_t *** );
546 int *pi_int = va_arg( args, int * );
548 if( p_sys->i_attachments <= 0 )
549 return VLC_EGENERIC;
551 *ppp_attach = vlc_alloc( p_sys->i_attachments, sizeof(input_attachment_t*) );
552 if( !*ppp_attach )
553 return VLC_EGENERIC;
554 *pi_int = p_sys->i_attachments;
555 for( int i = 0; i < p_sys->i_attachments; i++ )
556 (*ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachments[i] );
557 return VLC_SUCCESS;
559 else if( i_query == DEMUX_GET_TITLE_INFO )
561 input_title_t ***ppp_title = va_arg( args, input_title_t *** );
562 int *pi_int = va_arg( args, int * );
563 int *pi_title_offset = va_arg( args, int * );
564 int *pi_seekpoint_offset = va_arg( args, int * );
566 if( !p_sys->i_title_seekpoints )
567 return VLC_EGENERIC;
569 *pi_int = 1;
570 *ppp_title = malloc( sizeof(input_title_t*) );
571 if(!*ppp_title)
572 return VLC_EGENERIC;
574 input_title_t *p_title = (*ppp_title)[0] = vlc_input_title_New();
575 if(!p_title)
577 free(*ppp_title);
578 return VLC_EGENERIC;
581 p_title->seekpoint = vlc_alloc( p_sys->i_title_seekpoints, sizeof(seekpoint_t*) );
582 if(!p_title->seekpoint)
584 vlc_input_title_Delete(p_title);
585 free(*ppp_title);
586 return VLC_EGENERIC;
589 p_title->i_seekpoint = p_sys->i_title_seekpoints;
590 for( int i = 0; i < p_title->i_seekpoint; i++ )
591 p_title->seekpoint[i] = vlc_seekpoint_Duplicate( p_sys->pp_title_seekpoints[i] );
593 *pi_title_offset = 0;
594 *pi_seekpoint_offset = 0;
596 return VLC_SUCCESS;
598 else if( i_query == DEMUX_SET_TITLE )
600 const int i_title = va_arg( args, int );
601 if( i_title != 0 )
602 return VLC_EGENERIC;
603 return VLC_SUCCESS;
605 else if( i_query == DEMUX_SET_SEEKPOINT )
607 const int i_seekpoint = va_arg( args, int );
608 if( !p_sys->i_title_seekpoints || i_seekpoint >= p_sys->i_title_seekpoints )
609 return VLC_EGENERIC;
610 return ControlSetTime( p_demux, p_sys->pp_title_seekpoints[i_seekpoint]->i_time_offset );
613 return demux_vaControlHelper( p_demux->s, p_sys->i_data_pos, -1,
614 8*0, 1, i_query, args );
617 enum
619 META_STREAMINFO = 0,
620 META_SEEKTABLE = 3,
621 META_COMMENT = 4,
622 META_PICTURE = 6,
625 static inline int Get24bBE( const uint8_t *p )
627 return (p[0] << 16)|(p[1] << 8)|(p[2]);
630 static void ParseStreamInfo( es_format_t *, uint64_t *pi_count );
631 static void ParseSeekTable( demux_t *p_demux, const uint8_t *p_data, size_t i_data,
632 unsigned i_sample_rate );
633 static void ParseComment( demux_t *, const uint8_t *p_data, size_t i_data );
634 static void ParsePicture( demux_t *, const uint8_t *p_data, size_t i_data );
636 static int ParseHeaders( demux_t *p_demux, es_format_t *p_fmt )
638 demux_sys_t *p_sys = p_demux->p_sys;
639 ssize_t i_peek;
640 const uint8_t *p_peek;
641 bool b_last;
642 uint64_t i_sample_count;
644 /* Be sure we have seekpoint 0 */
645 flac_seekpoint_t *s = xmalloc( sizeof (*s) );
646 s->i_time_offset = 0;
647 s->i_byte_offset = 0;
648 TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s );
650 uint8_t header[4];
651 if( vlc_stream_Read( p_demux->s, header, 4) < 4)
652 return VLC_EGENERIC;
654 if (memcmp(header, "fLaC", 4))
655 return VLC_EGENERIC;
657 b_last = 0;
658 while( !b_last )
660 int i_len;
661 int i_type;
663 i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 4 );
664 if( i_peek < 4 )
665 break;
666 b_last = p_peek[0]&0x80;
667 i_type = p_peek[0]&0x7f;
668 i_len = Get24bBE( &p_peek[1] );
670 if( i_type == META_STREAMINFO && p_fmt->p_extra == NULL )
672 if( i_len != STREAMINFO_SIZE ) {
673 msg_Err( p_demux, "invalid size %d for a STREAMINFO metadata block", i_len );
674 return VLC_EGENERIC;
677 p_fmt->p_extra = malloc( STREAMINFO_SIZE);
678 if( p_fmt->p_extra == NULL )
679 return VLC_EGENERIC;
681 if( vlc_stream_Read( p_demux->s, NULL, 4) < 4)
683 FREENULL( p_fmt->p_extra );
684 return VLC_EGENERIC;
686 if( vlc_stream_Read( p_demux->s, p_fmt->p_extra,
687 STREAMINFO_SIZE ) != STREAMINFO_SIZE )
689 msg_Err( p_demux, "failed to read STREAMINFO metadata block" );
690 FREENULL( p_fmt->p_extra );
691 return VLC_EGENERIC;
693 p_fmt->i_extra = STREAMINFO_SIZE;
695 /* */
696 ParseStreamInfo( p_fmt, &i_sample_count );
697 if( p_fmt->audio.i_rate > 0 )
698 p_sys->i_length = i_sample_count * CLOCK_FREQ / p_fmt->audio.i_rate;
699 continue;
701 else if( i_type == META_SEEKTABLE )
703 i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 4+i_len );
704 if( i_peek == 4+i_len )
705 ParseSeekTable( p_demux, p_peek, i_peek, p_fmt->audio.i_rate );
707 else if( i_type == META_COMMENT )
709 i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 4+i_len );
710 if( i_peek == 4+i_len )
711 ParseComment( p_demux, p_peek, i_peek );
713 else if( i_type == META_PICTURE )
715 i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 4+i_len );
716 if( i_peek == 4+i_len )
717 ParsePicture( p_demux, p_peek, i_peek );
720 if( vlc_stream_Read( p_demux->s, NULL, 4+i_len ) < 4+i_len )
721 break;
724 /* */
725 p_sys->i_data_pos = vlc_stream_Tell( p_demux->s );
727 if ( p_fmt->p_extra == NULL )
728 return VLC_EGENERIC;
730 return VLC_SUCCESS;
732 static void ParseStreamInfo( es_format_t *p_fmt, uint64_t *pi_count )
734 uint8_t *p_data = p_fmt->p_extra;
735 p_fmt->audio.i_rate = GetDWBE(&p_data[4+6]) >> 12;
736 p_fmt->audio.i_channels = (p_data[12] & 0x0F >> 1) + 1;
737 p_fmt->audio.i_bitspersample = ((p_data[12] & 0x01) << 4) | p_data[13] >> 4;
738 *pi_count = GetQWBE(&p_data[4+6]) & ((INT64_C(1)<<36)-1);
741 static void ParseSeekTable( demux_t *p_demux, const uint8_t *p_data, size_t i_data,
742 unsigned i_sample_rate )
744 demux_sys_t *p_sys = p_demux->p_sys;
745 flac_seekpoint_t *s;
746 size_t i;
748 if( i_sample_rate == 0 )
749 return;
751 /* */
752 for( i = 0; i < (i_data-4)/18; i++ )
754 const int64_t i_sample = GetQWBE( &p_data[4+18*i+0] );
755 int j;
757 if( i_sample < 0 || i_sample >= INT64_MAX )
758 continue;
760 s = xmalloc( sizeof (*s) );
761 s->i_time_offset = i_sample * CLOCK_FREQ / i_sample_rate;
762 s->i_byte_offset = GetQWBE( &p_data[4+18*i+8] );
764 /* Check for duplicate entry */
765 for( j = 0; j < p_sys->i_seekpoint; j++ )
767 if( p_sys->seekpoint[j]->i_time_offset == s->i_time_offset ||
768 p_sys->seekpoint[j]->i_byte_offset == s->i_byte_offset )
770 free( s );
771 s = NULL;
772 break;
775 if( s )
777 TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s );
780 /* TODO sort it by size and remove wrong seek entry (time not increasing) */
783 static void ParseComment( demux_t *p_demux, const uint8_t *p_data, size_t i_data )
785 demux_sys_t *p_sys = p_demux->p_sys;
787 if( i_data < 4 )
788 return;
790 vorbis_ParseComment( NULL, &p_sys->p_meta, &p_data[4], i_data - 4,
791 &p_sys->i_attachments, &p_sys->attachments,
792 &p_sys->i_cover_score, &p_sys->i_cover_idx,
793 &p_sys->i_title_seekpoints, &p_sys->pp_title_seekpoints, NULL, NULL );
796 static void ParsePicture( demux_t *p_demux, const uint8_t *p_data, size_t i_data )
798 demux_sys_t *p_sys = p_demux->p_sys;
800 i_data -= 4; p_data += 4;
802 input_attachment_t *p_attachment = ParseFlacPicture( p_data, i_data,
803 p_sys->i_attachments, &p_sys->i_cover_score, &p_sys->i_cover_idx );
804 if( p_attachment == NULL )
805 return;
807 TAB_APPEND( p_sys->i_attachments, p_sys->attachments, p_attachment );