matroska_segment.cpp 41.5 KB
Newer Older
1
/*****************************************************************************
Pere Orga's avatar
Pere Orga committed
2
 * matroska_segment.cpp : matroska demuxer
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
4
 * Copyright (C) 2003-2010 VLC authors and VideoLAN
5
6
7
8
9
 * $Id$
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Steve Lhomme <steve.lhomme@free.fr>
 *
Jean-Baptiste Kempf's avatar
LGPL    
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
14
15
16
 * (at your option) any later version.
 *
 * 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
LGPL    
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
LGPL    
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
#include "matroska_segment.hpp"
#include "chapters.hpp"
#include "demux.hpp"
Denis Charmet's avatar
Denis Charmet committed
28
#include "util.hpp"
29
#include "Ebml_parser.hpp"
30
#include "Ebml_dispatcher.hpp"
31

32
33
#include <new>

34
35
36
37
38
matroska_segment_c::matroska_segment_c( demux_sys_t & demuxer, EbmlStream & estream )
    :segment(NULL)
    ,es(estream)
    ,i_timescale(MKVD_TIMECODESCALE)
    ,i_duration(-1)
39
    ,i_mk_start_time(0)
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    ,i_seekhead_count(0)
    ,i_seekhead_position(-1)
    ,i_cues_position(-1)
    ,i_tracks_position(-1)
    ,i_info_position(-1)
    ,i_chapters_position(-1)
    ,i_attachments_position(-1)
    ,cluster(NULL)
    ,i_block_pos(0)
    ,i_cluster_pos(0)
    ,p_segment_uid(NULL)
    ,p_prev_segment_uid(NULL)
    ,p_next_segment_uid(NULL)
    ,b_cues(false)
    ,psz_muxing_application(NULL)
    ,psz_writing_application(NULL)
    ,psz_segment_filename(NULL)
    ,psz_title(NULL)
    ,psz_date_utc(NULL)
    ,i_default_edition(0)
    ,sys(demuxer)
    ,ep(NULL)
    ,b_preloaded(false)
63
    ,b_ref_external_segments(false)
64
65
66
{
}

67
68
matroska_segment_c::~matroska_segment_c()
{
69
    for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it)
70
    {
71
72
73
74
75
76
        tracks_map_t::mapped_type& track = it->second;

        es_format_Clean( &track.fmt );
        delete track.p_compression_data;
        delete track.p_sys;
        free( track.p_extra_data );
77
    }
78

79
80
81
82
83
    free( psz_writing_application );
    free( psz_muxing_application );
    free( psz_segment_filename );
    free( psz_title );
    free( psz_date_utc );
84

85
86
87
88
89
    delete ep;
    delete segment;
    delete p_segment_uid;
    delete p_prev_segment_uid;
    delete p_next_segment_uid;
90

91
92
93
    vlc_delete_all( stored_editions );
    vlc_delete_all( translations );
    vlc_delete_all( families );
94
95
}

96

97
/*****************************************************************************
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
98
99
 * Tools                                                                     *
 *****************************************************************************
100
101
102
 *  * LoadCues : load the cues element and update index
 *  * LoadTags : load ... the tags element
 *  * InformationCreate : create all information, load tags if present
103
 *****************************************************************************/
