flac.c 26.2 KB
Newer Older
1
/*****************************************************************************
2
 * flac.c : FLAC demux module for vlc
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
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
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
10 11 12
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
13
 * (at your option) any later version.
14
 *
15 16
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
17 18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
19
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
20 21 22
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 24 25 26 27
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
28 29 30 31
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

32
#include <vlc_common.h>
33
#include <vlc_plugin.h>
34
#include <vlc_demux.h>
35 36 37 38 39
#include <vlc_meta.h>                 /* vlc_meta_* */
#include <vlc_input.h>                /* vlc_input_attachment, vlc_seekpoint */
#include <vlc_codec.h>                /* decoder_t */
#include <vlc_charset.h>              /* EnsureUTF8 */

40
#include <assert.h>
41
#include "xiph_metadata.h"            /* vorbis comments */
42
#include "../packetizer/flac.h"
43 44

/*****************************************************************************
45
 * Module descriptor
46
 *****************************************************************************/
47 48
static int  Open  ( vlc_object_t * );
static void Close ( vlc_object_t * );
49

50 51 52 53 54 55 56 57
vlc_module_begin ()
    set_description( N_("FLAC demuxer") )
    set_capability( "demux", 155 )
    set_category( CAT_INPUT )
    set_subcategory( SUBCAT_INPUT_DEMUX )
    set_callbacks( Open, Close )
    add_shortcut( "flac" )
vlc_module_end ()
58 59 60 61 62 63

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static int Demux  ( demux_t * );
static int Control( demux_t *, int, va_list );
64

65
static int  ParseHeaders( demux_t *, es_format_t * );
66

67 68 69 70 71 72
typedef struct
{
    mtime_t  i_time_offset;
    uint64_t i_byte_offset;
} flac_seekpoint_t;

73 74
struct demux_sys_t
{
75
    bool  b_start;
76
    int   i_next_block_flags;
77
    es_out_id_t *p_es;
78
    block_t *p_current_block;
79 80 81

    /* Packetizer */
    decoder_t *p_packetizer;
82

83
    vlc_meta_t *p_meta;
84 85

    int64_t i_pts;
86 87
    struct flac_stream_info stream_info;
    bool b_stream_info;
88 89

    int64_t i_length; /* Length from stream info */
90
    uint64_t i_data_pos;
91 92 93

    /* */
    int         i_seekpoint;
94
    flac_seekpoint_t **seekpoint;
95

96 97 98 99
    /* title/chapters seekpoints */
    int           i_title_seekpoints;
    seekpoint_t **pp_title_seekpoints;

100
    /* */
101 102
    int                i_attachments;
    input_attachment_t **attachments;
103 104
    int                i_cover_idx;
    int                i_cover_score;
105 106
};

107
#define FLAC_PACKET_SIZE 16384
108 109
#define FLAC_MAX_PREROLL      (CLOCK_FREQ * 4)
#define FLAC_MAX_SLOW_PREROLL (CLOCK_FREQ * 45)
110 111

/*****************************************************************************
112
 * Open: initializes ES structures
113
 *****************************************************************************/
114
static int Open( vlc_object_t * p_this )
115
{
116 117
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
118
    const uint8_t *p_peek;
119
    es_format_t fmt;
120

121
    /* Have a peep at the show. */
122
    if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;
123

124
    if( p_peek[0]!='f' || p_peek[1]!='L' || p_peek[2]!='a' || p_peek[3]!='C' )
125
    {
126
        if( !p_demux->obj.force
127 128
         && !demux_IsContentType( p_demux, "audio/flac" ) )
            return VLC_EGENERIC;
129

130 131 132
        /* User forced */
        msg_Err( p_demux, "this doesn't look like a flac stream, "
                 "continuing anyway" );
133 134
    }

135 136 137 138
    p_sys = malloc( sizeof( demux_sys_t ) );
    if( unlikely(p_sys == NULL) )
        return VLC_ENOMEM;

139 140
    p_demux->pf_demux   = Demux;
    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;
146
    p_sys->i_length = 0;
147
    p_sys->i_pts = VLC_TS_INVALID;
148
    p_sys->b_stream_info = false;
149
    p_sys->p_es = NULL;
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 155
    p_sys->i_cover_idx = 0;
    p_sys->i_cover_score = 0;
156

157 158 159 160
    es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_FLAC );

    /* We need to read and store the STREAMINFO metadata into fmt extra */
    if( ParseHeaders( p_demux, &fmt ) )
