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 */
42 #include "../packetizer/flac.h"
44 /*****************************************************************************
46 *****************************************************************************/
47 static int Open ( vlc_object_t
* );
48 static void Close ( vlc_object_t
* );
51 set_description( N_("FLAC demuxer") )
52 set_capability( "demux", 155 )
53 set_category( CAT_INPUT
)
54 set_subcategory( SUBCAT_INPUT_DEMUX
)
55 set_callbacks( Open
, Close
)
56 add_shortcut( "flac" )
59 /*****************************************************************************
61 *****************************************************************************/
62 static int Demux ( demux_t
* );
63 static int Control( demux_t
*, int, va_list );
65 static int ParseHeaders( demux_t
*, es_format_t
* );
69 vlc_tick_t i_time_offset
;
70 uint64_t i_byte_offset
;
76 int i_next_block_flags
;
78 block_t
*p_current_block
;
81 decoder_t
*p_packetizer
;
86 struct flac_stream_info stream_info
;
89 int64_t i_length
; /* Length from stream info */
94 flac_seekpoint_t
**seekpoint
;
96 /* title/chapters seekpoints */
97 int i_title_seekpoints
;
98 seekpoint_t
**pp_title_seekpoints
;
102 input_attachment_t
**attachments
;
107 #define FLAC_PACKET_SIZE 16384
108 #define FLAC_MAX_PREROLL VLC_TICK_FROM_SEC(4)
109 #define FLAC_MAX_SLOW_PREROLL VLC_TICK_FROM_SEC(45)
111 /*****************************************************************************
112 * Open: initializes ES structures
113 *****************************************************************************/
114 static int Open( vlc_object_t
* p_this
)
116 demux_t
*p_demux
= (demux_t
*)p_this
;
118 const uint8_t *p_peek
;
121 /* Have a peep at the show. */
122 if( vlc_stream_Peek( p_demux
->s
, &p_peek
, 4 ) < 4 ) return VLC_EGENERIC
;
124 if( p_peek
[0]!='f' || p_peek
[1]!='L' || p_peek
[2]!='a' || p_peek
[3]!='C' )
126 if( !p_demux
->obj
.force
127 && !demux_IsContentType( p_demux
, "audio/flac" ) )
131 msg_Err( p_demux
, "this doesn't look like a flac stream, "
132 "continuing anyway" );
135 p_sys
= malloc( sizeof( demux_sys_t
) );
136 if( unlikely(p_sys
== NULL
) )
139 p_demux
->pf_demux
= Demux
;
140 p_demux
->pf_control
= Control
;
141 p_demux
->p_sys
= p_sys
;
142 p_sys
->b_start
= true;
143 p_sys
->i_next_block_flags
= 0;
144 p_sys
->p_packetizer
= NULL
;
145 p_sys
->p_meta
= NULL
;
147 p_sys
->i_pts
= VLC_TICK_INVALID
;
148 p_sys
->b_stream_info
= false;
150 p_sys
->p_current_block
= NULL
;
151 TAB_INIT( p_sys
->i_seekpoint
, p_sys
->seekpoint
);
152 TAB_INIT( p_sys
->i_attachments
, p_sys
->attachments
);
153 TAB_INIT( p_sys
->i_title_seekpoints
, p_sys
->pp_title_seekpoints
);
154 p_sys
->i_cover_idx
= 0;
155 p_sys
->i_cover_score
= 0;
157 es_format_Init( &fmt
, AUDIO_ES
, VLC_CODEC_FLAC
);
159 /* We need to read and store the STREAMINFO metadata into fmt extra */
160 if( ParseHeaders( p_demux
, &fmt
) )
163 /* Load the FLAC packetizer */
164 p_sys
->p_packetizer
= demux_PacketizerNew( p_demux
, &fmt
, "flac" );
165 if( !p_sys
->p_packetizer
)
168 if( p_sys
->i_cover_idx
< p_sys
->i_attachments
)
172 p_sys
->p_meta
= vlc_meta_New();
173 snprintf( psz_url
, sizeof(psz_url
), "attachment://%s",
174 p_sys
->attachments
[p_sys
->i_cover_idx
]->psz_name
);
175 vlc_meta_Set( p_sys
->p_meta
, vlc_meta_ArtworkURL
, psz_url
);
178 p_sys
->p_es
= es_out_Add( p_demux
->out
, &p_sys
->p_packetizer
->fmt_in
);
188 /*****************************************************************************
189 * Close: frees unused data
190 *****************************************************************************/
191 static void Close( vlc_object_t
* p_this
)
193 demux_t
*p_demux
= (demux_t
*)p_this
;
194 demux_sys_t
*p_sys
= p_demux
->p_sys
;
196 if( p_sys
->p_current_block
)
197 block_Release( p_sys
->p_current_block
);
199 for( int i
= 0; i
< p_sys
->i_seekpoint
; i
++ )
200 free(p_sys
->seekpoint
[i
]);
201 TAB_CLEAN( p_sys
->i_seekpoint
, p_sys
->seekpoint
);
203 for( int i
= 0; i
< p_sys
->i_attachments
; i
++ )
204 vlc_input_attachment_Delete( p_sys
->attachments
[i
] );
205 TAB_CLEAN( p_sys
->i_attachments
, p_sys
->attachments
);
207 for( int i
= 0; i
< p_sys
->i_title_seekpoints
; i
++ )
208 vlc_seekpoint_Delete( p_sys
->pp_title_seekpoints
[i
] );
209 TAB_CLEAN( p_sys
->i_title_seekpoints
, p_sys
->pp_title_seekpoints
);
211 /* Delete the decoder */
212 if( p_sys
->p_packetizer
)
213 demux_PacketizerDestroy( p_sys
->p_packetizer
);
216 vlc_meta_Delete( p_sys
->p_meta
);
220 static block_t
*GetPacketizedBlock( decoder_t
*p_packetizer
,
221 const struct flac_stream_info
*streaminfo
,
222 block_t
**pp_current_block
)
224 block_t
*p_block
= p_packetizer
->pf_packetize( p_packetizer
, pp_current_block
);
227 if( p_block
->i_buffer
>= FLAC_HEADER_SIZE_MAX
)
229 struct flac_header_info headerinfo
;
230 int i_ret
= FLAC_ParseSyncInfo( p_block
->p_buffer
, streaminfo
, NULL
, &headerinfo
);
231 assert( i_ret
!= 0 ); /* Same as packetizer */
232 /* Use Frame PTS, not the interpolated one */
233 p_block
->i_dts
= p_block
->i_pts
= headerinfo
.i_pts
;
239 static void FlushPacketizer( decoder_t
*p_packetizer
)
241 if( p_packetizer
->pf_flush
)
242 p_packetizer
->pf_flush( p_packetizer
);
245 block_t
*p_block_out
;
246 while( (p_block_out
= p_packetizer
->pf_packetize( p_packetizer
, NULL
)) )
247 block_Release( p_block_out
);
251 static void Reset( demux_sys_t
*p_sys
)
253 p_sys
->i_pts
= VLC_TICK_INVALID
;
255 FlushPacketizer( p_sys
->p_packetizer
);
256 if( p_sys
->p_current_block
)
258 block_Release( p_sys
->p_current_block
);
259 p_sys
->p_current_block
= NULL
;
263 static int RefineSeek( demux_t
*p_demux
, vlc_tick_t i_time
, double i_bytemicrorate
,
264 uint64_t i_lowpos
, uint64_t i_highpos
)
266 demux_sys_t
*p_sys
= p_demux
->p_sys
;
267 bool b_found
= false;
268 block_t
*p_block_out
;
271 unsigned i_frame_size
= FLAC_FRAME_SIZE_MIN
;
273 bool b_canfastseek
= false;
274 (int) vlc_stream_Control( p_demux
->s
, STREAM_CAN_FASTSEEK
, &b_canfastseek
);
276 uint64_t i_start_pos
= vlc_stream_Tell( p_demux
->s
);
280 FlushPacketizer( p_sys
->p_packetizer
);
285 while( !p_block_out
)
289 if( !(p_block_in
= vlc_stream_Block( p_demux
->s
, i_frame_size
)) )
293 p_block_out
= GetPacketizedBlock( p_sys
->p_packetizer
,
294 p_sys
->b_stream_info
? &p_sys
->stream_info
: NULL
,
301 block_Release( p_block_in
);
305 if( p_block_out
->i_buffer
> i_frame_size
)
306 i_frame_size
= p_block_out
->i_buffer
;
308 /* If we are further than wanted block */
309 if( p_block_out
->i_dts
>= i_time
)
311 vlc_tick_t i_diff
= p_block_out
->i_dts
- i_time
;
312 /* Not in acceptable approximation range */
313 if( i_diff
> VLC_TICK_FROM_MS(100) && i_diff
/ i_bytemicrorate
> i_frame_size
)
315 i_highpos
= i_start_pos
;
316 i_start_pos
-= ( i_diff
/ i_bytemicrorate
);
317 i_start_pos
= __MAX(i_start_pos
, i_lowpos
+ i_frame_size
);
321 else if( p_block_out
->i_dts
< i_time
)
323 vlc_tick_t i_diff
= i_time
- p_block_out
->i_dts
;
324 /* Not in acceptable NEXT_TIME demux range */
325 if( i_diff
>= ((b_canfastseek
) ? FLAC_MAX_PREROLL
: FLAC_MAX_SLOW_PREROLL
) &&
326 i_diff
/ i_bytemicrorate
> i_frame_size
)
328 i_lowpos
= i_start_pos
;
329 i_start_pos
+= ( i_diff
/ i_bytemicrorate
);
330 i_start_pos
= __MIN(i_start_pos
, i_highpos
- i_frame_size
);
336 block_Release( p_block_out
);
338 block_Release( p_block_in
);
342 if( i_highpos
< i_lowpos
|| i_highpos
- i_lowpos
< i_frame_size
)
345 if( VLC_SUCCESS
!= vlc_stream_Seek( p_demux
->s
, i_start_pos
) )
350 return b_found
? VLC_SUCCESS
: VLC_EGENERIC
;
353 /*****************************************************************************
354 * Demux: reads and demuxes data packets
355 *****************************************************************************
356 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
357 *****************************************************************************/
358 static int Demux( demux_t
*p_demux
)
360 demux_sys_t
*p_sys
= p_demux
->p_sys
;
361 block_t
*p_block_out
;
364 if( p_sys
->p_current_block
== NULL
)
366 p_sys
->p_current_block
= vlc_stream_Block( p_demux
->s
, FLAC_PACKET_SIZE
);
367 b_eof
= (p_sys
->p_current_block
== NULL
);
370 if ( p_sys
->p_current_block
)
372 p_sys
->p_current_block
->i_flags
= p_sys
->i_next_block_flags
;
373 p_sys
->i_next_block_flags
= 0;
374 p_sys
->p_current_block
->i_pts
=
375 p_sys
->p_current_block
->i_dts
= p_sys
->b_start
? VLC_TICK_0
: VLC_TICK_INVALID
;
378 while( (p_block_out
= GetPacketizedBlock( p_sys
->p_packetizer
,
379 p_sys
->b_stream_info
? &p_sys
->stream_info
: NULL
,
380 p_sys
->p_current_block
? &p_sys
->p_current_block
: NULL
) ) )
382 /* Only clear on output when packet is accepted as sync #17111 */
383 p_sys
->b_start
= false;
386 block_t
*p_next
= p_block_out
->p_next
;
388 p_block_out
->p_next
= NULL
;
391 if( unlikely(p_sys
->i_pts
== VLC_TICK_INVALID
) )
392 es_out_SetPCR( p_demux
->out
, __MAX(p_block_out
->i_dts
- 1, VLC_TICK_0
) );
394 p_sys
->i_pts
= p_block_out
->i_dts
;
396 es_out_Send( p_demux
->out
, p_sys
->p_es
, p_block_out
);
398 es_out_SetPCR( p_demux
->out
, p_sys
->i_pts
);
400 p_block_out
= p_next
;
405 return b_eof
? VLC_DEMUXER_EOF
: VLC_DEMUXER_SUCCESS
;
408 /*****************************************************************************
410 *****************************************************************************/
411 static int64_t ControlGetLength( demux_t
*p_demux
)
413 demux_sys_t
*p_sys
= p_demux
->p_sys
;
414 const uint64_t i_size
= stream_Size(p_demux
->s
) - p_sys
->i_data_pos
;
415 int64_t i_length
= p_sys
->i_length
;
418 /* Try to fix length using seekpoint and current size for truncated file */
419 for( i
= p_sys
->i_seekpoint
-1; i
>= 0; i
-- )
421 flac_seekpoint_t
*s
= p_sys
->seekpoint
[i
];
422 if( s
->i_byte_offset
<= i_size
)
424 if( i
+1 < p_sys
->i_seekpoint
)
427 flac_seekpoint_t
*n
= p_sys
->seekpoint
[i
+1];
428 assert( n
->i_byte_offset
!= s
->i_byte_offset
); /* Should be ensured by ParseSeekTable */
429 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
);
437 static int64_t ControlGetTime( demux_t
*p_demux
)
439 demux_sys_t
*p_sys
= p_demux
->p_sys
;
443 static int ControlSetTime( demux_t
*p_demux
, int64_t i_time
)
445 demux_sys_t
*p_sys
= p_demux
->p_sys
;
450 vlc_stream_Control( p_demux
->s
, STREAM_CAN_SEEK
, &b_seekable
);
454 const vlc_tick_t i_length
= ControlGetLength( p_demux
);
458 const uint64_t i_stream_size
= stream_Size( p_demux
->s
);
459 if( i_stream_size
<= p_sys
->i_data_pos
)
462 const double i_bytemicrorate
= (double) i_length
/ (i_stream_size
- p_sys
->i_data_pos
);
463 if( i_bytemicrorate
== 0 )
466 uint64_t i_lower
= p_sys
->i_data_pos
;
467 uint64_t i_upper
= i_stream_size
;
468 uint64_t i_start_pos
;
470 assert( p_sys
->i_seekpoint
> 0 ); /* ReadMeta ensure at least (0,0) */
471 if( p_sys
->i_seekpoint
> 1 )
473 /* lookup base offset */
474 for( i
= p_sys
->i_seekpoint
-1; i
>= 0; i
-- )
476 if( p_sys
->seekpoint
[i
]->i_time_offset
<= i_time
)
480 i_lower
= p_sys
->seekpoint
[0]->i_byte_offset
+ p_sys
->i_data_pos
;
481 if( i
+1 < p_sys
->i_seekpoint
)
482 i_upper
= p_sys
->seekpoint
[i
+1]->i_byte_offset
+ p_sys
->i_data_pos
;
484 i_start_pos
= i_lower
;
488 i_start_pos
= i_time
/ i_bytemicrorate
;
491 if( VLC_SUCCESS
!= vlc_stream_Seek( p_demux
->s
, i_start_pos
) )
494 int i_ret
= RefineSeek( p_demux
, i_time
, i_bytemicrorate
, i_lower
, i_upper
);
495 if( i_ret
== VLC_SUCCESS
)
497 p_sys
->i_next_block_flags
|= BLOCK_FLAG_DISCONTINUITY
;
499 es_out_Control( p_demux
->out
, ES_OUT_SET_NEXT_DISPLAY_TIME
, i_time
);
505 static int Control( demux_t
*p_demux
, int i_query
, va_list args
)
507 demux_sys_t
*p_sys
= p_demux
->p_sys
;
509 if( i_query
== DEMUX_GET_META
)
511 vlc_meta_t
*p_meta
= va_arg( args
, vlc_meta_t
* );
513 vlc_meta_Merge( p_meta
, p_sys
->p_meta
);
516 else if( i_query
== DEMUX_HAS_UNSUPPORTED_META
)
518 bool *pb_bool
= va_arg( args
, bool* );
522 else if( i_query
== DEMUX_GET_LENGTH
)
524 int64_t *pi64
= va_arg( args
, int64_t * );
525 *pi64
= ControlGetLength( p_demux
);
528 else if( i_query
== DEMUX_SET_TIME
)
530 int64_t i_time
= va_arg( args
, int64_t );
531 return ControlSetTime( p_demux
, i_time
);
533 else if( i_query
== DEMUX_SET_POSITION
)
535 const double f
= va_arg( args
, double );
536 int64_t i_length
= ControlGetLength( p_demux
);
540 i_ret
= ControlSetTime( p_demux
, i_length
* f
);
541 if( i_ret
== VLC_SUCCESS
)
544 /* just byte pos seek */
545 i_ret
= vlc_stream_Seek( p_demux
->s
, (int64_t) (f
* stream_Size( p_demux
->s
)) );
546 if( i_ret
== VLC_SUCCESS
)
548 p_sys
->i_next_block_flags
|= BLOCK_FLAG_DISCONTINUITY
;
553 else if( i_query
== DEMUX_GET_TIME
)
555 int64_t *pi64
= va_arg( args
, int64_t * );
556 *pi64
= ControlGetTime( p_demux
);
559 else if( i_query
== DEMUX_GET_POSITION
)
561 const int64_t i_length
= ControlGetLength(p_demux
);
564 double current
= ControlGetTime(p_demux
);
565 if( current
<= i_length
)
567 *(va_arg( args
, double * )) = current
/ (double)i_length
;
571 /* Else fallback on byte position */
573 else if( i_query
== DEMUX_GET_ATTACHMENTS
)
575 input_attachment_t
***ppp_attach
=
576 va_arg( args
, input_attachment_t
*** );
577 int *pi_int
= va_arg( args
, int * );
579 if( p_sys
->i_attachments
<= 0 )
582 *ppp_attach
= vlc_alloc( p_sys
->i_attachments
, sizeof(input_attachment_t
*) );
585 *pi_int
= p_sys
->i_attachments
;
586 for( int i
= 0; i
< p_sys
->i_attachments
; i
++ )
587 (*ppp_attach
)[i
] = vlc_input_attachment_Duplicate( p_sys
->attachments
[i
] );
590 else if( i_query
== DEMUX_GET_TITLE_INFO
)
592 input_title_t
***ppp_title
= va_arg( args
, input_title_t
*** );
593 int *pi_int
= va_arg( args
, int * );
594 int *pi_title_offset
= va_arg( args
, int * );
595 int *pi_seekpoint_offset
= va_arg( args
, int * );
597 if( !p_sys
->i_title_seekpoints
)
601 *ppp_title
= malloc( sizeof(input_title_t
*) );
605 input_title_t
*p_title
= (*ppp_title
)[0] = vlc_input_title_New();
612 p_title
->seekpoint
= vlc_alloc( p_sys
->i_title_seekpoints
, sizeof(seekpoint_t
*) );
613 if(!p_title
->seekpoint
)
615 vlc_input_title_Delete(p_title
);
620 p_title
->i_seekpoint
= p_sys
->i_title_seekpoints
;
621 for( int i
= 0; i
< p_title
->i_seekpoint
; i
++ )
622 p_title
->seekpoint
[i
] = vlc_seekpoint_Duplicate( p_sys
->pp_title_seekpoints
[i
] );
624 *pi_title_offset
= 0;
625 *pi_seekpoint_offset
= 0;
629 else if( i_query
== DEMUX_SET_TITLE
)
631 const int i_title
= va_arg( args
, int );
636 else if( i_query
== DEMUX_SET_SEEKPOINT
)
638 const int i_seekpoint
= va_arg( args
, int );
639 if( !p_sys
->i_title_seekpoints
|| i_seekpoint
>= p_sys
->i_title_seekpoints
)
641 return ControlSetTime( p_demux
, p_sys
->pp_title_seekpoints
[i_seekpoint
]->i_time_offset
);
644 return demux_vaControlHelper( p_demux
->s
, p_sys
->i_data_pos
, -1,
645 8*0, 1, i_query
, args
);
656 static inline int Get24bBE( const uint8_t *p
)
658 return (p
[0] << 16)|(p
[1] << 8)|(p
[2]);
661 static void ParseSeekTable( demux_t
*p_demux
, const uint8_t *p_data
, size_t i_data
,
662 unsigned i_sample_rate
);
663 static void ParseComment( demux_t
*, const uint8_t *p_data
, size_t i_data
);
664 static void ParsePicture( demux_t
*, const uint8_t *p_data
, size_t i_data
);
666 static int ParseHeaders( demux_t
*p_demux
, es_format_t
*p_fmt
)
668 demux_sys_t
*p_sys
= p_demux
->p_sys
;
670 const uint8_t *p_peek
;
673 /* Be sure we have seekpoint 0 */
674 flac_seekpoint_t
*s
= xmalloc( sizeof (*s
) );
675 s
->i_time_offset
= 0;
676 s
->i_byte_offset
= 0;
677 TAB_APPEND( p_sys
->i_seekpoint
, p_sys
->seekpoint
, s
);
680 if( vlc_stream_Read( p_demux
->s
, header
, 4) < 4)
683 if (memcmp(header
, "fLaC", 4))
692 i_peek
= vlc_stream_Peek( p_demux
->s
, &p_peek
, 4 );
695 b_last
= p_peek
[0]&0x80;
696 i_type
= p_peek
[0]&0x7f;
697 i_len
= Get24bBE( &p_peek
[1] );
699 if( i_type
== META_STREAMINFO
&& p_fmt
->p_extra
== NULL
)
701 if( i_len
!= FLAC_STREAMINFO_SIZE
) {
702 msg_Err( p_demux
, "invalid size %d for a STREAMINFO metadata block", i_len
);
706 p_fmt
->p_extra
= malloc( FLAC_STREAMINFO_SIZE
);
707 if( p_fmt
->p_extra
== NULL
)
710 if( vlc_stream_Read( p_demux
->s
, NULL
, 4) < 4)
712 FREENULL( p_fmt
->p_extra
);
715 if( vlc_stream_Read( p_demux
->s
, p_fmt
->p_extra
,
716 FLAC_STREAMINFO_SIZE
) != FLAC_STREAMINFO_SIZE
)
718 msg_Err( p_demux
, "failed to read STREAMINFO metadata block" );
719 FREENULL( p_fmt
->p_extra
);
722 p_fmt
->i_extra
= FLAC_STREAMINFO_SIZE
;
725 p_sys
->b_stream_info
= true;
726 FLAC_ParseStreamInfo( (uint8_t *) p_fmt
->p_extra
, &p_sys
->stream_info
);
728 p_fmt
->audio
.i_rate
= p_sys
->stream_info
.sample_rate
;
729 p_fmt
->audio
.i_channels
= p_sys
->stream_info
.channels
;
730 p_fmt
->audio
.i_bitspersample
= p_sys
->stream_info
.bits_per_sample
;
731 if( p_sys
->stream_info
.sample_rate
> 0 )
732 p_sys
->i_length
= p_sys
->stream_info
.total_samples
* CLOCK_FREQ
733 / p_sys
->stream_info
.sample_rate
;
737 else if( i_type
== META_SEEKTABLE
)
739 i_peek
= vlc_stream_Peek( p_demux
->s
, &p_peek
, 4+i_len
);
740 if( i_peek
== 4+i_len
)
741 ParseSeekTable( p_demux
, p_peek
, i_peek
, p_fmt
->audio
.i_rate
);
743 else if( i_type
== META_COMMENT
)
745 i_peek
= vlc_stream_Peek( p_demux
->s
, &p_peek
, 4+i_len
);
746 if( i_peek
== 4+i_len
)
747 ParseComment( p_demux
, p_peek
, i_peek
);
749 else if( i_type
== META_PICTURE
)
751 i_peek
= vlc_stream_Peek( p_demux
->s
, &p_peek
, 4+i_len
);
752 if( i_peek
== 4+i_len
)
753 ParsePicture( p_demux
, p_peek
, i_peek
);
756 if( vlc_stream_Read( p_demux
->s
, NULL
, 4+i_len
) < 4+i_len
)
761 p_sys
->i_data_pos
= vlc_stream_Tell( p_demux
->s
);
763 if ( p_fmt
->p_extra
== NULL
)
769 static void ParseSeekTable( demux_t
*p_demux
, const uint8_t *p_data
, size_t i_data
,
770 unsigned i_sample_rate
)
772 demux_sys_t
*p_sys
= p_demux
->p_sys
;
776 if( i_sample_rate
== 0 )
780 for( i
= 0; i
< (i_data
-4)/18; i
++ )
782 const int64_t i_sample
= GetQWBE( &p_data
[4+18*i
+0] );
785 if( i_sample
< 0 || i_sample
>= INT64_MAX
||
786 GetQWBE( &p_data
[4+18*i
+8] ) < FLAC_STREAMINFO_SIZE
)
789 s
= xmalloc( sizeof (*s
) );
790 s
->i_time_offset
= i_sample
* CLOCK_FREQ
/ i_sample_rate
;
791 s
->i_byte_offset
= GetQWBE( &p_data
[4+18*i
+8] );
793 /* Check for duplicate entry */
794 for( j
= 0; j
< p_sys
->i_seekpoint
; j
++ )
796 if( p_sys
->seekpoint
[j
]->i_time_offset
== s
->i_time_offset
||
797 p_sys
->seekpoint
[j
]->i_byte_offset
== s
->i_byte_offset
)
806 TAB_APPEND( p_sys
->i_seekpoint
, p_sys
->seekpoint
, s
);
809 /* TODO sort it by size and remove wrong seek entry (time not increasing) */
812 static void ParseComment( demux_t
*p_demux
, const uint8_t *p_data
, size_t i_data
)
814 demux_sys_t
*p_sys
= p_demux
->p_sys
;
819 vorbis_ParseComment( NULL
, &p_sys
->p_meta
, &p_data
[4], i_data
- 4,
820 &p_sys
->i_attachments
, &p_sys
->attachments
,
821 &p_sys
->i_cover_score
, &p_sys
->i_cover_idx
,
822 &p_sys
->i_title_seekpoints
, &p_sys
->pp_title_seekpoints
, NULL
, NULL
);
825 static void ParsePicture( demux_t
*p_demux
, const uint8_t *p_data
, size_t i_data
)
827 demux_sys_t
*p_sys
= p_demux
->p_sys
;
829 i_data
-= 4; p_data
+= 4;
831 input_attachment_t
*p_attachment
= ParseFlacPicture( p_data
, i_data
,
832 p_sys
->i_attachments
, &p_sys
->i_cover_score
, &p_sys
->i_cover_idx
);
833 if( p_attachment
== NULL
)
836 TAB_APPEND( p_sys
->i_attachments
, p_sys
->attachments
, p_attachment
);