104
void matroska_segment_c::LoadCues( KaxCues *cues )
105
{
106
    EbmlElement *el;
107

108
    if( b_cues )
109
    {
110
111
        msg_Err( &sys.demuxer, "There can be only 1 Cues per section." );
        return;
112
113
    }

114
115
    EbmlParser eparser (&es, cues, &sys.demuxer, var_InheritBool( &sys.demuxer, "mkv-use-dummy" ) );
    while( ( el = eparser.Get() ) != NULL )
116
117
118
    {
        if( MKV_IS_ID( el, KaxCuePoint ) )
        {
119
120
121
122
123
            uint64_t cue_position = -1;
            mtime_t  cue_mk_time = -1;

            unsigned int track_id = 0;
            bool b_invalid_cue = false;
124

125
126
            eparser.Down();
            while( ( el = eparser.Get() ) != NULL )
127
            {
128
                if ( MKV_CHECKED_PTR_DECL( kct_ptr, KaxCueTime, el ) )
129
                {
130
131
                    try
                    {
132
                        if( unlikely( !kct_ptr->ValidateSize() ) )
133
134
135
136
137
                        {
                            msg_Err( &sys.demuxer, "CueTime size too big");
                            b_invalid_cue = true;
                            break;
                        }
138
                        kct_ptr->ReadData( es.I_O() );
139
140
141
142
143
144
145
                    }
                    catch(...)
                    {
                        msg_Err( &sys.demuxer, "Error while reading CueTime" );
                        b_invalid_cue = true;
                        break;
                    }
146
                    cue_mk_time = static_cast<uint64>( *kct_ptr ) * i_timescale / INT64_C(1000);
147
148
149
                }
                else if( MKV_IS_ID( el, KaxCueTrackPositions ) )
                {
150
                    eparser.Down();
151
                    try
152
                    {
153
                        while( ( el = eparser.Get() ) != NULL )
154
                        {
155
                            if( unlikely( !el->ValidateSize() ) )
156
                            {
157
                                eparser.Up();
158
159
160
161
162
                                msg_Err( &sys.demuxer, "Error %s too big, aborting", typeid(*el).name() );
                                b_invalid_cue = true;
                                break;
                            }

163
                            if( MKV_CHECKED_PTR_DECL ( kct_ptr, KaxCueTrack, el ) )
164
                            {
165
                                kct_ptr->ReadData( es.I_O() );
166
                                track_id = static_cast<uint16>( *kct_ptr );
167
                            }
168
                            else if( MKV_CHECKED_PTR_DECL ( kccp_ptr, KaxCueClusterPosition, el ) )
169
                            {
170
                                kccp_ptr->ReadData( es.I_O() );
171
                                cue_position = segment->GetGlobalPosition( static_cast<uint64>( *kccp_ptr ) );
172
                            }
173
                            else if( MKV_CHECKED_PTR_DECL ( kcbn_ptr, KaxCueBlockNumber, el ) )
174
                            {
175
                                VLC_UNUSED( kcbn_ptr );
176
                            }
177
178
179
#if LIBMATROSKA_VERSION >= 0x010401
                            else if( MKV_IS_ID( el, KaxCueRelativePosition ) )
                            {
180
181
182
183
184
185
186
187
188
                                b_invalid_cue = true; // since we do not support this type of cue: IGNORE
                            }
                            else if( MKV_IS_ID( el, KaxCueBlockNumber ) )
                            {
                                b_invalid_cue = true; // since we do not support this type of cue: IGNORE
                            }
                            else if( MKV_IS_ID( el, KaxCueReference ) )
                            {
                                b_invalid_cue = true; // since we do not support this type of cue: IGNORE
189
190
191
192
193
194
                            }
                            else if( MKV_IS_ID( el, KaxCueDuration ) )
                            {
                                /* For future use */
                            }
#endif
195
196
197
198
                            else
                            {
                                msg_Dbg( &sys.demuxer, "         * Unknown (%s)", typeid(*el).name() );
                            }
199
200
                        }
                    }
201
202
                    catch(...)
                    {
203
                        eparser.Up();
204
205
206
207
                        msg_Err( &sys.demuxer, "Error while reading %s", typeid(*el).name() );
                        b_invalid_cue = true;
                        break;
                    }
208
                    eparser.Up();
209
210
211
212
213
214
                }
                else
                {
                    msg_Dbg( &sys.demuxer, "     * Unknown (%s)", typeid(*el).name() );
                }
            }
215
            eparser.Up();
216

217
218
219
220
221
222
223
224
225
            if( likely( !b_invalid_cue ) && track_id != 0 && cue_mk_time != -1 && cue_position != static_cast<uint64_t>( -1 ) ) {

                if( tracks.find( track_id ) != tracks.end() )
                {
                   // TODO: handle addition of seekpoint
                }
                else
                    msg_Warn( &sys.demuxer, "Found cue with invalid track id = %u", track_id );
            }
226
        }
227
        else
228
        {
229
            msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() );
230
231
        }
    }
232
233
234
    b_cues = true;
    msg_Dbg( &sys.demuxer, "|   - loading cues done." );
}
235

236