161
        goto error;
162

163
    /* Load the FLAC packetizer */
164 165
    p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "flac" );
    if( !p_sys->p_packetizer )
166
        goto error;
167

168
    if( p_sys->i_cover_idx < p_sys->i_attachments )
169 170 171 172 173
    {
        char psz_url[128];
        if( !p_sys->p_meta )
            p_sys->p_meta = vlc_meta_New();
        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 );
176
    }
177

178
    p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_in );
179 180 181
    if( !p_sys->p_es )
        goto error;

182
    return VLC_SUCCESS;
183 184 185
error:
    Close( p_this );
    return VLC_EGENERIC;
186 187 188 189 190 191 192
}

/*****************************************************************************
 * Close: frees unused data
 *****************************************************************************/
static void Close( vlc_object_t * p_this )
{
193 194
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys = p_demux->p_sys;
195

196 197 198
    if( p_sys->p_current_block )
        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 );
202

203
    for( int i = 0; i < p_sys->i_attachments; i++ )
204
        vlc_input_attachment_Delete( p_sys->attachments[i] );
205 206
    TAB_CLEAN( p_sys->i_attachments, p_sys->attachments);

207 208 209 210
    for( int i = 0; i < p_sys->i_title_seekpoints; i++ )
        vlc_seekpoint_Delete( p_sys->pp_title_seekpoints[i] );
    TAB_CLEAN( p_sys->i_title_seekpoints, p_sys->pp_title_seekpoints );

211
    /* Delete the decoder */
212 213
    if( p_sys->p_packetizer )
        demux_PacketizerDestroy( p_sys->p_packetizer );
214

215 216
    if( p_sys->p_meta )
        vlc_meta_Delete( p_sys->p_meta );
217
    free( p_sys );
218 219
}

220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
static block_t *GetPacketizedBlock( decoder_t *p_packetizer,
                                    const struct flac_stream_info *streaminfo,
                                    block_t **pp_current_block )
{
    block_t *p_block = p_packetizer->pf_packetize( p_packetizer, pp_current_block );
    if( p_block )
    {
        if( p_block->i_buffer >= FLAC_HEADER_SIZE_MAX )
        {
            struct flac_header_info headerinfo;
            int i_ret = FLAC_ParseSyncInfo( p_block->p_buffer, streaminfo, NULL, &headerinfo );
            assert( i_ret != 0 ); /* Same as packetizer */
            /* Use Frame PTS, not the interpolated one */
            p_block->i_dts = p_block->i_pts = headerinfo.i_pts;
        }
    }
    return p_block;
}

239 240 241 242 243 244 245 246 247 248 249 250
static void FlushPacketizer( decoder_t *p_packetizer )
{
    if( p_packetizer->pf_flush )
        p_packetizer->pf_flush( p_packetizer );
    else
    {
        block_t *p_block_out;
        while( (p_block_out = p_packetizer->pf_packetize( p_packetizer, NULL )) )
            block_Release( p_block_out );
    }
}

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
static void Reset( demux_sys_t *p_sys )
{
    p_sys->i_pts = VLC_TS_INVALID;

    FlushPacketizer( p_sys->p_packetizer );
    if( p_sys->p_current_block )
    {
        block_Release( p_sys->p_current_block );
        p_sys->p_current_block = NULL;
    }
}

static int RefineSeek( demux_t *p_demux, mtime_t i_time, double i_bytemicrorate,
                       uint64_t i_lowpos, uint64_t i_highpos )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    bool b_found = false;
    block_t *p_block_out;
    block_t *p_block_in;

