1 /*****************************************************************************
2 * flac.c : FLAC demux module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001-2008 VLC authors and VideoLAN
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 /*****************************************************************************
27 *****************************************************************************/
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 */
41 #include "xiph_metadata.h" /* vorbis comments */
43 /*****************************************************************************
45 *****************************************************************************/
46 static int Open ( vlc_object_t
* );
47 static void Close ( vlc_object_t
* );
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" )
58 /*****************************************************************************
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
* );
68 mtime_t i_time_offset
;
69 uint64_t i_byte_offset
;
75 int i_next_block_flags
;
77 block_t
*p_current_block
;
80 decoder_t
*p_packetizer
;
86 int64_t i_length
; /* Length from stream info */
91 flac_seekpoint_t
**seekpoint
;
93 /* title/chapters seekpoints */
94 int i_title_seekpoints
;
95 seekpoint_t
**pp_title_seekpoints
;
99 input_attachment_t
**attachments
;
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
;
117 const uint8_t *p_peek
;
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" ) )
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
) )
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
;
146 p_sys
->i_pts
= VLC_TS_INVALID
;
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
) )
161 /* Load the FLAC packetizer */
162 p_sys
->p_packetizer
= demux_PacketizerNew( p_demux
, &fmt
, "flac" );
163 if( !p_sys
->p_packetizer
)
166 if( p_sys
->i_cover_idx
< p_sys
->i_attachments
)
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
);
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
);
214 vlc_meta_Delete( p_sys
->p_meta
);
218 static void FlushPacketizer( decoder_t
*p_packetizer
)
220 if( p_packetizer
->pf_flush
)
221 p_packetizer
->pf_flush( p_packetizer
);
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
;
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
);
259 FlushPacketizer( p_sys
->p_packetizer
);
264 while( !p_block_out
)
268 if( !(p_block_in
= vlc_stream_Block( p_demux
->s
, i_frame_size
)) )
272 p_block_out
= p_sys
->p_packetizer
->pf_packetize( p_sys
->p_packetizer
, &p_block_in
);
278 block_Release( p_block_in
);
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
);
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
);
313 block_Release( p_block_out
);
315 block_Release( p_block_in
);
319 if( i_highpos
< i_lowpos
|| i_highpos
- i_lowpos
< i_frame_size
)
322 if( VLC_SUCCESS
!= vlc_stream_Seek( p_demux
->s
, i_start_pos
) )
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
;
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;
362 block_t
*p_next
= p_block_out
->p_next
;
364 p_block_out
->p_next
= NULL
;
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
;
381 return b_eof
? VLC_DEMUXER_EOF
: VLC_DEMUXER_SUCCESS
;
384 /*****************************************************************************
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
;
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
)
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
);
413 static int64_t ControlGetTime( demux_t
*p_demux
)
415 demux_sys_t
*p_sys
= p_demux
->p_sys
;
419 static int ControlSetTime( demux_t
*p_demux
, int64_t i_time
)
421 demux_sys_t
*p_sys
= p_demux
->p_sys
;
426 vlc_stream_Control( p_demux
->s
, STREAM_CAN_SEEK
, &b_seekable
);
430 const mtime_t i_length
= ControlGetLength( p_demux
);
434 const uint64_t i_stream_size
= stream_Size( p_demux
->s
);
435 if( i_stream_size
<= p_sys
->i_data_pos
)
438 const double i_bytemicrorate
= (double) i_length
/ (i_stream_size
- p_sys
->i_data_pos
);
439 if( i_bytemicrorate
== 0 )
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
)
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
;
464 i_start_pos
= i_time
/ i_bytemicrorate
;
467 if( VLC_SUCCESS
!= vlc_stream_Seek( p_demux
->s
, i_start_pos
) )
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
;
475 es_out_Control( p_demux
->out
, ES_OUT_SET_NEXT_DISPLAY_TIME
, i_time
);
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
);
492 else if( i_query
== DEMUX_HAS_UNSUPPORTED_META
)
494 bool *pb_bool
= va_arg( args
, bool* );
498 else if( i_query
== DEMUX_GET_LENGTH
)
500 int64_t *pi64
= va_arg( args
, int64_t * );
501 *pi64
= ControlGetLength( p_demux
);
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
);
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
;
524 else if( i_query
== DEMUX_GET_TIME
)
526 int64_t *pi64
= va_arg( args
, int64_t * );
527 *pi64
= ControlGetTime( p_demux
);
530 else if( i_query
== DEMUX_GET_POSITION
)
532 const int64_t i_length
= ControlGetLength(p_demux
);
535 double *pf
= va_arg( args
, double * );
536 double current
= ControlGetTime(p_demux
);
537 *pf
= current
/ (double)i_length
;
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 )
551 *ppp_attach
= vlc_alloc( p_sys
->i_attachments
, sizeof(input_attachment_t
*) );
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
] );
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
)
570 *ppp_title
= malloc( sizeof(input_title_t
*) );
574 input_title_t
*p_title
= (*ppp_title
)[0] = vlc_input_title_New();
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
);
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;
598 else if( i_query
== DEMUX_SET_TITLE
)
600 const int i_title
= va_arg( args
, int );
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
)
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
);
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
;
640 const uint8_t *p_peek
;
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
);
651 if( vlc_stream_Read( p_demux
->s
, header
, 4) < 4)
654 if (memcmp(header
, "fLaC", 4))
663 i_peek
= vlc_stream_Peek( p_demux
->s
, &p_peek
, 4 );
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
);
677 p_fmt
->p_extra
= malloc( STREAMINFO_SIZE
);
678 if( p_fmt
->p_extra
== NULL
)
681 if( vlc_stream_Read( p_demux
->s
, NULL
, 4) < 4)
683 FREENULL( p_fmt
->p_extra
);
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
);
693 p_fmt
->i_extra
= STREAMINFO_SIZE
;
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
;
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
)
725 p_sys
->i_data_pos
= vlc_stream_Tell( p_demux
->s
);
727 if ( p_fmt
->p_extra
== NULL
)
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
;
748 if( i_sample_rate
== 0 )
752 for( i
= 0; i
< (i_data
-4)/18; i
++ )
754 const int64_t i_sample
= GetQWBE( &p_data
[4+18*i
+0] );
757 if( i_sample
< 0 || i_sample
>= INT64_MAX
)
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
)
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
;
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
)
807 TAB_APPEND( p_sys
->i_attachments
, p_sys
->attachments
, p_attachment
);