237
238
239
static const struct {
    vlc_meta_type_t type;
    const char *key;
240
    int target_type; /* 0 is valid for all target_type */
241
} metadata_map[] = {
242
                     {vlc_meta_Album,       "TITLE",         50},
243
                     {vlc_meta_Title,       "TITLE",         0},
244
245
246
247
248
249
250
251
                     {vlc_meta_Artist,      "ARTIST",        0},
                     {vlc_meta_Genre,       "GENRE",         0},
                     {vlc_meta_Copyright,   "COPYRIGHT",     0},
                     {vlc_meta_TrackNumber, "PART_NUMBER",   0},
                     {vlc_meta_Description, "DESCRIPTION",   0},
                     {vlc_meta_Description, "COMMENT",       0},
                     {vlc_meta_Rating,      "RATING",        0},
                     {vlc_meta_Date,        "DATE_RELEASED", 0},
252
                     {vlc_meta_Date,        "DATE_RELEASE",  0},
253
                     {vlc_meta_Date,        "DATE_RECORDED", 0},
254
255
256
257
                     {vlc_meta_URL,         "URL",           0},
                     {vlc_meta_Publisher,   "PUBLISHER",     0},
                     {vlc_meta_EncodedBy,   "ENCODED_BY",    0},
                     {vlc_meta_TrackTotal,  "TOTAL_PARTS",   0},
258
                     {vlc_meta_Album,       "ALBUM",         0},
259
                     {vlc_meta_Title,       NULL,            0},
260
261
};

262
bool matroska_segment_c::ParseSimpleTags( SimpleTag* pout_simple, KaxTagSimple *tag, int target_type )
263
{
264
    EbmlParser eparser ( &es, tag, &sys.demuxer, var_InheritBool( &sys.demuxer, "mkv-use-dummy" ) );
265
    EbmlElement *el;
266
267
    size_t max_size = tag->GetSize();
    size_t size = 0;
268

269
270
271
272
    if( !sys.meta )
        sys.meta = vlc_meta_New();

    msg_Dbg( &sys.demuxer, "|   + Simple Tag ");
273
    try
274
    {
275
        while( ( el = eparser.Get() ) != NULL && size < max_size)
276
        {
277
            if( unlikely( !el->ValidateSize() ) )
278
279
280
            {
                msg_Err( &sys.demuxer, "Error %s too big ignoring the tag", typeid(*el).name() );
                delete ep;
281
                return false;
282
            }
283
            if( MKV_CHECKED_PTR_DECL ( ktn_ptr, KaxTagName, el ) )
284
            {
285
                ktn_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA );
286
                pout_simple->tag_name = UTFstring( *ktn_ptr ).GetUTF8().c_str();
287
            }
288
            else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagString, el ) )
289
            {
290
                kts_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA );
291
                pout_simple->value = UTFstring( *kts_ptr ).GetUTF8().c_str();
292
            }
293
            else if(  MKV_CHECKED_PTR_DECL ( ktl_ptr, KaxTagLangue, el ) )
294
            {
295
                ktl_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA );
296
                pout_simple->lang = *ktl_ptr;
297
            }
298
            else if(  MKV_CHECKED_PTR_DECL ( ktd_ptr, KaxTagDefault, el ) )
299
            {
300
                VLC_UNUSED(ktd_ptr); // TODO: we do not care about this value, but maybe we should?
301
302
            }
            /*Tags can be nested*/
303
            else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagSimple, el) )
304
            {
305
306
307
308
309
310
                SimpleTag st; // ParseSimpleTags will write to this variable
                              // the SimpleTag is valid if ParseSimpleTags returns `true`

                if (ParseSimpleTags( &st, kts_ptr, target_type )) {
                  pout_simple->sub_tags.push_back( st );
                }
311
312
            }
            /*TODO Handle binary tags*/
313
            size += el->HeadSize() + el->GetSize();
314
        }
315
316
317
318
319
    }
    catch(...)
    {
        msg_Err( &sys.demuxer, "Error while reading Tag ");
        delete ep;
320
        return false;
321
322
    }

323
    if( pout_simple->tag_name.empty() )
324
325
    {
        msg_Warn( &sys.demuxer, "Invalid MKV SimpleTag found.");
326
        return false;
327
328
329
    }
    for( int i = 0; metadata_map[i].key; i++ )
    {
330
        if( pout_simple->tag_name == metadata_map[i].key &&
331
            (metadata_map[i].target_type == 0 || target_type == metadata_map[i].target_type ) )
332
        {
333
334
            vlc_meta_Set( sys.meta, metadata_map[i].type, pout_simple->value.c_str () );
            msg_Dbg( &sys.demuxer, "|   |   + Meta %s: %s", pout_simple->tag_name.c_str (), pout_simple->value.c_str ());
335
336
337
            goto done;
        }
    }
338
339
    msg_Dbg( &sys.demuxer, "|   |   + Meta %s: %s", pout_simple->tag_name.c_str (), pout_simple->value.c_str ());
    vlc_meta_AddExtra( sys.meta, pout_simple->tag_name.c_str (), pout_simple->value.c_str ());
340
done:
341
    return true;
342
343
}