271
    unsigned i_frame_size = FLAC_FRAME_SIZE_MIN;
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292

    bool b_canfastseek = false;
    (int) vlc_stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b_canfastseek );

    uint64_t i_start_pos = vlc_stream_Tell( p_demux->s );

    while( !b_found )
    {
        FlushPacketizer( p_sys->p_packetizer );

        p_block_out = NULL;
        p_block_in = NULL;

        while( !p_block_out )
        {
            if( !p_block_in )
            {
                if( !(p_block_in = vlc_stream_Block( p_demux->s, i_frame_size )) )
                    break;
            }

293 294 295
            p_block_out = GetPacketizedBlock( p_sys->p_packetizer,
                                              p_sys->b_stream_info ? &p_sys->stream_info : NULL,
                                             &p_block_in );
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
        }

        if( !p_block_out )
        {
            if( p_block_in )
                block_Release( p_block_in );
            break;
        }

        if( p_block_out->i_buffer > i_frame_size )
            i_frame_size = p_block_out->i_buffer;

        /* If we are further than wanted block */
        if( p_block_out->i_dts >= i_time )
        {
            mtime_t i_diff = p_block_out->i_dts - i_time;
            /* Not in acceptable approximation range */
            if( i_diff > CLOCK_FREQ / 10 && i_diff / i_bytemicrorate > i_frame_size )
            {
                i_highpos = i_start_pos;
                i_start_pos -= ( i_diff / i_bytemicrorate );
                i_start_pos = __MAX(i_start_pos, i_lowpos + i_frame_size);
            }
            else b_found = true;
        }
        else if( p_block_out->i_dts < i_time )
        {
            mtime_t i_diff = i_time - p_block_out->i_dts;
            /* Not in acceptable NEXT_TIME demux range */
            if( i_diff >= ((b_canfastseek) ? FLAC_MAX_PREROLL : FLAC_MAX_SLOW_PREROLL) &&
                i_diff / i_bytemicrorate > i_frame_size )
            {
                i_lowpos = i_start_pos;
                i_start_pos += ( i_diff / i_bytemicrorate );
                i_start_pos = __MIN(i_start_pos, i_highpos - i_frame_size);
            }
            else b_found = true;
        }

        if( p_block_out )
            block_Release( p_block_out );
        if( p_block_in )
            block_Release( p_block_in );

        if( !b_found )
        {
            if( i_highpos < i_lowpos || i_highpos - i_lowpos < i_frame_size )
                break;

            if( VLC_SUCCESS != vlc_stream_Seek( p_demux->s, i_start_pos ) )
                break;
        }
    }

    return b_found ? VLC_SUCCESS : VLC_EGENERIC;
}

353 354 355 356 357
/*****************************************************************************
 * Demux: reads and demuxes data packets
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
358
static int Demux( demux_t *p_demux )
359
{
360
    demux_sys_t *p_sys = p_demux->p_sys;
361
    block_t *p_block_out;
362

363 364 365 366 367 368
    bool b_eof = false;
    if( p_sys->p_current_block == NULL )
    {
        p_sys->p_current_block = vlc_stream_Block( p_demux->s, FLAC_PACKET_SIZE );
        b_eof = (p_sys->p_current_block == NULL);
    }
369

370
    if ( p_sys->p_current_block )
371
    {
372
        p_sys->p_current_block->i_flags = p_sys->i_next_block_flags;
373
        p_sys->i_next_block_flags = 0;
374 375
        p_sys->p_current_block->i_pts =
        p_sys->p_current_block->i_dts = p_sys->b_start ? VLC_TS_0 : VLC_TS_INVALID;
376
    }
377

378 379 380
    while( (p_block_out = GetPacketizedBlock( p_sys->p_packetizer,
                            p_sys->b_stream_info ? &p_sys->stream_info : NULL,
                            p_sys->p_current_block ? &p_sys->p_current_block : NULL ) ) )
381
    {
382 383
        /* Only clear on output when packet is accepted as sync #17111 */
        p_sys->b_start = false;
384 385 386
        while( p_block_out )
        {
            block_t *p_next = p_block_out->p_next;
387

388 389
            p_block_out->p_next = NULL;

390
            /* set PCR */
391
            if( unlikely(p_sys->i_pts == VLC_TS_INVALID) )
392
                es_out_SetPCR( p_demux->out, __MAX(p_block_out->i_dts - 1, VLC_TS_0) );
393 394

            p_sys->i_pts = p_block_out->i_dts;
395

396
            es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
397

398
            es_out_SetPCR( p_demux->out, p_sys->i_pts );
399

400 401
            p_block_out = p_next;
        }
