]> git.sesse.net Git - vlc/blob - modules/demux/flac.c
ASF: don't print debug infos in releases
[vlc] / modules / demux / flac.c
1 /*****************************************************************************
2  * flac.c : FLAC demux module for vlc
3  *****************************************************************************
4  * Copyright (C) 2001-2008 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *          Laurent Aimar <fenrir@via.ecp.fr>
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
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 */
39
40 #include <assert.h>
41 #include "vorbis.h"                   /* vorbis comments */
42
43 /*****************************************************************************
44  * Module descriptor
45  *****************************************************************************/
46 static int  Open  ( vlc_object_t * );
47 static void Close ( vlc_object_t * );
48
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 ()
57
58 /*****************************************************************************
59  * Local prototypes
60  *****************************************************************************/
61 static int Demux  ( demux_t * );
62 static int Control( demux_t *, int, va_list );
63
64 static int  ReadMeta( demux_t *, uint8_t **pp_streaminfo, int *pi_streaminfo );
65
66 struct demux_sys_t
67 {
68     bool  b_start;
69     es_out_id_t *p_es;
70
71     /* Packetizer */
72     decoder_t *p_packetizer;
73
74     vlc_meta_t *p_meta;
75     audio_replay_gain_t replay_gain;
76
77     int64_t i_time_offset;
78     int64_t i_pts;
79     int64_t i_pts_start;
80
81     int64_t i_length; /* Length from stream info */
82     int64_t i_data_pos;
83
84     /* */
85     int         i_seekpoint;
86     seekpoint_t **seekpoint;
87
88     /* */
89     int                i_attachments;
90     input_attachment_t **attachments;
91     int                i_cover_idx;
92     int                i_cover_score;
93 };
94
95 #define STREAMINFO_SIZE 38
96 #define FLAC_PACKET_SIZE 16384
97
98 /*****************************************************************************
99  * Open: initializes ES structures
100  *****************************************************************************/
101 static int Open( vlc_object_t * p_this )
102 {
103     demux_t     *p_demux = (demux_t*)p_this;
104     demux_sys_t *p_sys;
105     const uint8_t *p_peek;
106     uint8_t     *p_streaminfo;
107     int         i_streaminfo;
108     es_format_t fmt;
109
110     /* Have a peep at the show. */
111     if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;
112
113     if( p_peek[0]!='f' || p_peek[1]!='L' || p_peek[2]!='a' || p_peek[3]!='C' )
114     {
115         if( !p_demux->b_force ) return VLC_EGENERIC;
116
117         /* User forced */
118         msg_Err( p_demux, "this doesn't look like a flac stream, "
119                  "continuing anyway" );
120     }
121
122     p_sys = malloc( sizeof( demux_sys_t ) );
123     if( unlikely(p_sys == NULL) )
124         return VLC_ENOMEM;
125
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) );
132     p_sys->i_length = 0;
133     p_sys->i_time_offset = 0;
134     p_sys->i_pts = 0;
135     p_sys->i_pts_start = 0;
136     p_sys->p_es = NULL;
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;
141
142     /* We need to read and store the STREAMINFO metadata */
143     if( ReadMeta( p_demux, &p_streaminfo, &i_streaminfo ) )
144     {
145         free( p_sys );
146         return VLC_EGENERIC;
147     }
148
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;
155
156     p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "flac" );
157     if( !p_sys->p_packetizer )
158     {
159         free( p_sys );
160         return VLC_EGENERIC;
161     }
162
163     if( p_sys->i_cover_idx < p_sys->i_attachments )
164     {
165         char psz_url[128];
166         if( !p_sys->p_meta )
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 );
171     }
172     vlc_audio_replay_gain_MergeFromMeta( &p_sys->replay_gain, p_sys->p_meta );
173     return VLC_SUCCESS;
174 }
175
176 /*****************************************************************************
177  * Close: frees unused data
178  *****************************************************************************/
179 static void Close( vlc_object_t * p_this )
180 {
181     demux_t     *p_demux = (demux_t*)p_this;
182     demux_sys_t *p_sys = p_demux->p_sys;
183
184     TAB_CLEAN( p_sys->i_seekpoint, p_sys->seekpoint );
185
186     int i;
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);
190
191     /* Delete the decoder */
192     demux_PacketizerDestroy( p_sys->p_packetizer );
193
194     if( p_sys->p_meta )
195         vlc_meta_Delete( p_sys->p_meta );
196     free( p_sys );
197 }
198
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 )
205 {
206     demux_sys_t *p_sys = p_demux->p_sys;
207     block_t     *p_block_in, *p_block_out;
208
209     if( !( p_block_in = stream_Block( p_demux->s, FLAC_PACKET_SIZE ) ) )
210         return 0;
211
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;
214
215     while( (p_block_out = p_sys->p_packetizer->pf_packetize(
216                 p_sys->p_packetizer, &p_block_in )) )
217     {
218         while( p_block_out )
219         {
220             block_t *p_next = p_block_out->p_next;
221
222             p_block_out->p_next = NULL;
223
224             if( p_sys->p_es == NULL )
225             {
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);
229             }
230
231             p_sys->i_pts = p_block_out->i_dts - VLC_TS_0;
232
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;
236
237             /* set PCR */
238             es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_out->i_dts );
239
240             es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
241
242             p_block_out = p_next;
243         }
244     }
245     return 1;
246 }
247
248 /*****************************************************************************
249  * Control:
250  *****************************************************************************/
251 static int64_t ControlGetLength( demux_t *p_demux )
252 {
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;
256     int i;
257
258     /* Try to fix length using seekpoint and current size for truncated file */
259     for( i = p_sys->i_seekpoint-1; i >= 0; i-- )
260     {
261         seekpoint_t *s = p_sys->seekpoint[i];
262         if( s->i_byte_offset <= i_size )
263         {
264             if( i+1 < p_sys->i_seekpoint )
265             {
266                 /* Broken file */
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);
270             }
271             break;
272         }
273     }
274     return i_length;
275 }
276
277 static int64_t ControlGetTime( demux_t *p_demux )
278 {
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;
281 }
282
283 static int ControlSetTime( demux_t *p_demux, int64_t i_time )
284 {
285     demux_sys_t *p_sys = p_demux->p_sys;
286     int64_t i_delta_time;
287     bool b_seekable;
288     int i;
289
290     /* */
291     stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_seekable );
292     if( !b_seekable )
293         return VLC_EGENERIC;
294
295     /* */
296     assert( p_sys->i_seekpoint > 0 );   /* ReadMeta ensure at least (0,0) */
297     for( i = p_sys->i_seekpoint-1; i >= 0; i-- )
298     {
299         if( p_sys->seekpoint[i]->i_time_offset <= i_time )
300             break;
301     }
302     i_delta_time = i_time - p_sys->seekpoint[i]->i_time_offset;
303
304     /* XXX We do exact seek if it's not too far away(45s) */
305     if( i_delta_time < 45*INT64_C(1000000) )
306     {
307         if( stream_Seek( p_demux->s, p_sys->seekpoint[i]->i_byte_offset+p_sys->i_data_pos ) )
308             return VLC_EGENERIC;
309
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 );
313     }
314     else
315     {
316         int64_t i_delta_offset;
317         int64_t i_next_time;
318         int64_t i_next_offset;
319
320         if( i+1 < p_sys->i_seekpoint )
321         {
322             i_next_time   = p_sys->seekpoint[i+1]->i_time_offset;
323             i_next_offset = p_sys->seekpoint[i+1]->i_byte_offset;
324         }
325         else
326         {
327             i_next_time   = p_sys->i_length;
328             i_next_offset = stream_Size(p_demux->s)-p_sys->i_data_pos;
329         }
330
331         i_delta_offset = 0;
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);
335
336         if( stream_Seek( p_demux->s, p_sys->seekpoint[i]->i_byte_offset+p_sys->i_data_pos + i_delta_offset ) )
337             return VLC_EGENERIC;
338
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;
341     }
342     return VLC_SUCCESS;
343 }
344
345 static int Control( demux_t *p_demux, int i_query, va_list args )
346 {
347     demux_sys_t *p_sys = p_demux->p_sys;
348
349     if( i_query == DEMUX_GET_META )
350     {
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 );
354         return VLC_SUCCESS;
355     }
356     else if( i_query == DEMUX_HAS_UNSUPPORTED_META )
357     {
358         bool *pb_bool = (bool*)va_arg( args, bool* );
359         *pb_bool = true;
360         return VLC_SUCCESS;
361     }
362     else if( i_query == DEMUX_GET_LENGTH )
363     {
364         int64_t *pi64 = (int64_t*)va_arg( args, int64_t * );
365         *pi64 = ControlGetLength( p_demux );
366         return VLC_SUCCESS;
367     }
368     else if( i_query == DEMUX_SET_TIME )
369     {
370         int64_t i_time = (int64_t)va_arg( args, int64_t );
371         return ControlSetTime( p_demux, i_time );
372     }
373     else if( i_query == DEMUX_SET_POSITION )
374     {
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 );
378     }
379     else if( i_query == DEMUX_GET_TIME )
380     {
381         int64_t *pi64 = (int64_t*)va_arg( args, int64_t * );
382         *pi64 = ControlGetTime( p_demux );
383         return VLC_SUCCESS;
384     }
385     else if( i_query == DEMUX_GET_POSITION )
386     {
387         double *pf = (double*)va_arg( args, double * );
388         const int64_t i_length = ControlGetLength(p_demux);
389         if( i_length > 0 )
390         {
391             double current = ControlGetTime(p_demux);
392             *pf = current / (double)i_length;
393         }
394         else
395             *pf= 0.0;
396         return VLC_SUCCESS;
397     }
398     else if( i_query == DEMUX_GET_ATTACHMENTS )
399     {
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 * );
403
404         if( p_sys->i_attachments <= 0 )
405             return VLC_EGENERIC;
406
407         *pi_int = p_sys->i_attachments;
408         *ppp_attach = xmalloc( sizeof(input_attachment_t**) * p_sys->i_attachments );
409         for( int i = 0; i < p_sys->i_attachments; i++ )
410             (*ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachments[i] );
411         return VLC_SUCCESS;
412     }
413
414     return demux_vaControlHelper( p_demux->s, p_sys->i_data_pos, -1,
415                                    8*0, 1, i_query, args );
416 }
417
418 enum
419 {
420     META_STREAMINFO = 0,
421     META_SEEKTABLE = 3,
422     META_COMMENT = 4,
423     META_PICTURE = 6,
424 };
425
426 static inline int Get24bBE( const uint8_t *p )
427 {
428     return (p[0] << 16)|(p[1] << 8)|(p[2]);
429 }
430
431 static void ParseStreamInfo( int *pi_rate, int64_t *pi_count, uint8_t *p_data );
432 static void ParseSeekTable( demux_t *p_demux, const uint8_t *p_data, int i_data,
433                             int i_sample_rate );
434 static void ParseComment( demux_t *, const uint8_t *p_data, int i_data );
435 static void ParsePicture( demux_t *, const uint8_t *p_data, int i_data );
436
437 static int  ReadMeta( demux_t *p_demux, uint8_t **pp_streaminfo, int *pi_streaminfo )
438 {
439     demux_sys_t *p_sys = p_demux->p_sys;
440     int     i_peek;
441     const uint8_t *p_peek;
442     bool b_last;
443     int i_sample_rate;
444     int64_t i_sample_count;
445     seekpoint_t *s;
446
447     /* Read STREAMINFO */
448     i_peek = stream_Peek( p_demux->s, &p_peek, 8 );
449     if( (p_peek[4] & 0x7F) != META_STREAMINFO )
450     {
451         msg_Err( p_demux, "this isn't a STREAMINFO metadata block" );
452         return VLC_EGENERIC;
453     }
454     if( Get24bBE(&p_peek[5]) != (STREAMINFO_SIZE - 4) )
455     {
456         msg_Err( p_demux, "invalid size for a STREAMINFO metadata block" );
457         return VLC_EGENERIC;
458     }
459
460     *pi_streaminfo = 4 + STREAMINFO_SIZE;
461     *pp_streaminfo = malloc( 4 + STREAMINFO_SIZE );
462     if( *pp_streaminfo == NULL )
463         return VLC_EGENERIC;
464
465     if( stream_Read( p_demux->s, *pp_streaminfo, 4+STREAMINFO_SIZE ) != 4+STREAMINFO_SIZE )
466     {
467         msg_Err( p_demux, "failed to read STREAMINFO metadata block" );
468         free( *pp_streaminfo );
469         return VLC_EGENERIC;
470     }
471
472     /* */
473     ParseStreamInfo( &i_sample_rate, &i_sample_count, *pp_streaminfo );
474     if( i_sample_rate > 0 )
475         p_sys->i_length = i_sample_count * INT64_C(1000000)/i_sample_rate;
476
477     /* Be sure we have seekpoint 0 */
478     s = vlc_seekpoint_New();
479     s->i_time_offset = 0;
480     s->i_byte_offset = 0;
481     TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s );
482
483     b_last = (*pp_streaminfo)[4]&0x80;
484     while( !b_last )
485     {
486         int i_len;
487         int i_type;
488
489         i_peek = stream_Peek( p_demux->s, &p_peek, 4 );
490         if( i_peek < 4 )
491             break;
492         b_last = p_peek[0]&0x80;
493         i_type = p_peek[0]&0x7f;
494         i_len  = Get24bBE( &p_peek[1] );
495
496         if( i_type == META_SEEKTABLE )
497         {
498             i_peek = stream_Peek( p_demux->s, &p_peek, 4+i_len );
499             if( i_peek == 4+i_len )
500                 ParseSeekTable( p_demux, p_peek, i_peek, i_sample_rate );
501         }
502         else if( i_type == META_COMMENT )
503         {
504             i_peek = stream_Peek( p_demux->s, &p_peek, 4+i_len );
505             if( i_peek == 4+i_len )
506                 ParseComment( p_demux, p_peek, i_peek );
507         }
508         else if( i_type == META_PICTURE )
509         {
510             i_peek = stream_Peek( p_demux->s, &p_peek, 4+i_len );
511             if( i_peek == 4+i_len )
512                 ParsePicture( p_demux, p_peek, i_peek );
513         }
514
515         if( stream_Read( p_demux->s, NULL, 4+i_len ) < 4+i_len )
516             break;
517     }
518
519     /* */
520     p_sys->i_data_pos = stream_Tell( p_demux->s );
521
522     return VLC_SUCCESS;
523 }
524 static void ParseStreamInfo( int *pi_rate, int64_t *pi_count, uint8_t *p_data )
525 {
526     const int i_skip = 4+4;
527
528     *pi_rate = GetDWBE(&p_data[i_skip+4+6]) >> 12;
529     *pi_count = GetQWBE(&p_data[i_skip+4+6]) &  ((INT64_C(1)<<36)-1);
530 }
531
532 static void ParseSeekTable( demux_t *p_demux, const uint8_t *p_data, int i_data,
533                             int i_sample_rate )
534 {
535     demux_sys_t *p_sys = p_demux->p_sys;
536     seekpoint_t *s;
537     int i;
538
539     if( i_sample_rate <= 0 )
540         return;
541
542     /* */
543     for( i = 0; i < (i_data-4)/18; i++ )
544     {
545         const int64_t i_sample = GetQWBE( &p_data[4+18*i+0] );
546         int j;
547
548         if( i_sample < 0 || i_sample >= INT64_MAX )
549             continue;
550
551         s = vlc_seekpoint_New();
552         s->i_time_offset = i_sample * INT64_C(1000000)/i_sample_rate;
553         s->i_byte_offset = GetQWBE( &p_data[4+18*i+8] );
554
555         /* Check for duplicate entry */
556         for( j = 0; j < p_sys->i_seekpoint; j++ )
557         {
558             if( p_sys->seekpoint[j]->i_time_offset == s->i_time_offset ||
559                 p_sys->seekpoint[j]->i_byte_offset == s->i_byte_offset )
560             {
561                 vlc_seekpoint_Delete( s );
562                 s = NULL;
563                 break;
564             }
565         }
566         if( s )
567         {
568             TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s );
569         }
570     }
571     /* TODO sort it by size and remove wrong seek entry (time not increasing) */
572 }
573
574 static void ParseComment( demux_t *p_demux, const uint8_t *p_data, int i_data )
575 {
576     demux_sys_t *p_sys = p_demux->p_sys;
577
578     if( i_data < 4 )
579         return;
580
581     vorbis_ParseComment( &p_sys->p_meta, &p_data[4], i_data - 4, NULL, NULL, NULL, NULL );
582
583 }
584
585 static void ParsePicture( demux_t *p_demux, const uint8_t *p_data, int i_data )
586 {
587     static const int pi_cover_score[] = {
588         0,      /* other */
589         2, 1,   /* icons */
590         10,     /* front cover */
591         9,      /* back cover */
592         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
593         6,      /* movie/video screen capture */
594         0,
595         7,      /* Illustration */
596         8,      /* Band/Artist logotype */
597         0,      /* Publisher/Studio */
598     };
599     demux_sys_t *p_sys = p_demux->p_sys;
600     int i_type;
601
602     i_data -= 4; p_data += 4;
603
604     input_attachment_t *p_attachment = ParseFlacPicture( p_data, i_data, p_sys->i_attachments, &i_type );
605     if( p_attachment == NULL )
606         return;
607
608     TAB_APPEND( p_sys->i_attachments, p_sys->attachments, p_attachment );
609
610     if( i_type >= 0 && (unsigned int)i_type < sizeof(pi_cover_score)/sizeof(pi_cover_score[0]) &&
611         p_sys->i_cover_score < pi_cover_score[i_type] )
612     {
613         p_sys->i_cover_idx = p_sys->i_attachments-1;
614         p_sys->i_cover_score = pi_cover_score[i_type];
615     }
616 }
617