344
void matroska_segment_c::LoadTags( KaxTags *tags )
345
{
346
    /* Master elements */
347
    EbmlParser eparser = EbmlParser( &es, tags, &sys.demuxer, true );
348
    EbmlElement *el;
349

350
    while( ( el = eparser.Get() ) != NULL )
351
    {
352
        if( MKV_IS_ID( el, KaxTag ) )
353
        {
354
355
            Tag tag;

356
            msg_Dbg( &sys.demuxer, "+ Tag" );
357
            eparser.Down();
358
            int target_type = 50;
359
            while( ( el = eparser.Get() ) != NULL )
360
            {
361
                if( MKV_IS_ID( el, KaxTagTargets ) )
362
363
                {
                    msg_Dbg( &sys.demuxer, "|   + Targets" );
364
365
                    eparser.Down();
                    while( ( el = eparser.Get() ) != NULL )
366
                    {
367
                        try
368
                        {
369
                            if( unlikely( !el->ValidateSize() ) )
370
371
372
373
                            {
                                msg_Err( &sys.demuxer, "Invalid size while reading tag");
                                break;
                            }
374
                            if( MKV_CHECKED_PTR_DECL ( ktttv_ptr, KaxTagTargetTypeValue, el ) )
375
                            {
376
                                ktttv_ptr->ReadData( es.I_O() );
377

378
379
                                msg_Dbg( &sys.demuxer, "|   |   + TargetTypeValue: %u", uint32(*ktttv_ptr));
                                target_type = static_cast<uint32>( *ktttv_ptr );
380
                            }
381
                            else if( MKV_CHECKED_PTR_DECL ( kttu_ptr, KaxTagTrackUID, el ) )
382
                            {
383
                                tag.i_tag_type = TRACK_UID;
384
                                kttu_ptr->ReadData( es.I_O() );
385
386
                                tag.i_uid = static_cast<uint64>( *kttu_ptr );
                                msg_Dbg( &sys.demuxer, "|   |   + TrackUID: %" PRIu64, tag.i_uid);
387
388

                            }
389
                            else if( MKV_CHECKED_PTR_DECL ( kteu_ptr, KaxTagEditionUID, el ) )
390
                            {
391
                                tag.i_tag_type = EDITION_UID;
392
                                kteu_ptr->ReadData( es.I_O() );
393
394
                                tag.i_uid = static_cast<uint64>( *kteu_ptr );
                                msg_Dbg( &sys.demuxer, "|   |   + EditionUID: %" PRIu64, tag.i_uid);
395
                            }
396
                            else if( MKV_CHECKED_PTR_DECL ( ktcu_ptr, KaxTagChapterUID, el ) )
397
                            {
398
                                tag.i_tag_type = CHAPTER_UID;
399
                                ktcu_ptr->ReadData( es.I_O() );
400
401
                                tag.i_uid = static_cast<uint64>( *ktcu_ptr );
                                msg_Dbg( &sys.demuxer, "|   |   + ChapterUID: %" PRIu64, tag.i_uid);
402
                            }
403
                            else if( MKV_CHECKED_PTR_DECL ( ktau_ptr, KaxTagAttachmentUID, el ) )
404
                            {
405
                                tag.i_tag_type = ATTACHMENT_UID;
406
                                ktau_ptr->ReadData( es.I_O() );
407
408
                                tag.i_uid = static_cast<uint64>( *ktau_ptr );
                                msg_Dbg( &sys.demuxer, "|   |   + AttachmentUID: %" PRIu64, tag.i_uid);
409
                            }
410
411
412
413
                            else
                            {
                                msg_Dbg( &sys.demuxer, "|   |   + LoadTag Unknown (%s)", typeid( *el ).name() );
                            }
414
                        }
415
                        catch(...)
416
                        {
417
418
                            msg_Err( &sys.demuxer, "Error while reading tag");
                            break;
419
                        }
420
                    }
421
                    eparser.Up();
422
                }
423
                else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagSimple, el ) )
424
                {
425
426
427
428
429
                    SimpleTag simple;

                    if (ParseSimpleTags(&simple, kts_ptr, target_type )) {
                      tag.simple_tags.push_back( simple );
                    }
430
                }
431
432
                else
                {
433
                    msg_Dbg( &sys.demuxer, "|   + LoadTag Unknown (%s)", typeid( *el ).name() );
434
435
                }
            }
436
            eparser.Up();
437
            this->tags.push_back(tag);
438
439
440
        }
        else
        {
441
            msg_Dbg( &sys.demuxer, "+ Unknown (%s)", typeid( *el ).name() );
442
443
444
        }
    }