402
        break;
403
    }
404 405

    return b_eof ? VLC_DEMUXER_EOF : VLC_DEMUXER_SUCCESS;
406
}
407 408 409 410

/*****************************************************************************
 * Control:
 *****************************************************************************/
411 412 413
static int64_t ControlGetLength( demux_t *p_demux )
{
    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 416 417 418 419 420
    int64_t i_length = p_sys->i_length;
    int i;

    /* Try to fix length using seekpoint and current size for truncated file */
    for( i = p_sys->i_seekpoint-1; i >= 0; i-- )
    {
421
        flac_seekpoint_t *s = p_sys->seekpoint[i];
422 423 424 425 426
        if( s->i_byte_offset <= i_size )
        {
            if( i+1 < p_sys->i_seekpoint )
            {
                /* Broken file */
427
                flac_seekpoint_t *n = p_sys->seekpoint[i+1];
428 429 430 431 432 433 434 435
                assert( n->i_byte_offset != s->i_byte_offset); /* Should be ensured by ParseSeekTable */
                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);
            }
            break;
        }
    }
    return i_length;
}
436

437 438 439
static int64_t ControlGetTime( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
440
    return p_sys->i_pts;
441
}
442

443 444 445
static int ControlSetTime( demux_t *p_demux, int64_t i_time )
{
    demux_sys_t *p_sys = p_demux->p_sys;
446
    bool b_seekable;
447 448 449
    int i;

    /* */
450
    vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_seekable );
451 452 453
    if( !b_seekable )
        return VLC_EGENERIC;

454 455 456
    const mtime_t i_length = ControlGetLength( p_demux );
    if( i_length <= 0 )
        return VLC_EGENERIC;
457

458 459 460
    const uint64_t i_stream_size = stream_Size( p_demux->s );
    if( i_stream_size <= p_sys->i_data_pos )
        return VLC_EGENERIC;
461

462 463 464
    const double i_bytemicrorate = (double) i_length / (i_stream_size - p_sys->i_data_pos);
    if( i_bytemicrorate == 0 )
        return VLC_EGENERIC;
465

466 467 468 469 470 471 472 473 474
    uint64_t i_lower = p_sys->i_data_pos;
    uint64_t i_upper = i_stream_size;
    uint64_t i_start_pos;

    assert( p_sys->i_seekpoint > 0 );   /* ReadMeta ensure at least (0,0) */
    if( p_sys->i_seekpoint > 1 )
    {
        /* lookup base offset */
        for( i = p_sys->i_seekpoint-1; i >= 0; i-- )
475
        {
476 477
            if( p_sys->seekpoint[i]->i_time_offset <= i_time )
                break;
478 479
        }

480 481 482
        i_lower = p_sys->seekpoint[0]->i_byte_offset + p_sys->i_data_pos;
        if( i+1 < p_sys->i_seekpoint )
            i_upper = p_sys->seekpoint[i+1]->i_byte_offset + p_sys->i_data_pos;
483

484 485 486 487 488
        i_start_pos = i_lower;
    }
    else
    {
        i_start_pos = i_time / i_bytemicrorate;
489
    }
490

491 492 493 494 495
    if( VLC_SUCCESS != vlc_stream_Seek( p_demux->s, i_start_pos ) )
        return VLC_EGENERIC;

    int i_ret = RefineSeek( p_demux, i_time, i_bytemicrorate, i_lower, i_upper );
    if( i_ret == VLC_SUCCESS )
496
    {
497 498 499
        p_sys->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
        Reset( p_sys );
        es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_time );
500 501
    }

502
    return i_ret;
503 504
}

