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