445
    msg_Dbg( &sys.demuxer, "loading tags done." );
446
447
448
449
450
451
452
}

/*****************************************************************************
 * InformationCreate:
 *****************************************************************************/
void matroska_segment_c::InformationCreate( )
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
453
454
    if( !sys.meta )
        sys.meta = vlc_meta_New();
455

456
457
458
    if( psz_title )
    {
        vlc_meta_SetTitle( sys.meta, psz_title );
459
    }
460
}
461
462


463
464
465
/*****************************************************************************
 * Misc
 *****************************************************************************/
466

467
void matroska_segment_c::IndexAppendCluster( KaxCluster *cluster )
468
{
469

470
471
}

472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
bool matroska_segment_c::PreloadClusters(uint64 i_cluster_pos)
{
    struct ClusterHandlerPayload
    {
        matroska_segment_c * const obj;
        bool stop_parsing;

    } payload = { this, false };

    MKV_SWITCH_CREATE(EbmlTypeDispatcher, ClusterHandler, ClusterHandlerPayload )
    {
        MKV_SWITCH_INIT();

        E_CASE( KaxCluster, kcluster )
        {
            vars.obj->ParseCluster( &kcluster, false );
            vars.obj->IndexAppendCluster( &kcluster );
        }

        E_CASE_DEFAULT( el )
        {
            VLC_UNUSED( el );
            vars.stop_parsing = true;
        }
    };

    {
        es.I_O().setFilePointer( i_cluster_pos );

        while (payload.stop_parsing == false)
        {
            EbmlParser parser ( &es, segment, &sys.demuxer, var_InheritBool( &sys.demuxer, "mkv-use-dummy" ) );

            ClusterHandler::Dispatcher().send( parser.Get(), ClusterHandler::Payload( payload ) );
        }
    }

    return true;
}

512
bool matroska_segment_c::PreloadFamily( const matroska_segment_c & of_segment )
513
{
514
515
    if ( b_preloaded )
        return false;
516

517
518
    if ( SameFamily( of_segment ) )
        return Preload( );
519
520

    return false;
521
522
523
524
525
526
527
528
529
}

bool matroska_segment_c::CompareSegmentUIDs( const matroska_segment_c * p_item_a, const matroska_segment_c * p_item_b )
{
    EbmlBinary *p_tmp;

    if ( p_item_a == NULL || p_item_b == NULL )
        return false;

530
    p_tmp = static_cast<EbmlBinary *>( p_item_a->p_segment_uid );
531
532
533
534
    if ( p_item_b->p_prev_segment_uid != NULL
          && *p_tmp == *p_item_b->p_prev_segment_uid )
        return true;

535
    p_tmp = static_cast<EbmlBinary *>( p_item_a->p_next_segment_uid );
536
537
    if ( !p_tmp )
        return false;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
538

539
540
541
542
543
544
545
546
547
548
549
    if ( p_item_b->p_segment_uid != NULL
          && *p_tmp == *p_item_b->p_segment_uid )
        return true;

    if ( p_item_b->p_prev_segment_uid != NULL
          && *p_tmp == *p_item_b->p_prev_segment_uid )
        return true;

    return false;
}

550
551
552
553
554
555
556
557
558
559
560
561
562
bool matroska_segment_c::SameFamily( const matroska_segment_c & of_segment ) const
{
    for (size_t i=0; i<families.size(); i++)
    {
        for (size_t j=0; j<of_segment.families.size(); j++)
        {
            if ( *(families[i]) == *(of_segment.families[j]) )
                return true;
        }
    }
    return false;
}

