1 /*****************************************************************************
2 * flac.c : FLAC demux module for vlc
3 *****************************************************************************
4 * Copyright (C) 2001-2008 the VideoLAN team
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
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 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 General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, 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 "vorbis.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 ReadMeta( demux_t
*, uint8_t **pp_streaminfo
, int *pi_streaminfo
);
72 decoder_t
*p_packetizer
;
75 audio_replay_gain_t replay_gain
;
77 int64_t i_time_offset
;
81 int64_t i_length
; /* Length from stream info */
86 seekpoint_t
**seekpoint
;
90 input_attachment_t
**attachments
;
95 #define STREAMINFO_SIZE 38
96 #define FLAC_PACKET_SIZE 16384
98 /*****************************************************************************
99 * Open: initializes ES structures
100 *****************************************************************************/
101 static int Open( vlc_object_t
* p_this
)
103 demux_t
*p_demux
= (demux_t
*)p_this
;
105 const uint8_t *p_peek
;
106 uint8_t *p_streaminfo
;
110 /* Have a peep at the show. */
111 if( stream_Peek( p_demux
->s
, &p_peek
, 4 ) < 4 ) return VLC_EGENERIC
;
113 if( p_peek
[0]!='f' || p_peek
[1]!='L' || p_peek
[2]!='a' || p_peek
[3]!='C' )
115 if( !p_demux
->b_force
) return VLC_EGENERIC
;
118 msg_Err( p_demux
, "this doesn't look like a flac stream, "
119 "continuing anyway" );
122 p_sys
= malloc( sizeof( demux_sys_t
) );
123 if( unlikely(p_sys
== NULL
) )
126 p_demux
->pf_demux
= Demux
;
127 p_demux
->pf_control
= Control
;
128 p_demux
->p_sys
= p_sys
;
129 p_sys
->b_start
= true;
130 p_sys
->p_meta
= NULL
;
131 memset( &p_sys
->replay_gain
, 0, sizeof(p_sys
->replay_gain
) );
133 p_sys
->i_time_offset
= 0;
135 p_sys
->i_pts_start
= 0;
137 TAB_INIT( p_sys
->i_seekpoint
, p_sys
->seekpoint
);
138 TAB_INIT( p_sys
->i_attachments
, p_sys
->attachments
);
139 p_sys
->i_cover_idx
= 0;
140 p_sys
->i_cover_score
= 0;
142 /* We need to read and store the STREAMINFO metadata */
143 if( ReadMeta( p_demux
, &p_streaminfo
, &i_streaminfo
) )
149 /* Load the FLAC packetizer */
150 /* Store STREAMINFO for the decoder and packetizer */
151 p_streaminfo
[4] |= 0x80; /* Fake this as the last metadata block */
152 es_format_Init( &fmt
, AUDIO_ES
, VLC_CODEC_FLAC
);
153 fmt
.i_extra
= i_streaminfo
;
154 fmt
.p_extra
= p_streaminfo
;
156 p_sys
->p_packetizer
= demux_PacketizerNew( p_demux
, &fmt
, "flac" );
157 if( !p_sys
->p_packetizer
)
163 if( p_sys
->i_cover_idx
< p_sys
->i_attachments
)
167 p_sys
->p_meta
= vlc_meta_New();
168 snprintf( psz_url
, sizeof(psz_url
), "attachment://%s",
169 p_sys
->attachments
[p_sys
->i_cover_idx
]->psz_name
);
170 vlc_meta_Set( p_sys
->p_meta
, vlc_meta_ArtworkURL
, psz_url
);
172 vlc_audio_replay_gain_MergeFromMeta( &p_sys
->replay_gain
, p_sys
->p_meta
);
176 /*****************************************************************************
177 * Close: frees unused data
178 *****************************************************************************/
179 static void Close( vlc_object_t
* p_this
)
181 demux_t
*p_demux
= (demux_t
*)p_this
;
182 demux_sys_t
*p_sys
= p_demux
->p_sys
;
184 TAB_CLEAN( p_sys
->i_seekpoint
, p_sys
->seekpoint
);
187 for( i
= 0; i
< p_sys
->i_attachments
; i
++ )
188 free( p_sys
->attachments
[i
] );
189 TAB_CLEAN( p_sys
->i_attachments
, p_sys
->attachments
);
191 /* Delete the decoder */
192 demux_PacketizerDestroy( p_sys
->p_packetizer
);
195 vlc_meta_Delete( p_sys
->p_meta
);
199 /*****************************************************************************
200 * Demux: reads and demuxes data packets
201 *****************************************************************************
202 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
203 *****************************************************************************/
204 static int Demux( demux_t
*p_demux
)
206 demux_sys_t
*p_sys
= p_demux
->p_sys
;
207 block_t
*p_block_in
, *p_block_out
;
209 if( !( p_block_in
= stream_Block( p_demux
->s
, FLAC_PACKET_SIZE
) ) )
212 p_block_in
->i_pts
= p_block_in
->i_dts
= p_sys
->b_start
? VLC_TS_0
: VLC_TS_INVALID
;
213 p_sys
->b_start
= false;
215 while( (p_block_out
= p_sys
->p_packetizer
->pf_packetize(
216 p_sys
->p_packetizer
, &p_block_in
)) )
220 block_t
*p_next
= p_block_out
->p_next
;
222 p_block_out
->p_next
= NULL
;
224 if( p_sys
->p_es
== NULL
)
226 p_sys
->p_packetizer
->fmt_out
.b_packetized
= true;
227 p_sys
->p_packetizer
->fmt_out
.audio_replay_gain
= p_sys
->replay_gain
;
228 p_sys
->p_es
= es_out_Add( p_demux
->out
, &p_sys
->p_packetizer
->fmt_out
);
231 p_sys
->i_pts
= p_block_out
->i_dts
- VLC_TS_0
;
233 /* Correct timestamp */
234 p_block_out
->i_pts
+= p_sys
->i_time_offset
;
235 p_block_out
->i_dts
+= p_sys
->i_time_offset
;
238 es_out_Control( p_demux
->out
, ES_OUT_SET_PCR
, p_block_out
->i_dts
);
240 es_out_Send( p_demux
->out
, p_sys
->p_es
, p_block_out
);
242 p_block_out
= p_next
;
248 /*****************************************************************************
250 *****************************************************************************/
251 static int64_t ControlGetLength( demux_t
*p_demux
)
253 demux_sys_t
*p_sys
= p_demux
->p_sys
;
254 const int64_t i_size
= stream_Size(p_demux
->s
) - p_sys
->i_data_pos
;
255 int64_t i_length
= p_sys
->i_length
;
258 /* Try to fix length using seekpoint and current size for truncated file */
259 for( i
= p_sys
->i_seekpoint
-1; i
>= 0; i
-- )
261 seekpoint_t
*s
= p_sys
->seekpoint
[i
];
262 if( s
->i_byte_offset
<= i_size
)
264 if( i
+1 < p_sys
->i_seekpoint
)
267 seekpoint_t
*n
= p_sys
->seekpoint
[i
+1];
268 assert( n
->i_byte_offset
!= s
->i_byte_offset
); /* Should be ensured by ParseSeekTable */
269 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
);
277 static int64_t ControlGetTime( demux_t
*p_demux
)
279 demux_sys_t
*p_sys
= p_demux
->p_sys
;
280 return __MAX(p_sys
->i_pts
, p_sys
->i_pts_start
) + p_sys
->i_time_offset
;
283 static int ControlSetTime( demux_t
*p_demux
, int64_t i_time
)
285 demux_sys_t
*p_sys
= p_demux
->p_sys
;
286 int64_t i_delta_time
;
291 stream_Control( p_demux
->s
, STREAM_CAN_SEEK
, &b_seekable
);
296 assert( p_sys
->i_seekpoint
> 0 ); /* ReadMeta ensure at least (0,0) */
297 for( i
= p_sys
->i_seekpoint
-1; i
>= 0; i
-- )
299 if( p_sys
->seekpoint
[i
]->i_time_offset
<= i_time
)
302 i_delta_time
= i_time
- p_sys
->seekpoint
[i
]->i_time_offset
;
304 /* XXX We do exact seek if it's not too far away(45s) */
305 if( i_delta_time
< 45*INT64_C(1000000) )
307 if( stream_Seek( p_demux
->s
, p_sys
->seekpoint
[i
]->i_byte_offset
+p_sys
->i_data_pos
) )
310 p_sys
->i_time_offset
= p_sys
->seekpoint
[i
]->i_time_offset
- p_sys
->i_pts
;
311 p_sys
->i_pts_start
= p_sys
->i_pts
+i_delta_time
;
312 es_out_Control( p_demux
->out
, ES_OUT_SET_NEXT_DISPLAY_TIME
, p_sys
->i_pts_start
+ p_sys
->i_time_offset
);
316 int64_t i_delta_offset
;
318 int64_t i_next_offset
;
320 if( i
+1 < p_sys
->i_seekpoint
)
322 i_next_time
= p_sys
->seekpoint
[i
+1]->i_time_offset
;
323 i_next_offset
= p_sys
->seekpoint
[i
+1]->i_byte_offset
;
327 i_next_time
= p_sys
->i_length
;
328 i_next_offset
= stream_Size(p_demux
->s
)-p_sys
->i_data_pos
;
332 if( i_next_time
-p_sys
->seekpoint
[i
]->i_time_offset
> 0 )
333 i_delta_offset
= (i_next_offset
- p_sys
->seekpoint
[i
]->i_byte_offset
) * i_delta_time
/
334 (i_next_time
-p_sys
->seekpoint
[i
]->i_time_offset
);
336 if( stream_Seek( p_demux
->s
, p_sys
->seekpoint
[i
]->i_byte_offset
+p_sys
->i_data_pos
+ i_delta_offset
) )
339 p_sys
->i_pts_start
= p_sys
->i_pts
;
340 p_sys
->i_time_offset
= (p_sys
->seekpoint
[i
]->i_time_offset
+i_delta_time
) - p_sys
->i_pts
;
345 static int Control( demux_t
*p_demux
, int i_query
, va_list args
)
347 demux_sys_t
*p_sys
= p_demux
->p_sys
;
349 if( i_query
== DEMUX_GET_META
)
351 vlc_meta_t
*p_meta
= (vlc_meta_t
*)va_arg( args
, vlc_meta_t
* );
352 if( p_demux
->p_sys
->p_meta
)
353 vlc_meta_Merge( p_meta
, p_demux
->p_sys
->p_meta
);
356 else if( i_query
== DEMUX_HAS_UNSUPPORTED_META
)
358 bool *pb_bool
= (bool*)va_arg( args
, bool* );
362 else if( i_query
== DEMUX_GET_LENGTH
)
364 int64_t *pi64
= (int64_t*)va_arg( args
, int64_t * );
365 *pi64
= ControlGetLength( p_demux
);
368 else if( i_query
== DEMUX_SET_TIME
)
370 int64_t i_time
= (int64_t)va_arg( args
, int64_t );
371 return ControlSetTime( p_demux
, i_time
);
373 else if( i_query
== DEMUX_SET_POSITION
)
375 const double f
= (double)va_arg( args
, double );
376 int64_t i_time
= f
* ControlGetLength( p_demux
);
377 return ControlSetTime( p_demux
, i_time
);
379 else if( i_query
== DEMUX_GET_TIME
)
381 int64_t *pi64
= (int64_t*)va_arg( args
, int64_t * );
382 *pi64
= ControlGetTime( p_demux
);
385 else if( i_query
== DEMUX_GET_POSITION
)
387 double *pf
= (double*)va_arg( args
, double * );
388 const int64_t i_length
= ControlGetLength(p_demux
);
391 double current
= ControlGetTime(p_demux
);
392 *pf
= current
/ (double)i_length
;
398 else if( i_query
== DEMUX_GET_ATTACHMENTS
)
400 input_attachment_t
***ppp_attach
=
401 (input_attachment_t
***)va_arg( args
, input_attachment_t
*** );
402 int *pi_int
= (int*)va_arg( args
, int * );
405 if( p_sys
->i_attachments
<= 0 )
408 *pi_int
= p_sys
->i_attachments
;;
409 *ppp_attach
= xmalloc( sizeof(input_attachment_t
**) * p_sys
->i_attachments
);
410 for( i
= 0; i
< p_sys
->i_attachments
; i
++ )
411 (*ppp_attach
)[i
] = vlc_input_attachment_Duplicate( p_sys
->attachments
[i
] );
415 return demux_vaControlHelper( p_demux
->s
, p_sys
->i_data_pos
, -1,
416 8*0, 1, i_query
, args
);
427 static inline int Get24bBE( const uint8_t *p
)
429 return (p
[0] << 16)|(p
[1] << 8)|(p
[2]);
432 static void ParseStreamInfo( int *pi_rate
, int64_t *pi_count
, uint8_t *p_data
);
433 static void ParseSeekTable( demux_t
*p_demux
, const uint8_t *p_data
, int i_data
,
435 static void ParseComment( demux_t
*, const uint8_t *p_data
, int i_data
);
436 static void ParsePicture( demux_t
*, const uint8_t *p_data
, int i_data
);
438 static int ReadMeta( demux_t
*p_demux
, uint8_t **pp_streaminfo
, int *pi_streaminfo
)
440 demux_sys_t
*p_sys
= p_demux
->p_sys
;
442 const uint8_t *p_peek
;
445 int64_t i_sample_count
;
448 /* Read STREAMINFO */
449 i_peek
= stream_Peek( p_demux
->s
, &p_peek
, 8 );
450 if( (p_peek
[4] & 0x7F) != META_STREAMINFO
)
452 msg_Err( p_demux
, "this isn't a STREAMINFO metadata block" );
455 if( Get24bBE(&p_peek
[5]) != (STREAMINFO_SIZE
- 4) )
457 msg_Err( p_demux
, "invalid size for a STREAMINFO metadata block" );
461 *pi_streaminfo
= 4 + STREAMINFO_SIZE
;
462 *pp_streaminfo
= malloc( 4 + STREAMINFO_SIZE
);
463 if( *pp_streaminfo
== NULL
)
466 if( stream_Read( p_demux
->s
, *pp_streaminfo
, 4+STREAMINFO_SIZE
) != 4+STREAMINFO_SIZE
)
468 msg_Err( p_demux
, "failed to read STREAMINFO metadata block" );
469 free( *pp_streaminfo
);
474 ParseStreamInfo( &i_sample_rate
, &i_sample_count
, *pp_streaminfo
);
475 if( i_sample_rate
> 0 )
476 p_sys
->i_length
= i_sample_count
* INT64_C(1000000)/i_sample_rate
;
478 /* Be sure we have seekpoint 0 */
479 s
= vlc_seekpoint_New();
480 s
->i_time_offset
= 0;
481 s
->i_byte_offset
= 0;
482 TAB_APPEND( p_sys
->i_seekpoint
, p_sys
->seekpoint
, s
);
484 b_last
= (*pp_streaminfo
)[4]&0x80;
490 i_peek
= stream_Peek( p_demux
->s
, &p_peek
, 4 );
493 b_last
= p_peek
[0]&0x80;
494 i_type
= p_peek
[0]&0x7f;
495 i_len
= Get24bBE( &p_peek
[1] );
497 if( i_type
== META_SEEKTABLE
)
499 i_peek
= stream_Peek( p_demux
->s
, &p_peek
, 4+i_len
);
500 if( i_peek
== 4+i_len
)
501 ParseSeekTable( p_demux
, p_peek
, i_peek
, i_sample_rate
);
503 else if( i_type
== META_COMMENT
)
505 i_peek
= stream_Peek( p_demux
->s
, &p_peek
, 4+i_len
);
506 if( i_peek
== 4+i_len
)
507 ParseComment( p_demux
, p_peek
, i_peek
);
509 else if( i_type
== META_PICTURE
)
511 i_peek
= stream_Peek( p_demux
->s
, &p_peek
, 4+i_len
);
512 if( i_peek
== 4+i_len
)
513 ParsePicture( p_demux
, p_peek
, i_peek
);
516 if( stream_Read( p_demux
->s
, NULL
, 4+i_len
) < 4+i_len
)
521 p_sys
->i_data_pos
= stream_Tell( p_demux
->s
);
525 static void ParseStreamInfo( int *pi_rate
, int64_t *pi_count
, uint8_t *p_data
)
527 const int i_skip
= 4+4;
529 *pi_rate
= GetDWBE(&p_data
[i_skip
+4+6]) >> 12;
530 *pi_count
= GetQWBE(&p_data
[i_skip
+4+6]) & ((INT64_C(1)<<36)-1);
533 static void ParseSeekTable( demux_t
*p_demux
, const uint8_t *p_data
, int i_data
,
536 demux_sys_t
*p_sys
= p_demux
->p_sys
;
540 if( i_sample_rate
<= 0 )
544 for( i
= 0; i
< (i_data
-4)/18; i
++ )
546 const int64_t i_sample
= GetQWBE( &p_data
[4+18*i
+0] );
549 if( i_sample
< 0 || i_sample
>= INT64_MAX
)
552 s
= vlc_seekpoint_New();
553 s
->i_time_offset
= i_sample
* INT64_C(1000000)/i_sample_rate
;
554 s
->i_byte_offset
= GetQWBE( &p_data
[4+18*i
+8] );
556 /* Check for duplicate entry */
557 for( j
= 0; j
< p_sys
->i_seekpoint
; j
++ )
559 if( p_sys
->seekpoint
[j
]->i_time_offset
== s
->i_time_offset
||
560 p_sys
->seekpoint
[j
]->i_byte_offset
== s
->i_byte_offset
)
562 vlc_seekpoint_Delete( s
);
569 TAB_APPEND( p_sys
->i_seekpoint
, p_sys
->seekpoint
, s
);
572 /* TODO sort it by size and remove wrong seek entry (time not increasing) */
575 #define RM(x) do { i_data -= (x); p_data += (x); } while(0)
576 static void ParseComment( demux_t
*p_demux
, const uint8_t *p_data
, int i_data
)
578 demux_sys_t
*p_sys
= p_demux
->p_sys
;
583 vorbis_ParseComment( &p_sys
->p_meta
, &p_data
[4], i_data
- 4 );
587 static void ParsePicture( demux_t
*p_demux
, const uint8_t *p_data
, int i_data
)
589 static const int pi_cover_score
[] = {
592 10, /* front cover */
594 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
595 6, /* movie/video screen capture */
597 7, /* Illustration */
598 8, /* Band/Artist logotype */
599 0, /* Publisher/Studio */
601 demux_sys_t
*p_sys
= p_demux
->p_sys
;
604 char *psz_mime
= NULL
;
605 char *psz_description
= NULL
;
606 input_attachment_t
*p_attachment
;
609 if( i_data
< 4 + 3*4 )
611 #define RM(x) do { i_data -= (x); p_data += (x); } while(0)
614 i_type
= GetDWBE( p_data
); RM(4);
615 i_len
= GetDWBE( p_data
); RM(4);
616 if( i_len
< 0 || i_data
< i_len
+ 4 )
618 psz_mime
= strndup( (const char*)p_data
, i_len
); RM(i_len
);
619 i_len
= GetDWBE( p_data
); RM(4);
620 if( i_len
< 0 || i_data
< i_len
+ 4*4 + 4)
622 psz_description
= strndup( (const char*)p_data
, i_len
); RM(i_len
);
623 EnsureUTF8( psz_description
);
625 i_len
= GetDWBE( p_data
); RM(4);
626 if( i_len
< 0 || i_len
> i_data
)
629 msg_Dbg( p_demux
, "Picture type=%d mime=%s description='%s' file length=%d",
630 i_type
, psz_mime
, psz_description
, i_len
);
632 snprintf( psz_name
, sizeof(psz_name
), "picture%d", p_sys
->i_attachments
);
633 if( !strcasecmp( psz_mime
, "image/jpeg" ) )
634 strcat( psz_name
, ".jpg" );
635 else if( !strcasecmp( psz_mime
, "image/png" ) )
636 strcat( psz_name
, ".png" );
638 p_attachment
= vlc_input_attachment_New( psz_name
, psz_mime
, psz_description
,
640 TAB_APPEND( p_sys
->i_attachments
, p_sys
->attachments
, p_attachment
);
642 if( i_type
>= 0 && (unsigned int)i_type
< sizeof(pi_cover_score
)/sizeof(pi_cover_score
[0]) &&
643 p_sys
->i_cover_score
< pi_cover_score
[i_type
] )
645 p_sys
->i_cover_idx
= p_sys
->i_attachments
-1;
646 p_sys
->i_cover_score
= pi_cover_score
[i_type
];
650 free( psz_description
);