505 506
static int Control( demux_t *p_demux, int i_query, va_list args )
{
507 508 509
    demux_sys_t *p_sys = p_demux->p_sys;

    if( i_query == DEMUX_GET_META )
510
    {
511
        vlc_meta_t *p_meta = va_arg( args, vlc_meta_t * );
512
        if( p_demux->p_sys->p_meta )
513
            vlc_meta_Merge( p_meta, p_demux->p_sys->p_meta );
514 515
        return VLC_SUCCESS;
    }
516 517
    else if( i_query == DEMUX_HAS_UNSUPPORTED_META )
    {
518
        bool *pb_bool = va_arg( args, bool* );
519
        *pb_bool = true;
520 521
        return VLC_SUCCESS;
    }
522 523
    else if( i_query == DEMUX_GET_LENGTH )
    {
524
        int64_t *pi64 = va_arg( args, int64_t * );
525 526 527 528 529
        *pi64 = ControlGetLength( p_demux );
        return VLC_SUCCESS;
    }
    else if( i_query == DEMUX_SET_TIME )
    {
530
        int64_t i_time = va_arg( args, int64_t );
531 532 533 534
        return ControlSetTime( p_demux, i_time );
    }
    else if( i_query == DEMUX_SET_POSITION )
    {
535
        const double f = va_arg( args, double );
536
        int64_t i_length = ControlGetLength( p_demux );
537
        int i_ret;
538
        if( i_length > 0 )
539 540 541 542 543
        {
            i_ret = ControlSetTime( p_demux, i_length * f );
            if( i_ret == VLC_SUCCESS )
                return i_ret;
        }
544
        /* just byte pos seek */
545
        i_ret = vlc_stream_Seek( p_demux->s, (int64_t) (f * stream_Size( p_demux->s )) );
546 547 548 549 550 551
        if( i_ret == VLC_SUCCESS )
        {
            p_sys->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
            Reset( p_sys );
        }
        return i_ret;
552 553 554
    }
    else if( i_query == DEMUX_GET_TIME )
    {
555
        int64_t *pi64 = va_arg( args, int64_t * );
556 557 558 559 560 561 562
        *pi64 = ControlGetTime( p_demux );
        return VLC_SUCCESS;
    }
    else if( i_query == DEMUX_GET_POSITION )
    {
        const int64_t i_length = ControlGetLength(p_demux);
        if( i_length > 0 )
563 564
        {
            double current = ControlGetTime(p_demux);
565 566 567 568 569
            if( current <= i_length )
            {
                *(va_arg( args, double * )) = current / (double)i_length;
                return VLC_SUCCESS;
            }
570
        }
571
        /* Else fallback on byte position */
572
    }
573 574 575
    else if( i_query == DEMUX_GET_ATTACHMENTS )
    {
        input_attachment_t ***ppp_attach =
576 577
            va_arg( args, input_attachment_t *** );
        int *pi_int = va_arg( args, int * );
578

579
        if( p_sys->i_attachments <= 0 )
580 581
            return VLC_EGENERIC;

582
        *ppp_attach = vlc_alloc( p_sys->i_attachments, sizeof(input_attachment_t*) );
583 584
        if( !*ppp_attach )
            return VLC_EGENERIC;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
585 586
        *pi_int = p_sys->i_attachments;
        for( int i = 0; i < p_sys->i_attachments; i++ )
587
            (*ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachments[i] );
588 589
        return VLC_SUCCESS;
    }
590 591
    else if( i_query == DEMUX_GET_TITLE_INFO )
    {
592 593 594 595
        input_title_t ***ppp_title = va_arg( args, input_title_t *** );
        int *pi_int = va_arg( args, int * );
        int *pi_title_offset = va_arg( args, int * );
        int *pi_seekpoint_offset = va_arg( args, int * );
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611

        if( !p_sys->i_title_seekpoints )
            return VLC_EGENERIC;

        *pi_int = 1;
        *ppp_title = malloc( sizeof(input_title_t*) );
        if(!*ppp_title)
            return VLC_EGENERIC;

        input_title_t *p_title = (*ppp_title)[0] = vlc_input_title_New();
        if(!p_title)
        {
            free(*ppp_title);
            return VLC_EGENERIC;
        }

612
        p_title->seekpoint = vlc_alloc( p_sys->i_title_seekpoints, sizeof(seekpoint_t*) );
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
        if(!p_title->seekpoint)
        {
            vlc_input_title_Delete(p_title);
            free(*ppp_title);
            return VLC_EGENERIC;
        }

        p_title->i_seekpoint = p_sys->i_title_seekpoints;
        for( int i = 0; i < p_title->i_seekpoint; i++ )
            p_title->seekpoint[i] = vlc_seekpoint_Duplicate( p_sys->pp_title_seekpoints[i] );

        *pi_title_offset = 0;
        *pi_seekpoint_offset = 0;

        return VLC_SUCCESS;
    }
    else if( i_query == DEMUX_SET_TITLE )
    {
631
        const int i_title = va_arg( args, int );
632 633 634 635 636 637
        if( i_title != 0 )
            return VLC_EGENERIC;
        return VLC_SUCCESS;
    }
    else if( i_query == DEMUX_SET_SEEKPOINT )
    {
638
        const int i_seekpoint = va_arg( args, int );
639 640 641 642
        if( !p_sys->i_title_seekpoints || i_seekpoint >= p_sys->i_title_seekpoints )
            return VLC_EGENERIC;
        return ControlSetTime( p_demux, p_sys->pp_title_seekpoints[i_seekpoint]->i_time_offset );
    }
643

644
    return demux_vaControlHelper( p_demux->s, p_sys->i_data_pos, -1,
645 646 647 648 649 650 651 652
                                   8*0, 1, i_query, args );
}