563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
bool matroska_segment_c::Preload( )
{
    if ( b_preloaded )
        return false;

    EbmlElement *el = NULL;

    ep->Reset( &sys.demuxer );

    while( ( el = ep->Get() ) != NULL )
    {
        if( MKV_IS_ID( el, KaxSeekHead ) )
        {
            /* Multiple allowed */
            /* We bail at 10, to prevent possible recursion */
            msg_Dbg(  &sys.demuxer, "|   + Seek head" );
            if( i_seekhead_count < 10 )
            {
581
                i_seekhead_position = el->GetElementPosition();
582
583
584
585
586
587
588
                ParseSeekHead( static_cast<KaxSeekHead*>( el ) );
            }
        }
        else if( MKV_IS_ID( el, KaxInfo ) )
        {
            /* Multiple allowed, mandatory */
            msg_Dbg(  &sys.demuxer, "|   + Information" );
589
590
            if( i_info_position < 0 )
            {
591
                ParseInfo( static_cast<KaxInfo*>( el ) );
592
593
                i_info_position = el->GetElementPosition();
            }
594
        }
595
        else if( MKV_CHECKED_PTR_DECL ( kt_ptr, KaxTracks, el ) )
596
597
598
        {
            /* Multiple allowed */
            msg_Dbg(  &sys.demuxer, "|   + Tracks" );
599
600
            if( i_tracks_position < 0 )
            {
601
                ParseTracks( kt_ptr );
602
            }
603
604
605
606
607
            if ( tracks.size() == 0 )
            {
                msg_Err( &sys.demuxer, "No tracks supported" );
                return false;
            }
608
            i_tracks_position = el->GetElementPosition();
609
        }
610
        else if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxCues, el ) )
611
612
613
        {
            msg_Dbg(  &sys.demuxer, "|   + Cues" );
            if( i_cues_position < 0 )
614
            {
615
                LoadCues( kc_ptr );
616
617
                i_cues_position = el->GetElementPosition();
            }
618
        }
619
        else if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxCluster, el ) )
620
        {
621
622
623
624
625
            if( var_InheritBool( &sys.demuxer, "mkv-preload-clusters" ) )
            {
                PreloadClusters        ( kc_ptr->GetElementPosition() );
                es.I_O().setFilePointer( kc_ptr->GetElementPosition() );
            }
626
627
            msg_Dbg( &sys.demuxer, "|   + Cluster" );

628
            cluster = kc_ptr;
629

630
            i_cluster_pos = cluster->GetElementPosition();
631
            ParseCluster( cluster );
632
            IndexAppendCluster( cluster );
633
634
635
636
637

            ep->Down();
            /* stop pre-parsing the stream */
            break;
        }
638
        else if( MKV_CHECKED_PTR_DECL ( ka_ptr, KaxAttachments, el ) )
639
640
641
        {
            msg_Dbg( &sys.demuxer, "|   + Attachments" );
            if( i_attachments_position < 0 )
642
            {
643
                ParseAttachments( ka_ptr );
644
645
                i_attachments_position = el->GetElementPosition();
            }
646
        }
647
        else if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxChapters, el ) )
648
649
650
        {
            msg_Dbg( &sys.demuxer, "|   + Chapters" );
            if( i_chapters_position < 0 )
651
            {
652
                ParseChapters( kc_ptr );
653
654
                i_chapters_position = el->GetElementPosition();
            }
655
        }
656
        else if( MKV_CHECKED_PTR_DECL ( kt_ptr, KaxTags, el ) )
657
658
        {
            msg_Dbg( &sys.demuxer, "|   + Tags" );
659
            if(tags.empty ())
660
            {
661
                LoadTags( kt_ptr );
662
            }
663
        }
664
        else if( MKV_IS_ID ( el, EbmlVoid ) )
665
            msg_Dbg( &sys.demuxer, "|   + Void" );
666
667
668
669
        else
            msg_Dbg( &sys.demuxer, "|   + Preload Unknown (%s)", typeid(*el).name() );
    }

670
671
    ComputeTrackPriority();

672
673
    b_preloaded = true;

674
675
    EnsureDuration();

676
677
678
679
680
681
    return true;
}

