1 /*****************************************************************************
2  * matroska_segment.cpp : matroska demuxer
3  *****************************************************************************
4  * Copyright (C) 2003-2010 VLC authors and VideoLAN
5  * $Id: 7e2bd8a0aea85a4f3fa9ade2ffda05852a032fed $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Steve Lhomme <steve.lhomme@free.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 #include "matroska_segment.hpp"
26 #include "chapters.hpp"
27 #include "demux.hpp"
28 #include "util.hpp"
29 #include "Ebml_parser.hpp"
30 #include "Ebml_dispatcher.hpp"
31 
32 #include <new>
33 #include <iterator>
34 #include <limits>
35 
matroska_segment_c(demux_sys_t & demuxer,EbmlStream & estream,KaxSegment * p_seg)36 matroska_segment_c::matroska_segment_c( demux_sys_t & demuxer, EbmlStream & estream, KaxSegment *p_seg )
37     :segment(p_seg)
38     ,es(estream)
39     ,i_timescale(MKVD_TIMECODESCALE)
40     ,i_duration(-1)
41     ,i_mk_start_time(0)
42     ,i_seekhead_count(0)
43     ,i_seekhead_position(-1)
44     ,i_cues_position(-1)
45     ,i_tracks_position(-1)
46     ,i_info_position(-1)
47     ,i_chapters_position(-1)
48     ,i_attachments_position(-1)
49     ,cluster(NULL)
50     ,i_block_pos(0)
51     ,p_segment_uid(NULL)
52     ,p_prev_segment_uid(NULL)
53     ,p_next_segment_uid(NULL)
54     ,b_cues(false)
55     ,psz_muxing_application(NULL)
56     ,psz_writing_application(NULL)
57     ,psz_segment_filename(NULL)
58     ,psz_title(NULL)
59     ,psz_date_utc(NULL)
60     ,i_default_edition(0)
61     ,sys(demuxer)
62     ,ep( EbmlParser(&estream, p_seg, &demuxer.demuxer ))
63     ,b_preloaded(false)
64     ,b_ref_external_segments(false)
65 {
66 }
67 
~matroska_segment_c()68 matroska_segment_c::~matroska_segment_c()
69 {
70     free( psz_writing_application );
71     free( psz_muxing_application );
72     free( psz_segment_filename );
73     free( psz_title );
74     free( psz_date_utc );
75 
76     delete segment;
77     delete p_segment_uid;
78     delete p_prev_segment_uid;
79     delete p_next_segment_uid;
80 
81     vlc_delete_all( stored_editions );
82     vlc_delete_all( translations );
83     vlc_delete_all( families );
84 }
85 
86 
87 /*****************************************************************************
88  * Tools                                                                     *
89  *****************************************************************************
90  *  * LoadCues : load the cues element and update index
91  *  * LoadTags : load ... the tags element
92  *  * InformationCreate : create all information, load tags if present
93  *****************************************************************************/
LoadCues(KaxCues * cues)94 void matroska_segment_c::LoadCues( KaxCues *cues )
95 {
96     EbmlElement *el;
97 
98     if( b_cues )
99     {
100         msg_Warn( &sys.demuxer, "There can be only 1 Cues per section." );
101         return;
102     }
103 
104     EbmlParser eparser (&es, cues, &sys.demuxer );
105     while( ( el = eparser.Get() ) != NULL )
106     {
107         if( MKV_IS_ID( el, KaxCuePoint ) )
108         {
109             uint64_t cue_position = -1;
110             mtime_t  cue_mk_time = -1;
111 
112             unsigned int track_id = 0;
113             bool b_invalid_cue = false;
114 
115             eparser.Down();
116             while( ( el = eparser.Get() ) != NULL )
117             {
118                 if ( MKV_CHECKED_PTR_DECL( kct_ptr, KaxCueTime, el ) )
119                 {
120                     try
121                     {
122                         if( unlikely( !kct_ptr->ValidateSize() ) )
123                         {
124                             msg_Err( &sys.demuxer, "CueTime size too big");
125                             b_invalid_cue = true;
126                             break;
127                         }
128                         kct_ptr->ReadData( es.I_O() );
129                     }
130                     catch(...)
131                     {
132                         msg_Err( &sys.demuxer, "Error while reading CueTime" );
133                         b_invalid_cue = true;
134                         break;
135                     }
136                     cue_mk_time = static_cast<uint64>( *kct_ptr ) * i_timescale / INT64_C(1000);
137                 }
138                 else if( MKV_IS_ID( el, KaxCueTrackPositions ) )
139                 {
140                     eparser.Down();
141                     try
142                     {
143                         while( ( el = eparser.Get() ) != NULL )
144                         {
145                             if( unlikely( !el->ValidateSize() ) )
146                             {
147                                 eparser.Up();
148                                 msg_Err( &sys.demuxer, "Error %s too big, aborting", typeid(*el).name() );
149                                 b_invalid_cue = true;
150                                 break;
151                             }
152 
153                             if( MKV_CHECKED_PTR_DECL ( kct_ptr, KaxCueTrack, el ) )
154                             {
155                                 kct_ptr->ReadData( es.I_O() );
156                                 track_id = static_cast<uint16>( *kct_ptr );
157                             }
158                             else if( MKV_CHECKED_PTR_DECL ( kccp_ptr, KaxCueClusterPosition, el ) )
159                             {
160                                 kccp_ptr->ReadData( es.I_O() );
161                                 cue_position = segment->GetGlobalPosition( static_cast<uint64>( *kccp_ptr ) );
162 
163                                 _seeker.add_cluster_position( cue_position );
164                             }
165                             else if( MKV_CHECKED_PTR_DECL ( kcbn_ptr, KaxCueBlockNumber, el ) )
166                             {
167                                 VLC_UNUSED( kcbn_ptr );
168                             }
169 #if LIBMATROSKA_VERSION >= 0x010401
170                             else if( MKV_CHECKED_PTR_DECL( ignored, KaxCueRelativePosition, el ) )
171                             {
172                                 // IGNORE
173                                 ignored->ReadData( es.I_O() );
174                             }
175                             else if( MKV_CHECKED_PTR_DECL( ignored, KaxCueBlockNumber, el ) )
176                             {
177                                 // IGNORE
178                                 ignored->ReadData( es.I_O() );
179                             }
180                             else if( MKV_CHECKED_PTR_DECL( ignored, KaxCueReference, el ) )
181                             {
182                                 // IGNORE
183                                 ignored->ReadData( es.I_O(), SCOPE_ALL_DATA );
184                             }
185                             else if( MKV_CHECKED_PTR_DECL( ignored, KaxCueDuration, el ) )
186                             {
187                                 /* For future use */
188                                 ignored->ReadData( es.I_O() );
189                             }
190 #endif
191                             else
192                             {
193                                 msg_Dbg( &sys.demuxer, "         * Unknown (%s)", typeid(*el).name() );
194                             }
195                         }
196                     }
197                     catch(...)
198                     {
199                         eparser.Up();
200                         msg_Err( &sys.demuxer, "Error while reading %s", typeid(*el).name() );
201                         b_invalid_cue = true;
202                         break;
203                     }
204                     eparser.Up();
205                 }
206                 else
207                 {
208                     msg_Dbg( &sys.demuxer, "     * Unknown (%s)", typeid(*el).name() );
209                 }
210             }
211             eparser.Up();
212 
213             if( track_id != 0 && cue_mk_time != -1 && cue_position != static_cast<uint64_t>( -1 ) ) {
214 
215                 SegmentSeeker::Seekpoint::TrustLevel level = SegmentSeeker::Seekpoint::DISABLED;
216 
217                 if( ! b_invalid_cue && tracks.find( track_id ) != tracks.end() )
218                 {
219                     level = SegmentSeeker::Seekpoint::QUESTIONABLE; // TODO: var_InheritBool( ..., "mkv-trust-cues" );
220                 }
221 
222                 _seeker.add_seekpoint( track_id,
223                     SegmentSeeker::Seekpoint( cue_position, cue_mk_time, level ) );
224             }
225         }
226         else
227         {
228             msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() );
229         }
230     }
231     b_cues = true;
232     msg_Dbg( &sys.demuxer, "|   - loading cues done." );
233 }
234 
235 
236 static const struct {
237     vlc_meta_type_t type;
238     const char *key;
239     int target_type; /* 0 is valid for all target_type */
240 } metadata_map[] = {
241                      {vlc_meta_ShowName,    "TITLE",         70},
242                      {vlc_meta_Album,       "TITLE",         50},
243                      {vlc_meta_Title,       "TITLE",         30},
244                      {vlc_meta_DiscNumber,  "PART_NUMBER",   60},
245                      {vlc_meta_Season,      "PART_NUMBER",   60},
246                      {vlc_meta_Episode,     "PART_NUMBER",   50},
247                      {vlc_meta_TrackNumber, "PART_NUMBER",   30},
248                      {vlc_meta_DiscTotal,   "TOTAL_PARTS",   70},
249                      {vlc_meta_TrackTotal,  "TOTAL_PARTS",   30},
250                      {vlc_meta_Setting,     "ENCODER_SETTINGS", 0},
251                      /* TODO read TagLanguage {vlc_meta_Language} */
252                      /* TODO read tags targeting attachments {vlc_meta_ArtworkURL, */
253                      {vlc_meta_AlbumArtist, "ARTIST",        50},
254                      {vlc_meta_Artist,      "ARTIST",        0},
255                      {vlc_meta_Director,    "DIRECTOR",      0},
256                      {vlc_meta_Actors,      "ACTOR",         0},
257                      {vlc_meta_Genre,       "GENRE",         0},
258                      {vlc_meta_Copyright,   "COPYRIGHT",     0},
259                      {vlc_meta_Description, "DESCRIPTION",   0},
260                      {vlc_meta_Description, "COMMENT",       0},
261                      {vlc_meta_Rating,      "RATING",        0},
262                      {vlc_meta_Date,        "DATE_RELEASED", 0},
263                      {vlc_meta_Date,        "DATE_RELEASE",  0},
264                      {vlc_meta_Date,        "DATE_RECORDED", 0},
265                      {vlc_meta_URL,         "URL",           0},
266                      {vlc_meta_Publisher,   "PUBLISHER",     0},
267                      {vlc_meta_EncodedBy,   "ENCODED_BY",    0},
268                      {vlc_meta_Album,       "ALBUM",         0}, /* invalid tag */
269                      {vlc_meta_Title,       NULL,            0},
270 };
271 
ParseSimpleTags(SimpleTag * pout_simple,KaxTagSimple * tag,int target_type)272 bool matroska_segment_c::ParseSimpleTags( SimpleTag* pout_simple, KaxTagSimple *tag, int target_type )
273 {
274     EbmlParser eparser ( &es, tag, &sys.demuxer );
275     EbmlElement *el;
276     size_t max_size = tag->GetSize();
277     size_t size = 0;
278 
279     if( !sys.meta )
280         sys.meta = vlc_meta_New();
281 
282     msg_Dbg( &sys.demuxer, "|   + Simple Tag ");
283     try
284     {
285         while( ( el = eparser.Get() ) != NULL && size < max_size)
286         {
287             if( unlikely( !el->ValidateSize() ) )
288             {
289                 msg_Err( &sys.demuxer, "Error %s too big ignoring the tag", typeid(*el).name() );
290                 return false;
291             }
292             if( MKV_CHECKED_PTR_DECL ( ktn_ptr, KaxTagName, el ) )
293             {
294                 ktn_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA );
295                 pout_simple->tag_name = UTFstring( *ktn_ptr ).GetUTF8().c_str();
296             }
297             else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagString, el ) )
298             {
299                 kts_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA );
300                 pout_simple->value = UTFstring( *kts_ptr ).GetUTF8().c_str();
301             }
302             else if(  MKV_CHECKED_PTR_DECL ( ktl_ptr, KaxTagLangue, el ) )
303             {
304                 ktl_ptr->ReadData( es.I_O(), SCOPE_ALL_DATA );
305                 pout_simple->lang = *ktl_ptr;
306             }
307             else if(  MKV_CHECKED_PTR_DECL ( ktd_ptr, KaxTagDefault, el ) )
308             {
309                 VLC_UNUSED(ktd_ptr); // TODO: we do not care about this value, but maybe we should?
310             }
311             /*Tags can be nested*/
312             else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagSimple, el) )
313             {
314                 SimpleTag st; // ParseSimpleTags will write to this variable
315                               // the SimpleTag is valid if ParseSimpleTags returns `true`
316 
317                 if (ParseSimpleTags( &st, kts_ptr, target_type )) {
318                   pout_simple->sub_tags.push_back( st );
319                 }
320             }
321             /*TODO Handle binary tags*/
322             size += el->HeadSize() + el->GetSize();
323         }
324     }
325     catch(...)
326     {
327         msg_Err( &sys.demuxer, "Error while reading Tag ");
328         return false;
329     }
330 
331     if( pout_simple->tag_name.empty() )
332     {
333         msg_Warn( &sys.demuxer, "Invalid MKV SimpleTag found.");
334         return false;
335     }
336     for( int i = 0; metadata_map[i].key; i++ )
337     {
338         if( pout_simple->tag_name == metadata_map[i].key &&
339             (metadata_map[i].target_type == 0 || target_type == metadata_map[i].target_type ) )
340         {
341             vlc_meta_Set( sys.meta, metadata_map[i].type, pout_simple->value.c_str () );
342             msg_Dbg( &sys.demuxer, "|   |   + Meta %s: %s", pout_simple->tag_name.c_str (), pout_simple->value.c_str ());
343             goto done;
344         }
345     }
346     msg_Dbg( &sys.demuxer, "|   |   + Meta %s: %s", pout_simple->tag_name.c_str (), pout_simple->value.c_str ());
347     vlc_meta_AddExtra( sys.meta, pout_simple->tag_name.c_str (), pout_simple->value.c_str ());
348 done:
349     return true;
350 }
351 
LoadTags(KaxTags * tags)352 void matroska_segment_c::LoadTags( KaxTags *tags )
353 {
354     /* Master elements */
355     EbmlParser eparser = EbmlParser( &es, tags, &sys.demuxer );
356     EbmlElement *el;
357 
358     while( ( el = eparser.Get() ) != NULL )
359     {
360         if( MKV_IS_ID( el, KaxTag ) )
361         {
362             Tag tag;
363 
364             msg_Dbg( &sys.demuxer, "+ Tag" );
365             eparser.Down();
366             int target_type = 50;
367             while( ( el = eparser.Get() ) != NULL )
368             {
369                 if( MKV_IS_ID( el, KaxTagTargets ) )
370                 {
371                     msg_Dbg( &sys.demuxer, "|   + Targets" );
372                     eparser.Down();
373                     while( ( el = eparser.Get() ) != NULL )
374                     {
375                         try
376                         {
377                             if( unlikely( !el->ValidateSize() ) )
378                             {
379                                 msg_Err( &sys.demuxer, "Invalid size while reading tag");
380                                 break;
381                             }
382                             if( MKV_CHECKED_PTR_DECL ( ktttv_ptr, KaxTagTargetTypeValue, el ) )
383                             {
384                                 ktttv_ptr->ReadData( es.I_O() );
385 
386                                 msg_Dbg( &sys.demuxer, "|   |   + TargetTypeValue: %u", uint32(*ktttv_ptr));
387                                 target_type = static_cast<uint32>( *ktttv_ptr );
388                             }
389                             else if( MKV_CHECKED_PTR_DECL ( kttu_ptr, KaxTagTrackUID, el ) )
390                             {
391                                 tag.i_tag_type = TRACK_UID;
392                                 kttu_ptr->ReadData( es.I_O() );
393                                 tag.i_uid = static_cast<uint64>( *kttu_ptr );
394                                 msg_Dbg( &sys.demuxer, "|   |   + TrackUID: %" PRIu64, tag.i_uid);
395 
396                             }
397                             else if( MKV_CHECKED_PTR_DECL ( kteu_ptr, KaxTagEditionUID, el ) )
398                             {
399                                 tag.i_tag_type = EDITION_UID;
400                                 kteu_ptr->ReadData( es.I_O() );
401                                 tag.i_uid = static_cast<uint64>( *kteu_ptr );
402                                 msg_Dbg( &sys.demuxer, "|   |   + EditionUID: %" PRIu64, tag.i_uid);
403                             }
404                             else if( MKV_CHECKED_PTR_DECL ( ktcu_ptr, KaxTagChapterUID, el ) )
405                             {
406                                 tag.i_tag_type = CHAPTER_UID;
407                                 ktcu_ptr->ReadData( es.I_O() );
408                                 tag.i_uid = static_cast<uint64>( *ktcu_ptr );
409                                 msg_Dbg( &sys.demuxer, "|   |   + ChapterUID: %" PRIu64, tag.i_uid);
410                             }
411                             else if( MKV_CHECKED_PTR_DECL ( ktau_ptr, KaxTagAttachmentUID, el ) )
412                             {
413                                 tag.i_tag_type = ATTACHMENT_UID;
414                                 ktau_ptr->ReadData( es.I_O() );
415                                 tag.i_uid = static_cast<uint64>( *ktau_ptr );
416                                 msg_Dbg( &sys.demuxer, "|   |   + AttachmentUID: %" PRIu64, tag.i_uid);
417                             }
418                             if( MKV_CHECKED_PTR_DECL ( ktttv_ptr, KaxTagTargetType, el ) )
419                             {
420                                 ktttv_ptr->ReadData( es.I_O() );
421 
422                                 msg_Dbg( &sys.demuxer, "|   |   + TargetType: %s", ktttv_ptr->GetValue().c_str());
423                             }
424                             else
425                             {
426                                 msg_Dbg( &sys.demuxer, "|   |   + LoadTag Unknown (%s)", typeid( *el ).name() );
427                             }
428                         }
429                         catch(...)
430                         {
431                             msg_Err( &sys.demuxer, "Error while reading tag");
432                             break;
433                         }
434                     }
435                     eparser.Up();
436                 }
437                 else if( MKV_CHECKED_PTR_DECL ( kts_ptr, KaxTagSimple, el ) )
438                 {
439                     SimpleTag simple;
440 
441                     if (ParseSimpleTags(&simple, kts_ptr, target_type )) {
442                       tag.simple_tags.push_back( simple );
443                     }
444                 }
445                 else
446                 {
447                     msg_Dbg( &sys.demuxer, "|   + LoadTag Unknown (%s)", typeid( *el ).name() );
448                 }
449             }
450             eparser.Up();
451             this->tags.push_back(tag);
452         }
453         else
454         {
455             msg_Dbg( &sys.demuxer, "+ Unknown (%s)", typeid( *el ).name() );
456         }
457     }
458 
459     msg_Dbg( &sys.demuxer, "loading tags done." );
460 }
461 
462 /*****************************************************************************
463  * InformationCreate:
464  *****************************************************************************/
InformationCreate()465 void matroska_segment_c::InformationCreate( )
466 {
467     if( !sys.meta )
468         sys.meta = vlc_meta_New();
469 
470     if( psz_title )
471     {
472         vlc_meta_SetTitle( sys.meta, psz_title );
473     }
474 }
475 
476 
477 /*****************************************************************************
478  * Misc
479  *****************************************************************************/
480 
IndexAppendCluster(KaxCluster * cluster)481 void matroska_segment_c::IndexAppendCluster( KaxCluster *cluster )
482 {
483     _seeker.add_cluster( cluster );
484 }
485 
PreloadClusters(uint64 i_cluster_pos)486 bool matroska_segment_c::PreloadClusters(uint64 i_cluster_pos)
487 {
488     struct ClusterHandlerPayload
489     {
490         matroska_segment_c * const obj;
491         bool stop_parsing;
492 
493     } payload = { this, false };
494 
495     MKV_SWITCH_CREATE(EbmlTypeDispatcher, ClusterHandler, ClusterHandlerPayload )
496     {
497         MKV_SWITCH_INIT();
498 
499         E_CASE( KaxCluster, kcluster )
500         {
501             if( vars.obj->ParseCluster( &kcluster, false ) )
502                 vars.obj->IndexAppendCluster( &kcluster );
503         }
504 
505         E_CASE_DEFAULT( el )
506         {
507             VLC_UNUSED( el );
508             vars.stop_parsing = true;
509         }
510     };
511 
512     {
513         es.I_O().setFilePointer( i_cluster_pos );
514 
515         while (payload.stop_parsing == false)
516         {
517             EbmlParser parser ( &es, segment, &sys.demuxer );
518             EbmlElement* el = parser.Get();
519 
520             if( el == NULL )
521                 break;
522 
523             ClusterHandler::Dispatcher().send( el, &payload );
524         }
525     }
526 
527     return true;
528 }
529 
PreloadFamily(const matroska_segment_c & of_segment)530 bool matroska_segment_c::PreloadFamily( const matroska_segment_c & of_segment )
531 {
532     if ( b_preloaded )
533         return false;
534 
535     if ( SameFamily( of_segment ) )
536         return Preload( );
537 
538     return false;
539 }
540 
CompareSegmentUIDs(const matroska_segment_c * p_item_a,const matroska_segment_c * p_item_b)541 bool matroska_segment_c::CompareSegmentUIDs( const matroska_segment_c * p_item_a, const matroska_segment_c * p_item_b )
542 {
543     EbmlBinary *p_tmp;
544 
545     if ( p_item_a == NULL || p_item_b == NULL )
546         return false;
547 
548     p_tmp = static_cast<EbmlBinary *>( p_item_a->p_segment_uid );
549     if ( !p_tmp )
550         return false;
551     if ( p_item_b->p_prev_segment_uid != NULL
552           && *p_tmp == *p_item_b->p_prev_segment_uid )
553         return true;
554 
555     p_tmp = static_cast<EbmlBinary *>( p_item_a->p_next_segment_uid );
556     if ( !p_tmp )
557         return false;
558 
559     if ( p_item_b->p_segment_uid != NULL
560           && *p_tmp == *p_item_b->p_segment_uid )
561         return true;
562 
563     if ( p_item_b->p_prev_segment_uid != NULL
564           && *p_tmp == *p_item_b->p_prev_segment_uid )
565         return true;
566 
567     return false;
568 }
569 
SameFamily(const matroska_segment_c & of_segment) const570 bool matroska_segment_c::SameFamily( const matroska_segment_c & of_segment ) const
571 {
572     for (size_t i=0; i<families.size(); i++)
573     {
574         for (size_t j=0; j<of_segment.families.size(); j++)
575         {
576             if ( *(families[i]) == *(of_segment.families[j]) )
577                 return true;
578         }
579     }
580     return false;
581 }
582 
Preload()583 bool matroska_segment_c::Preload( )
584 {
585     if ( b_preloaded )
586         return false;
587 
588     EbmlElement *el = NULL;
589 
590     ep.Reset( &sys.demuxer );
591 
592     while( ( el = ep.Get() ) != NULL )
593     {
594         if( MKV_IS_ID( el, KaxSeekHead ) )
595         {
596             /* Multiple allowed */
597             /* We bail at 10, to prevent possible recursion */
598             msg_Dbg(  &sys.demuxer, "|   + Seek head" );
599             if( i_seekhead_count < 10 )
600             {
601                 i_seekhead_position = el->GetElementPosition();
602                 ParseSeekHead( static_cast<KaxSeekHead*>( el ) );
603             }
604         }
605         else if( MKV_IS_ID( el, KaxInfo ) )
606         {
607             /* Multiple allowed, mandatory */
608             msg_Dbg(  &sys.demuxer, "|   + Information" );
609             if( i_info_position < 0 )
610             {
611                 ParseInfo( static_cast<KaxInfo*>( el ) );
612                 i_info_position = el->GetElementPosition();
613             }
614         }
615         else if( MKV_CHECKED_PTR_DECL ( kt_ptr, KaxTracks, el ) )
616         {
617             /* Multiple allowed */
618             msg_Dbg(  &sys.demuxer, "|   + Tracks" );
619             if( i_tracks_position < 0 )
620             {
621                 ParseTracks( kt_ptr );
622             }
623             if ( tracks.size() == 0 )
624             {
625                 msg_Err( &sys.demuxer, "No tracks supported" );
626             }
627             i_tracks_position = el->GetElementPosition();
628         }
629         else if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxCues, el ) )
630         {
631             msg_Dbg(  &sys.demuxer, "|   + Cues" );
632             if( i_cues_position < 0 )
633             {
634                 LoadCues( kc_ptr );
635                 i_cues_position = el->GetElementPosition();
636             }
637         }
638         else if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxCluster, el ) )
639         {
640             if( var_InheritBool( &sys.demuxer, "mkv-preload-clusters" ) )
641             {
642                 PreloadClusters        ( kc_ptr->GetElementPosition() );
643                 es.I_O().setFilePointer( kc_ptr->GetElementPosition() );
644             }
645             msg_Dbg( &sys.demuxer, "|   + Cluster" );
646 
647             if( !ParseCluster( kc_ptr ) )
648                 break;
649 
650             cluster = kc_ptr;
651             IndexAppendCluster( cluster );
652 
653             // add first cluster as trusted seekpoint for all tracks
654             for( tracks_map_t::const_iterator it = tracks.begin();
655                  it != tracks.end(); ++it )
656             {
657                 _seeker.add_seekpoint( it->first,
658                     SegmentSeeker::Seekpoint( cluster->GetElementPosition(), 0 ) );
659             }
660 
661             ep.Down();
662             /* stop pre-parsing the stream */
663             break;
664         }
665         else if( MKV_CHECKED_PTR_DECL ( ka_ptr, KaxAttachments, el ) )
666         {
667             msg_Dbg( &sys.demuxer, "|   + Attachments" );
668             if( i_attachments_position < 0 )
669             {
670                 ParseAttachments( ka_ptr );
671                 i_attachments_position = el->GetElementPosition();
672             }
673         }
674         else if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxChapters, el ) )
675         {
676             msg_Dbg( &sys.demuxer, "|   + Chapters" );
677             if( i_chapters_position < 0 )
678             {
679                 ParseChapters( kc_ptr );
680                 i_chapters_position = el->GetElementPosition();
681             }
682         }
683         else if( MKV_CHECKED_PTR_DECL ( kt_ptr, KaxTags, el ) )
684         {
685             msg_Dbg( &sys.demuxer, "|   + Tags" );
686             if(tags.empty ())
687             {
688                 LoadTags( kt_ptr );
689             }
690         }
691         else if( MKV_IS_ID ( el, EbmlVoid ) )
692             msg_Dbg( &sys.demuxer, "|   + Void" );
693         else
694             msg_Dbg( &sys.demuxer, "|   + Preload Unknown (%s)", typeid(*el).name() );
695     }
696 
697     ComputeTrackPriority();
698 
699     b_preloaded = true;
700 
701     if( cluster )
702         EnsureDuration();
703 
704     return true;
705 }
706 
707 /* Here we try to load elements that were found in Seek Heads, but not yet parsed */
LoadSeekHeadItem(const EbmlCallbacks & ClassInfos,int64_t i_element_position)708 bool matroska_segment_c::LoadSeekHeadItem( const EbmlCallbacks & ClassInfos, int64_t i_element_position )
709 {
710     int64_t     i_sav_position = static_cast<int64_t>( es.I_O().getFilePointer() );
711     EbmlElement *el;
712 
713     es.I_O().setFilePointer( i_element_position, seek_beginning );
714     el = es.FindNextID( ClassInfos, 0xFFFFFFFFL);
715 
716     if( el == NULL )
717     {
718         msg_Err( &sys.demuxer, "cannot load some cues/chapters/tags etc. (broken seekhead or file)" );
719         es.I_O().setFilePointer( i_sav_position, seek_beginning );
720         return false;
721     }
722 
723     if( MKV_CHECKED_PTR_DECL ( ksh_ptr, KaxSeekHead, el ) )
724     {
725         /* Multiple allowed */
726         msg_Dbg( &sys.demuxer, "|   + Seek head" );
727         if( i_seekhead_count < 10 )
728         {
729             if ( i_seekhead_position != i_element_position )
730             {
731                 i_seekhead_position = i_element_position;
732                 ParseSeekHead( ksh_ptr );
733             }
734         }
735     }
736     else if( MKV_CHECKED_PTR_DECL ( ki_ptr, KaxInfo, el ) ) // FIXME
737     {
738         /* Multiple allowed, mandatory */
739         msg_Dbg( &sys.demuxer, "|   + Information" );
740         if( i_info_position < 0 )
741         {
742             ParseInfo( ki_ptr );
743             i_info_position = i_element_position;
744         }
745     }
746     else if( MKV_CHECKED_PTR_DECL ( kt_ptr, KaxTracks, el ) ) // FIXME
747     {
748         /* Multiple allowed */
749         msg_Dbg( &sys.demuxer, "|   + Tracks" );
750         if( i_tracks_position < 0 )
751             ParseTracks( kt_ptr );
752         if ( tracks.size() == 0 )
753         {
754             msg_Err( &sys.demuxer, "No tracks supported" );
755             delete el;
756             es.I_O().setFilePointer( i_sav_position, seek_beginning );
757             return false;
758         }
759         i_tracks_position = i_element_position;
760     }
761     else if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxCues, el ) )
762     {
763         msg_Dbg( &sys.demuxer, "|   + Cues" );
764         if( i_cues_position < 0 )
765         {
766             LoadCues( kc_ptr );
767             i_cues_position = i_element_position;
768         }
769     }
770     else if( MKV_CHECKED_PTR_DECL ( ka_ptr, KaxAttachments, el ) )
771     {
772         msg_Dbg( &sys.demuxer, "|   + Attachments" );
773         if( i_attachments_position < 0 )
774         {
775             ParseAttachments( ka_ptr );
776             i_attachments_position = i_element_position;
777         }
778     }
779     else if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxChapters, el ) )
780     {
781         msg_Dbg( &sys.demuxer, "|   + Chapters" );
782         if( i_chapters_position < 0 )
783         {
784             ParseChapters( kc_ptr );
785             i_chapters_position = i_element_position;
786         }
787     }
788     else if( MKV_CHECKED_PTR_DECL ( kt_ptr, KaxTags, el ) )
789     {
790         msg_Dbg( &sys.demuxer, "|   + Tags" );
791         if(tags.empty ())
792         {
793             LoadTags( kt_ptr );
794         }
795     }
796     else
797     {
798         msg_Dbg( &sys.demuxer, "|   + LoadSeekHeadItem Unknown (%s)", typeid(*el).name() );
799     }
800     delete el;
801 
802     es.I_O().setFilePointer( i_sav_position, seek_beginning );
803     return true;
804 }
805 
Seek(demux_t & demuxer,mtime_t i_absolute_mk_date,mtime_t i_mk_time_offset,bool b_accurate)806 bool matroska_segment_c::Seek( demux_t &demuxer, mtime_t i_absolute_mk_date, mtime_t i_mk_time_offset, bool b_accurate )
807 {
808     SegmentSeeker::tracks_seekpoint_t seekpoints;
809 
810     SegmentSeeker::fptr_t i_seek_position = std::numeric_limits<SegmentSeeker::fptr_t>::max();
811     mtime_t i_mk_seek_time = -1;
812     mtime_t i_mk_date = i_absolute_mk_date - i_mk_time_offset;
813     SegmentSeeker::track_ids_t selected_tracks;
814     SegmentSeeker::track_ids_t priority;
815 
816     // reset information for all tracks //
817 
818     for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it )
819     {
820         mkv_track_t &track = *it->second;
821 
822         track.i_skip_until_fpos = std::numeric_limits<uint64_t>::max();
823         if( track.i_last_dts > VLC_TS_INVALID )
824             track.b_discontinuity = true;
825         track.i_last_dts        = VLC_TS_INVALID;
826 
827         bool selected;
828         if (track.p_es == NULL)
829             selected = false;
830         else
831             es_out_Control( demuxer.out, ES_OUT_GET_ES_STATE, track.p_es, &selected );
832         if ( selected )
833             selected_tracks.push_back( track.i_number );
834     }
835 
836     if ( selected_tracks.empty() )
837     {
838         selected_tracks = priority_tracks;
839         priority = priority_tracks;
840     }
841     else
842     {
843         std::set_intersection(priority_tracks.begin(),priority_tracks.end(),
844                               selected_tracks.begin(),selected_tracks.end(),
845                               std::back_inserter(priority));
846         if (priority.empty()) // no video selected ?
847             priority = selected_tracks;
848     }
849 
850     // find appropriate seekpoints //
851 
852     try {
853         seekpoints = _seeker.get_seekpoints( *this, i_mk_date, priority, selected_tracks );
854     }
855     catch( std::exception const& e )
856     {
857         msg_Err( &sys.demuxer, "error during seek: \"%s\", aborting!", e.what() );
858         return false;
859     }
860 
861     // initialize seek information in order to set up playback //
862 
863     for( SegmentSeeker::tracks_seekpoint_t::const_iterator it = seekpoints.begin(); it != seekpoints.end(); ++it )
864     {
865         tracks_map_t::iterator trackit = tracks.find( it->first );
866         if ( trackit == tracks.end() )
867             continue; // there were blocks with unknown tracks
868 
869         if( i_seek_position > it->second.fpos )
870         {
871             i_seek_position = it->second.fpos;
872             i_mk_seek_time  = it->second.pts;
873         }
874 
875         // blocks that will be not be read until this fpos
876         if ( b_accurate )
877             trackit->second->i_skip_until_fpos = it->second.fpos;
878         else
879             trackit->second->i_skip_until_fpos = std::numeric_limits<uint64_t>::max();
880         trackit->second->i_last_dts        = it->second.pts + i_mk_time_offset;
881 
882         msg_Dbg( &sys.demuxer, "seek: preroll{ track: %u, pts: %" PRId64 ", fpos: %" PRIu64 " skip: %" PRIu64 "} ",
883           it->first, it->second.pts, it->second.fpos, trackit->second->i_skip_until_fpos );
884     }
885 
886     if ( i_seek_position == std::numeric_limits<SegmentSeeker::fptr_t>::max() )
887         return false;
888 
889     // propogate seek information //
890 
891     sys.i_pcr           = VLC_TS_INVALID;
892     sys.i_pts           = VLC_TS_0 + i_mk_seek_time + i_mk_time_offset;
893     if (b_accurate)
894         sys.i_start_pts = VLC_TS_0 + i_absolute_mk_date;
895     else
896         sys.i_start_pts = sys.i_pts;
897 
898     // make the jump //
899 
900     _seeker.mkv_jump_to( *this, i_seek_position );
901 
902     // debug diagnostics //
903 
904     msg_Dbg( &sys.demuxer, "seek: preroll{ req: %" PRId64 ", start-pts: %" PRId64 ", start-fpos: %" PRIu64 "} ",
905       sys.i_start_pts, sys.i_pts, i_seek_position );
906 
907     // blocks that will be read and decoded but discarded until this pts
908     es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, sys.i_start_pts );
909     return true;
910 }
911 
912 
FindTrackByBlock(const KaxBlock * p_block,const KaxSimpleBlock * p_simpleblock)913 mkv_track_t * matroska_segment_c::FindTrackByBlock(
914                                              const KaxBlock *p_block, const KaxSimpleBlock *p_simpleblock )
915 {
916     tracks_map_t::iterator track_it;
917 
918     if (p_block != NULL)
919         track_it = tracks.find( p_block->TrackNum() );
920     else if( p_simpleblock != NULL)
921         track_it = tracks.find( p_simpleblock->TrackNum() );
922     else
923         track_it = tracks.end();
924 
925     if (track_it == tracks.end())
926         return NULL;
927 
928     return track_it->second.get();
929 }
930 
ComputeTrackPriority()931 void matroska_segment_c::ComputeTrackPriority()
932 {
933     bool b_has_default_video = false;
934     bool b_has_default_audio = false;
935     /* check for default */
936     for( tracks_map_t::const_iterator it = tracks.begin(); it != tracks.end();
937          ++it )
938     {
939         mkv_track_t &track = *it->second;
940 
941         bool flag = track.b_enabled && ( track.b_default || track.b_forced );
942 
943         switch( track.fmt.i_cat )
944         {
945             case VIDEO_ES: b_has_default_video |= flag; break;
946             case AUDIO_ES: b_has_default_audio |= flag; break;
947             default: break; // ignore
948         }
949     }
950 
951     for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it )
952     {
953         tracks_map_t::key_type track_id = it->first;
954         mkv_track_t          & track    = *it->second;
955 
956         if( unlikely( track.fmt.i_cat == UNKNOWN_ES || track.codec.empty() ) )
957         {
958             msg_Warn( &sys.demuxer, "invalid track[%d]", static_cast<int>( track_id ) );
959             track.p_es = NULL;
960             continue;
961         }
962         else if( unlikely( !b_has_default_video && track.fmt.i_cat == VIDEO_ES ) )
963         {
964             track.b_default = true;
965             b_has_default_video = true;
966         }
967         else if( unlikely( !b_has_default_audio &&  track.fmt.i_cat == AUDIO_ES ) )
968         {
969             track.b_default = true;
970             b_has_default_audio = true;
971         }
972         if( unlikely( !track.b_enabled ) )
973             track.fmt.i_priority = ES_PRIORITY_NOT_SELECTABLE;
974         else if( track.b_forced )
975             track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 2;
976         else if( track.b_default )
977             track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 1;
978         else
979             track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN;
980 
981         /* Avoid multivideo tracks when unnecessary */
982         if( track.fmt.i_cat == VIDEO_ES )
983             track.fmt.i_priority--;
984     }
985 
986     // find track(s) with highest priority //
987     {
988         int   score = -1;
989         int es_type = -1;
990 
991         for( tracks_map_t::const_iterator it = this->tracks.begin(); it != this->tracks.end(); ++it )
992         {
993             int track_score = -1;
994 
995             switch( it->second->fmt.i_cat )
996             {
997                 case VIDEO_ES: ++track_score;
998                 case AUDIO_ES: ++track_score;
999                 case   SPU_ES: ++track_score;
1000                 default:
1001                   if( score < track_score )
1002                   {
1003                       es_type = it->second->fmt.i_cat;
1004                       score   = track_score;
1005                   }
1006             }
1007         }
1008 
1009         for( tracks_map_t::const_iterator it = this->tracks.begin(); it != this->tracks.end(); ++it )
1010         {
1011             if( it->second->fmt.i_cat == es_type )
1012                 priority_tracks.push_back( it->first );
1013         }
1014     }
1015 }
1016 
EnsureDuration()1017 void matroska_segment_c::EnsureDuration()
1018 {
1019     if ( i_duration > 0 )
1020         return;
1021 
1022     i_duration = -1;
1023 
1024     bool b_seekable;
1025 
1026     if( vlc_stream_Control( sys.demuxer.s, STREAM_CAN_FASTSEEK, &b_seekable ) ||
1027         !b_seekable )
1028     {
1029         msg_Warn( &sys.demuxer, "could not look for the segment duration" );
1030         return;
1031     }
1032 
1033     uint64 i_current_position = es.I_O().getFilePointer();
1034     uint64 i_last_cluster_pos = cluster->GetElementPosition();
1035 
1036     // find the last Cluster from the Cues
1037 
1038     if ( b_cues && _seeker._cluster_positions.size() )
1039         i_last_cluster_pos = *_seeker._cluster_positions.rbegin();
1040     else if( !cluster->IsFiniteSize() )
1041         return;
1042 
1043     es.I_O().setFilePointer( i_last_cluster_pos, seek_beginning );
1044 
1045     EbmlParser eparser ( &es, segment, &sys.demuxer );
1046 
1047     // locate the definitely last cluster in the stream
1048 
1049     while( EbmlElement* el = eparser.Get() )
1050     {
1051         if( !el->IsFiniteSize() && el->GetElementPosition() != i_last_cluster_pos )
1052         {
1053             es.I_O().setFilePointer( i_current_position, seek_beginning );
1054             return;
1055         }
1056 
1057         if( MKV_IS_ID( el, KaxCluster ) )
1058         {
1059             i_last_cluster_pos = el->GetElementPosition();
1060             if ( i_last_cluster_pos == cluster->GetElementPosition() )
1061                 // make sure our first Cluster has a timestamp
1062                 ParseCluster( cluster, false, SCOPE_PARTIAL_DATA );
1063         }
1064     }
1065 
1066     // find the last timecode in the Cluster
1067 
1068     eparser.Reset( &sys.demuxer );
1069     es.I_O().setFilePointer( i_last_cluster_pos, seek_beginning );
1070 
1071     EbmlElement* el = eparser.Get();
1072     MKV_CHECKED_PTR_DECL( p_last_cluster, KaxCluster, el );
1073 
1074     if( p_last_cluster &&
1075         ParseCluster( p_last_cluster, false, SCOPE_PARTIAL_DATA ) )
1076     {
1077         // use the last block + duration
1078         uint64 i_last_timecode = p_last_cluster->GlobalTimecode();
1079         for( unsigned int i = 0; i < p_last_cluster->ListSize(); i++ )
1080         {
1081             EbmlElement *l = (*p_last_cluster)[i];
1082 
1083             if( MKV_CHECKED_PTR_DECL ( block, KaxSimpleBlock, l ) )
1084             {
1085                 block->SetParent( *p_last_cluster );
1086                 i_last_timecode = std::max(i_last_timecode, block->GlobalTimecode());
1087             }
1088             else if( MKV_CHECKED_PTR_DECL ( group, KaxBlockGroup, l ) )
1089             {
1090                 uint64 i_group_timecode = 0;
1091                 for( unsigned int j = 0; j < group->ListSize(); j++ )
1092                 {
1093                     EbmlElement *l = (*group)[j];
1094 
1095                     if( MKV_CHECKED_PTR_DECL ( block, KaxBlock, l ) )
1096                     {
1097                         block->SetParent( *p_last_cluster );
1098                         i_group_timecode += block->GlobalTimecode();
1099                     }
1100                     else if( MKV_CHECKED_PTR_DECL ( kbd_ptr, KaxBlockDuration, l ) )
1101                     {
1102                         i_group_timecode += static_cast<uint64>( *kbd_ptr );
1103                     }
1104                 }
1105                 i_last_timecode = std::max(i_last_timecode, i_group_timecode);
1106             }
1107         }
1108 
1109         i_duration = ( i_last_timecode - cluster->GlobalTimecode() ) / INT64_C(1000000);
1110         msg_Dbg( &sys.demuxer, " extracted Duration=%" PRId64, i_duration );
1111     }
1112 
1113     // get back to the reading position we were at before looking for a duration
1114     es.I_O().setFilePointer( i_current_position, seek_beginning );
1115 }
1116 
ESCreate()1117 bool matroska_segment_c::ESCreate()
1118 {
1119     /* add all es */
1120     msg_Dbg( &sys.demuxer, "found %d es", static_cast<int>( tracks.size() ) );
1121     es_out_Control( sys.demuxer.out, ES_OUT_SET_ES_CAT_POLICY, VIDEO_ES,
1122                     ES_OUT_ES_POLICY_EXCLUSIVE );
1123 
1124     mkv_track_t *default_tracks[ES_CATEGORY_COUNT] = {};
1125     for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it )
1126     {
1127         tracks_map_t::key_type   track_id = it->first;
1128         mkv_track_t            & track    = *it->second;
1129 
1130         if( unlikely( track.fmt.i_cat == UNKNOWN_ES || track.codec.empty() ) )
1131         {
1132             msg_Warn( &sys.demuxer, "invalid track[%d]", static_cast<int>( track_id ) );
1133             track.p_es = NULL;
1134             continue;
1135         }
1136 
1137         if( !track.p_es )
1138             track.p_es = es_out_Add( sys.demuxer.out, &track.fmt );
1139 
1140         /* Turn on a subtitles track if it has been flagged as default -
1141          * but only do this if no subtitles track has already been engaged,
1142          * either by an earlier 'default track' (??) or by default
1143          * language choice behaviour.
1144          */
1145         if( track.b_default || track.b_forced )
1146         {
1147             mkv_track_t *&default_track = default_tracks[track.fmt.i_cat];
1148             if( !default_track || track.b_default )
1149                 default_track = &track;
1150         }
1151 
1152     }
1153 
1154     for( mkv_track_t *track : default_tracks )
1155     {
1156         if( track )
1157             es_out_Control( sys.demuxer.out, ES_OUT_SET_ES_DEFAULT, track->p_es );
1158     }
1159 
1160     return true;
1161 }
1162 
ESDestroy()1163 void matroska_segment_c::ESDestroy( )
1164 {
1165     sys.p_ev->ResetPci();
1166 
1167     for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it )
1168     {
1169         mkv_track_t & track = *it->second;
1170 
1171         if( track.p_es != NULL )
1172         {
1173             es_out_Del( sys.demuxer.out, track.p_es );
1174             track.p_es = NULL;
1175         }
1176     }
1177 }
1178 
BlockGet(KaxBlock * & pp_block,KaxSimpleBlock * & pp_simpleblock,KaxBlockAdditions * & pp_additions,bool * pb_key_picture,bool * pb_discardable_picture,int64_t * pi_duration)1179 int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_simpleblock,
1180                                   KaxBlockAdditions * & pp_additions,
1181                                   bool *pb_key_picture, bool *pb_discardable_picture,
1182                                   int64_t *pi_duration )
1183 {
1184     pp_simpleblock = NULL;
1185     pp_block = NULL;
1186     pp_additions = NULL;
1187 
1188     *pb_key_picture         = true;
1189     *pb_discardable_picture = false;
1190     *pi_duration = 0;
1191 
1192     struct BlockPayload {
1193         matroska_segment_c * const obj;
1194         EbmlParser         * const ep;
1195         demux_t            * const p_demuxer;
1196         KaxBlock          *& block;
1197         KaxSimpleBlock    *& simpleblock;
1198         KaxBlockAdditions *& additions;
1199 
1200         int64_t            & i_duration;
1201         bool               & b_key_picture;
1202         bool               & b_discardable_picture;
1203         bool                 b_cluster_timecode;
1204 
1205     } payload = {
1206         this, &ep, &sys.demuxer, pp_block, pp_simpleblock, pp_additions,
1207         *pi_duration, *pb_key_picture, *pb_discardable_picture, true
1208     };
1209 
1210     MKV_SWITCH_CREATE( EbmlTypeDispatcher, BlockGetHandler_l1, BlockPayload )
1211     {
1212         MKV_SWITCH_INIT();
1213 
1214         E_CASE( KaxCluster, kcluster )
1215         {
1216             vars.obj->cluster = &kcluster;
1217             vars.b_cluster_timecode = false;
1218             vars.ep->Down ();
1219         }
1220         E_CASE( KaxCues, kcue )
1221         {
1222             VLC_UNUSED( kcue );
1223             msg_Warn( vars.p_demuxer, "find KaxCues FIXME" );
1224         }
1225         E_CASE_DEFAULT(element)
1226         {
1227             msg_Dbg( vars.p_demuxer, "Unknown (%s)", typeid (element).name () );
1228         }
1229     };
1230 
1231     MKV_SWITCH_CREATE( EbmlTypeDispatcher, BlockGetHandler_l2, BlockPayload )
1232     {
1233         MKV_SWITCH_INIT();
1234 
1235         E_CASE( KaxClusterTimecode, ktimecode )
1236         {
1237             ktimecode.ReadData( vars.obj->es.I_O(), SCOPE_ALL_DATA );
1238             vars.obj->cluster->InitTimecode( static_cast<uint64>( ktimecode ), vars.obj->i_timescale );
1239             vars.obj->IndexAppendCluster( vars.obj->cluster );
1240             vars.b_cluster_timecode = true;
1241         }
1242         E_CASE( KaxClusterSilentTracks, ksilent )
1243         {
1244             vars.ep->Down ();
1245 
1246             VLC_UNUSED( ksilent );
1247         }
1248         E_CASE( KaxBlockGroup, kbgroup )
1249         {
1250             vars.obj->i_block_pos = kbgroup.GetElementPosition();
1251             vars.ep->Down ();
1252         }
1253         E_CASE( KaxSimpleBlock, ksblock )
1254         {
1255             if( vars.b_cluster_timecode == false )
1256             {
1257                 msg_Warn( vars.p_demuxer, "ignoring SimpleBlock prior to mandatory Timecode" );
1258                 return;
1259             }
1260 
1261             vars.simpleblock = &ksblock;
1262             vars.simpleblock->ReadData( vars.obj->es.I_O() );
1263             vars.simpleblock->SetParent( *vars.obj->cluster );
1264 
1265             if( ksblock.IsKeyframe() )
1266             {
1267                 bool const b_valid_track = vars.obj->FindTrackByBlock( NULL, &ksblock ) != NULL;
1268                 if (b_valid_track)
1269                     vars.obj->_seeker.add_seekpoint( ksblock.TrackNum(),
1270                         SegmentSeeker::Seekpoint( ksblock.GetElementPosition(), ksblock.GlobalTimecode() / 1000 ) );
1271             }
1272         }
1273     };
1274 
1275     MKV_SWITCH_CREATE( EbmlTypeDispatcher, BlockGetHandler_l3, BlockPayload )
1276     {
1277         MKV_SWITCH_INIT();
1278 
1279         E_CASE( KaxBlock, kblock )
1280         {
1281             vars.block = &kblock;
1282             vars.block->ReadData( vars.obj->es.I_O() );
1283             vars.block->SetParent( *vars.obj->cluster );
1284 
1285             const mkv_track_t *p_track = vars.obj->FindTrackByBlock( &kblock, NULL );
1286             if( p_track != NULL && p_track->fmt.i_cat == SPU_ES )
1287             {
1288                 vars.obj->_seeker.add_seekpoint( kblock.TrackNum(),
1289                     SegmentSeeker::Seekpoint( kblock.GetElementPosition(), kblock.GlobalTimecode() / 1000 ) );
1290             }
1291 
1292             vars.ep->Keep ();
1293         }
1294         E_CASE( KaxBlockAdditions, kadditions )
1295         {
1296             EbmlElement *el;
1297             int i_upper_level = 0;
1298             try
1299             {
1300                 kadditions.Read( vars.obj->es, EBML_CONTEXT(&kadditions), i_upper_level, el, false );
1301                 vars.additions = &kadditions;
1302                 vars.ep->Keep ();
1303             } catch (...) {}
1304         }
1305         E_CASE( KaxBlockDuration, kduration )
1306         {
1307             kduration.ReadData( vars.obj->es.I_O() );
1308             vars.i_duration = static_cast<uint64>( kduration );
1309         }
1310         E_CASE( KaxReferenceBlock, kreference )
1311         {
1312            kreference.ReadData( vars.obj->es.I_O() );
1313 
1314            if( vars.b_key_picture )
1315                vars.b_key_picture = false;
1316            else if( static_cast<int64>( kreference ) )
1317                vars.b_discardable_picture = true;
1318         }
1319         E_CASE( KaxClusterSilentTrackNumber, kstrackn )
1320         {
1321             VLC_UNUSED( kstrackn );
1322             VLC_UNUSED( vars );
1323         }
1324 #if LIBMATROSKA_VERSION >= 0x010401
1325         E_CASE( KaxDiscardPadding, kdiscardp )
1326         {
1327             kdiscardp.ReadData( vars.obj->es.I_O() );
1328             int64 i_duration = static_cast<int64>( kdiscardp );
1329 
1330             if( vars.i_duration < i_duration )
1331                 vars.i_duration = 0;
1332             else
1333                 vars.i_duration -= i_duration;
1334         }
1335 #endif
1336         E_CASE_DEFAULT( element )
1337         {
1338             VLC_UNUSED(element);
1339 
1340             msg_Warn( vars.p_demuxer, "unknown element at { fpos: %" PRId64 ", '%s' }",
1341               element.GetElementPosition(), typeid( element ).name() );
1342         }
1343     };
1344 
1345     static EbmlTypeDispatcher const * const dispatchers[] = {
1346         &BlockGetHandler_l1::Dispatcher(),
1347         &BlockGetHandler_l2::Dispatcher(),
1348         &BlockGetHandler_l3::Dispatcher()
1349     };
1350 
1351     for( ;; )
1352     {
1353         EbmlElement *el = NULL;
1354         int         i_level;
1355 
1356         if( pp_simpleblock != NULL || ((el = ep.Get()) == NULL && pp_block != NULL) )
1357         {
1358             /* Check blocks validity to protect againts broken files */
1359             const mkv_track_t *p_track = FindTrackByBlock( pp_block , pp_simpleblock );
1360             if( p_track == NULL )
1361             {
1362                 ep.Unkeep();
1363                 pp_simpleblock = NULL;
1364                 pp_block = NULL;
1365                 continue;
1366             }
1367             if( pp_simpleblock != NULL )
1368             {
1369                 *pb_key_picture         = pp_simpleblock->IsKeyframe();
1370                 *pb_discardable_picture = pp_simpleblock->IsDiscardable();
1371             }
1372             /* We have block group let's check if the picture is a keyframe */
1373             else if( *pb_key_picture )
1374             {
1375                 if( p_track->fmt.i_codec == VLC_CODEC_THEORA )
1376                 {
1377                     DataBuffer *    p_data = &pp_block->GetBuffer(0);
1378                     const uint8_t * p_buff = p_data->Buffer();
1379                     /* if the second bit of a Theora frame is 1
1380                        it's not a keyframe */
1381                     if( p_data->Size() && p_buff )
1382                     {
1383                         if( p_buff[0] & 0x40 )
1384                             *pb_key_picture = false;
1385                     }
1386                     else
1387                         *pb_key_picture = false;
1388                 }
1389             }
1390 
1391             return VLC_SUCCESS;
1392         }
1393 
1394         i_level = ep.GetLevel();
1395 
1396         if( el == NULL )
1397         {
1398             if( i_level > 1 )
1399             {
1400                 ep.Up();
1401                 continue;
1402             }
1403             msg_Warn( &sys.demuxer, "EOF" );
1404             return VLC_EGENERIC;
1405         }
1406 
1407         /* Verify that we are still inside our cluster
1408          * It can happens whith broken files and when seeking
1409          * without index */
1410         if( i_level > 1 )
1411         {
1412             if( cluster && !ep.IsTopPresent( cluster ) )
1413             {
1414                 msg_Warn( &sys.demuxer, "Unexpected escape from current cluster" );
1415                 cluster = NULL;
1416             }
1417             if( !cluster )
1418                 continue;
1419         }
1420 
1421         /* do parsing */
1422 
1423         try {
1424             switch( i_level )
1425             {
1426                 case 2:
1427                 case 3:
1428                     if( unlikely( !el->ValidateSize() || ( el->IsFiniteSize() && el->GetSize() >= SIZE_MAX ) ) )
1429                     {
1430                         msg_Err( &sys.demuxer, "Error while reading %s... upping level", typeid(*el).name());
1431                         ep.Up();
1432 
1433                         if ( i_level == 2 )
1434                             break;
1435 
1436                         ep.Unkeep();
1437                         pp_simpleblock = NULL;
1438                         pp_block = NULL;
1439 
1440                         break;
1441                     }
1442                 case 1:
1443                     {
1444                         EbmlTypeDispatcher const * dispatcher = dispatchers[i_level - 1];
1445                         dispatcher->send( el, &payload );
1446                     }
1447                     break;
1448 
1449                 default:
1450                     msg_Err( &sys.demuxer, "invalid level = %d", i_level );
1451                     return VLC_EGENERIC;
1452             }
1453         }
1454         catch (int ret_code)
1455         {
1456             return ret_code;
1457         }
1458         catch (...)
1459         {
1460             msg_Err( &sys.demuxer, "Error while reading %s... upping level", typeid(*el).name());
1461             ep.Up();
1462             ep.Unkeep();
1463             pp_simpleblock = NULL;
1464             pp_block = NULL;
1465         }
1466     }
1467 }
1468