enum
{
    META_STREAMINFO = 0,
    META_SEEKTABLE = 3,
    META_COMMENT = 4,
653
    META_PICTURE = 6,
654 655
};

656
static inline int Get24bBE( const uint8_t *p )
657 658 659 660
{
    return (p[0] << 16)|(p[1] << 8)|(p[2]);
}

661 662 663 664
static void ParseSeekTable( demux_t *p_demux, const uint8_t *p_data, size_t i_data,
                            unsigned i_sample_rate );
static void ParseComment( demux_t *, const uint8_t *p_data, size_t i_data );
static void ParsePicture( demux_t *, const uint8_t *p_data, size_t i_data );
665

666
static int  ParseHeaders( demux_t *p_demux, es_format_t *p_fmt )
667 668
{
    demux_sys_t *p_sys = p_demux->p_sys;
669
    ssize_t i_peek;
670
    const uint8_t *p_peek;
671
    bool b_last;
672 673

    /* Be sure we have seekpoint 0 */
674
    flac_seekpoint_t *s = xmalloc( sizeof (*s) );
675 676 677 678
    s->i_time_offset = 0;
    s->i_byte_offset = 0;
    TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s );

679
    uint8_t header[4];
680
    if( vlc_stream_Read( p_demux->s, header, 4) < 4)
681 682
        return VLC_EGENERIC;

683
    if (memcmp(header, "fLaC", 4))
684 685 686
        return VLC_EGENERIC;

    b_last = 0;
687 688 689 690 691
    while( !b_last )
    {
        int i_len;
        int i_type;

692
        i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 4 );
693 694 695 696 697 698
        if( i_peek < 4 )
            break;
        b_last = p_peek[0]&0x80;
        i_type = p_peek[0]&0x7f;
        i_len  = Get24bBE( &p_peek[1] );

699
        if( i_type == META_STREAMINFO && p_fmt->p_extra == NULL )
700
        {
701
            if( i_len != FLAC_STREAMINFO_SIZE ) {
702 703 704 705
                msg_Err( p_demux, "invalid size %d for a STREAMINFO metadata block", i_len );
                return VLC_EGENERIC;
            }

706
            p_fmt->p_extra = malloc( FLAC_STREAMINFO_SIZE );
707
            if( p_fmt->p_extra == NULL )
708 709
                return VLC_EGENERIC;

710
            if( vlc_stream_Read( p_demux->s, NULL, 4) < 4)
711
            {
712
                FREENULL( p_fmt->p_extra );
713
                return VLC_EGENERIC;
714
            }
715
            if( vlc_stream_Read( p_demux->s, p_fmt->p_extra,
716
                                 FLAC_STREAMINFO_SIZE ) != FLAC_STREAMINFO_SIZE )
717 718
            {
                msg_Err( p_demux, "failed to read STREAMINFO metadata block" );
719
                FREENULL( p_fmt->p_extra );
720 721
                return VLC_EGENERIC;
            }
722
            p_fmt->i_extra = FLAC_STREAMINFO_SIZE;
723 724

            /* */
725 726 727 728 729 730 731 732 733 734
            p_sys->b_stream_info = true;
            FLAC_ParseStreamInfo( (uint8_t *) p_fmt->p_extra, &p_sys->stream_info );

            p_fmt->audio.i_rate = p_sys->stream_info.sample_rate;
            p_fmt->audio.i_channels = p_sys->stream_info.channels;
            p_fmt->audio.i_bitspersample = p_sys->stream_info.bits_per_sample;
            if( p_sys->stream_info.sample_rate > 0 )
                p_sys->i_length = p_sys->stream_info.total_samples * CLOCK_FREQ
                                / p_sys->stream_info.sample_rate;

735
            continue;
736 737
        }
        else if( i_type == META_SEEKTABLE )