/* Here we try to load elements that were found in Seek Heads, but not yet parsed */
bool matroska_segment_c::LoadSeekHeadItem( const EbmlCallbacks & ClassInfos, int64_t i_element_position )
{
682
    int64_t     i_sav_position = static_cast<int64_t>( es.I_O().getFilePointer() );
683
684
685
686
687
688
689
690
691
692
693
694
    EbmlElement *el;

    es.I_O().setFilePointer( i_element_position, seek_beginning );
    el = es.FindNextID( ClassInfos, 0xFFFFFFFFL);

    if( el == NULL )
    {
        msg_Err( &sys.demuxer, "cannot load some cues/chapters/tags etc. (broken seekhead or file)" );
        es.I_O().setFilePointer( i_sav_position, seek_beginning );
        return false;
    }

695
    if( MKV_CHECKED_PTR_DECL ( ksh_ptr, KaxSeekHead, el ) )
696
697
698
699
700
    {
        /* Multiple allowed */
        msg_Dbg( &sys.demuxer, "|   + Seek head" );
        if( i_seekhead_count < 10 )
        {
701
702
703
            if ( i_seekhead_position != i_element_position )
            {
                i_seekhead_position = i_element_position;
704
                ParseSeekHead( ksh_ptr );
705
            }
706
707
        }
    }
708
    else if( MKV_CHECKED_PTR_DECL ( ki_ptr, KaxInfo, el ) ) // FIXME
709
710
711
712
    {
        /* Multiple allowed, mandatory */
        msg_Dbg( &sys.demuxer, "|   + Information" );
        if( i_info_position < 0 )
713
        {
714
            ParseInfo( ki_ptr );
715
716
            i_info_position = i_element_position;
        }
717
    }
718
    else if( MKV_CHECKED_PTR_DECL ( kt_ptr, KaxTracks, el ) ) // FIXME
719
720
721
722
    {
        /* Multiple allowed */
        msg_Dbg( &sys.demuxer, "|   + Tracks" );
        if( i_tracks_position < 0 )
723
            ParseTracks( kt_ptr );
724
725
726
727
728
729
730
731
732
        if ( tracks.size() == 0 )
        {
            msg_Err( &sys.demuxer, "No tracks supported" );
            delete el;
            es.I_O().setFilePointer( i_sav_position, seek_beginning );
            return false;
        }
        i_tracks_position = i_element_position;
    }
733
    else if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxCues, el ) )
734
735
736
    {
        msg_Dbg( &sys.demuxer, "|   + Cues" );
        if( i_cues_position < 0 )
737
        {
738
            LoadCues( kc_ptr );
739
740
            i_cues_position = i_element_position;
        }
741
    }
742
    else if( MKV_CHECKED_PTR_DECL ( ka_ptr, KaxAttachments, el ) )
743
744
745
    {
        msg_Dbg( &sys.demuxer, "|   + Attachments" );
        if( i_attachments_position < 0 )
746
        {
747
            ParseAttachments( ka_ptr );
748
749
            i_attachments_position = i_element_position;
        }
750
    }
751
    else if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxChapters, el ) )
752
753
754
    {
        msg_Dbg( &sys.demuxer, "|   + Chapters" );
        if( i_chapters_position < 0 )
755
        {
756
            ParseChapters( kc_ptr );
757
758
            i_chapters_position = i_element_position;
        }
759
    }
760
    else if( MKV_CHECKED_PTR_DECL ( kt_ptr, KaxTags, el ) )
761
762
    {
        msg_Dbg( &sys.demuxer, "|   + Tags" );
763
        if(tags.empty ())
764
        {
765
            LoadTags( kt_ptr );
766
        }
767
768
769
770
771
772
773
774
775
776
777
    }
    else
    {
        msg_Dbg( &sys.demuxer, "|   + LoadSeekHeadItem Unknown (%s)", typeid(*el).name() );
    }
    delete el;

    es.I_O().setFilePointer( i_sav_position, seek_beginning );
    return true;
}

778
void matroska_segment_c::Seek( mtime_t i_mk_date, mtime_t i_mk_time_offset )
779
{
Filip Roséen's avatar
Filip Roséen committed
780
    // TODO: implement
781
782
}

783
784

int matroska_segment_c::FindTrackByBlock(tracks_map_t::iterator* p_track_it,
785
                                             const KaxBlock *p_block, const KaxSimpleBlock *p_simpleblock )
786
{
787
    *p_track_it = tracks.end();
788

789
    if( p_block == NULL && p_simpleblock == NULL )
790
        return VLC_EGENERIC;
791

792
793
794
795
796
797
798
799
800
801
    if (p_block != NULL)
    {
        *p_track_it = tracks.find( p_block->TrackNum() );
    }
    else if( p_simpleblock != NULL)
    {
        *p_track_it = tracks.find( p_simpleblock->TrackNum() );
    }

    return *p_track_it != tracks.end() ? VLC_SUCCESS : VLC_EGENERIC;
802
803
}

804
void matroska_segment_c::ComputeTrackPriority()
805
{
806
807
808
    bool b_has_default_video = false;
    bool b_has_default_audio = false;
    /* check for default */
809
    for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it )
810
    {
811
812
813
814
815
816
817
818
819
        tracks_map_t::mapped_type& track = it->second;

        bool flag = track.b_enabled && ( track.b_default || track.b_forced );

        switch( track.fmt.i_cat )
        {
            case VIDEO_ES: b_has_default_video |= flag; break;
            case AUDIO_ES: b_has_default_audio |= flag; break;
        }
820
821
    }

822
    for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it )
823
    {
824
825
        tracks_map_t::key_type    track_id = it->first;
        tracks_map_t::mapped_type track    = it->second;
826

827
        if( unlikely( track.fmt.i_cat == UNKNOWN_ES || !track.psz_codec ) )
828
        {
829
830
            msg_Warn( &sys.demuxer, "invalid track[%d]", static_cast<int>( track_id ) );
            track.p_es = NULL;
831
            continue;
832
        }
833
        else if( unlikely( !b_has_default_video && track.fmt.i_cat == VIDEO_ES ) )
834
        {
835
            track.b_default = true;
836
837
            b_has_default_video = true;
        }
838
        else if( unlikely( !b_has_default_audio &&  track.fmt.i_cat == AUDIO_ES ) )
839
        {
840
            track.b_default = true;
841
842
            b_has_default_audio = true;
        }
843
844
845
846
847
848
        if( unlikely( !track.b_enabled ) )
            track.fmt.i_priority = ES_PRIORITY_NOT_SELECTABLE;
        else if( track.b_forced )
            track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 2;
        else if( track.b_default )
            track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 1;
849
        else
850
            track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN;
851
852

        /* Avoid multivideo tracks when unnecessary */
853
854
        if( track.fmt.i_cat == VIDEO_ES )
            track.fmt.i_priority--;
855
    }
856
857
}

858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
void matroska_segment_c::EnsureDuration()
{
    if ( i_duration > 0 )
        return;

    i_duration = -1;

    bool b_seekable;

    stream_Control( sys.demuxer.s, STREAM_CAN_FASTSEEK, &b_seekable );
    if ( !b_seekable )
    {
        msg_Warn( &sys.demuxer, "could not look for the segment duration" );
        return;
    }

    uint64 i_current_position = es.I_O().getFilePointer();
    uint64 i_last_cluster_pos = 0;

    // find the last Cluster from the Cues
    {
    }

    // find the last Cluster manually
    if ( !i_last_cluster_pos && cluster != NULL )
    {
        es.I_O().setFilePointer( cluster->GetElementPosition(), seek_beginning );
885
886
887

        EbmlElement* el;
        EbmlParser ep( &es, segment, &sys.demuxer,
888
                             var_InheritBool( &sys.demuxer, "mkv-use-dummy" ) );
889

890
        while( ( el = ep.Get() ) != NULL )
891
892
893
894
895
896
897
898
899
900
901
902
903
        {
            if ( MKV_IS_ID( el, KaxCluster ) )
            {
                i_last_cluster_pos = el->GetElementPosition();
            }
        }
    }

    // find the last timecode in the Cluster
    if ( i_last_cluster_pos )
    {
        es.I_O().setFilePointer( i_last_cluster_pos, seek_beginning );

904
905
906
907
        EbmlParser eparser (
            &es , segment, &sys.demuxer, var_InheritBool( &sys.demuxer, "mkv-use-dummy" ) );

        KaxCluster *p_last_cluster = static_cast<KaxCluster*>( eparser.Get() );
908
909
        if( p_last_cluster == NULL )
            return;
910
911
912
913
914
915
916
917
        ParseCluster( p_last_cluster, false, SCOPE_PARTIAL_DATA );

        // use the last block + duration
        uint64 i_last_timecode = p_last_cluster->GlobalTimecode();
        for( unsigned int i = 0; i < p_last_cluster->ListSize(); i++ )
        {
            EbmlElement *l = (*p_last_cluster)[i];

918
            if( MKV_CHECKED_PTR_DECL ( block, KaxSimpleBlock, l ) )
919
920
            {
                block->SetParent( *p_last_cluster );
921
                i_last_timecode = std::max(i_last_timecode, block->GlobalTimecode());
922
            }
923
            else if( MKV_CHECKED_PTR_DECL ( group, KaxBlockGroup, l ) )
924
925
926
927
928
929
            {
                uint64 i_group_timecode = 0;
                for( unsigned int j = 0; j < group->ListSize(); j++ )
                {
                    EbmlElement *l = (*group)[j];

930
                    if( MKV_CHECKED_PTR_DECL ( block, KaxBlock, l ) )
931
932
933
934
                    {
                        block->SetParent( *p_last_cluster );
                        i_group_timecode += block->GlobalTimecode();
                    }
935
                    else if( MKV_CHECKED_PTR_DECL ( kbd_ptr, KaxBlockDuration, l ) )
936
                    {
937
                        i_group_timecode += static_cast<uint64>( *kbd_ptr );
938
939
                    }
                }
940
                i_last_timecode = std::max(i_last_timecode, i_group_timecode);