738
        {
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 );
742 743 744
        }
        else if( i_type == META_COMMENT )
        {
745
            i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 4+i_len );
746 747 748
            if( i_peek == 4+i_len )
                ParseComment( p_demux, p_peek, i_peek );
        }
749 750
        else if( i_type == META_PICTURE )
        {
751
            i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 4+i_len );
752 753 754
            if( i_peek == 4+i_len )
                ParsePicture( p_demux, p_peek, i_peek );
        }
755

756
        if( vlc_stream_Read( p_demux->s, NULL, 4+i_len ) < 4+i_len )
757 758 759 760
            break;
    }

    /* */
761
    p_sys->i_data_pos = vlc_stream_Tell( p_demux->s );
762

763
    if ( p_fmt->p_extra == NULL )
764 765
        return VLC_EGENERIC;

766 767
    return VLC_SUCCESS;
}
768

769 770
static void ParseSeekTable( demux_t *p_demux, const uint8_t *p_data, size_t i_data,
                            unsigned i_sample_rate )
771 772
{
    demux_sys_t *p_sys = p_demux->p_sys;
773
    flac_seekpoint_t *s;
774
    size_t i;
775

776
    if( i_sample_rate == 0 )
777 778 779 780 781 782 783 784
        return;

    /* */
    for( i = 0; i < (i_data-4)/18; i++ )
    {
        const int64_t i_sample = GetQWBE( &p_data[4+18*i+0] );
        int j;

785 786 787
        if( i_sample < 0 || i_sample >= INT64_MAX ||
            GetQWBE( &p_data[4+18*i+8] ) < FLAC_STREAMINFO_SIZE )
            break;
788

789
        s = xmalloc( sizeof (*s) );
790
        s->i_time_offset = i_sample * CLOCK_FREQ / i_sample_rate;
791 792 793 794 795 796 797 798
        s->i_byte_offset = GetQWBE( &p_data[4+18*i+8] );

        /* Check for duplicate entry */
        for( j = 0; j < p_sys->i_seekpoint; j++ )
        {
            if( p_sys->seekpoint[j]->i_time_offset == s->i_time_offset ||
                p_sys->seekpoint[j]->i_byte_offset == s->i_byte_offset )
            {
799
                free( s );
800 801 802 803 804 805 806 807 808 809 810
                s = NULL;
                break;
            }
        }
        if( s )
        {
            TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s );
        }
    }
    /* TODO sort it by size and remove wrong seek entry (time not increasing) */
}
811

812
static void ParseComment( demux_t *p_demux, const uint8_t *p_data, size_t i_data )
813 814 815 816 817 818
{
    demux_sys_t *p_sys = p_demux->p_sys;

    if( i_data < 4 )
        return;

819
    vorbis_ParseComment( NULL, &p_sys->p_meta, &p_data[4], i_data - 4,
820
        &p_sys->i_attachments, &p_sys->attachments,
821 822
        &p_sys->i_cover_score, &p_sys->i_cover_idx,
        &p_sys->i_title_seekpoints, &p_sys->pp_title_seekpoints, NULL, NULL );
823 824
}

825
static void ParsePicture( demux_t *p_demux, const uint8_t *p_data, size_t i_data )
826 827 828
{
    demux_sys_t *p_sys = p_demux->p_sys;

829 830
    i_data -= 4; p_data += 4;

831 832
    input_attachment_t *p_attachment = ParseFlacPicture( p_data, i_data,
        p_sys->i_attachments, &p_sys->i_cover_score, &p_sys->i_cover_idx );
833
    if( p_attachment == NULL )
834
        return;
835

836
    TAB_APPEND( p_sys->i_attachments, p_sys->attachments, p_attachment );
837 838
}