]> git.sesse.net Git - vlc/blob - modules/demux/mkv/matroska_segment_parse.cpp
MKV: Handle file with no duration or 0 duration
[vlc] / modules / demux / mkv / matroska_segment_parse.cpp
1 /*****************************************************************************
2  * matroska_segment_parse.cpp : matroska demuxer
3  *****************************************************************************
4  * Copyright (C) 2003-2010 the VideoLAN team
5  * $Id$
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
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 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 General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include "matroska_segment.hpp"
26
27 #include "chapters.hpp"
28
29 #include "demux.hpp"
30
31 #include "Ebml_parser.hpp"
32
33 /*****************************************************************************
34  * Some functions to manipulate memory
35  *****************************************************************************/
36 static inline char * ToUTF8( const UTFstring &u )
37 {
38     return strdup( u.GetUTF8().c_str() );
39 }
40
41 /*****************************************************************************
42  * ParseSeekHead:
43  *****************************************************************************/
44 void matroska_segment_c::ParseSeekHead( KaxSeekHead *seekhead )
45 {
46     EbmlParser  *ep;
47     EbmlElement *l;
48     bool b_seekable;
49
50     i_seekhead_count++;
51
52     stream_Control( sys.demuxer.s, STREAM_CAN_SEEK, &b_seekable );
53     if( !b_seekable )
54         return;
55
56     ep = new EbmlParser( &es, seekhead, &sys.demuxer );
57
58     while( ( l = ep->Get() ) != NULL )
59     {
60         if( MKV_IS_ID( l, KaxSeek ) )
61         {
62             EbmlId id = EBML_ID(EbmlVoid);
63             int64_t i_pos = -1;
64
65 #ifdef MKV_DEBUG
66             msg_Dbg( &sys.demuxer, "|   |   + Seek" );
67 #endif
68             ep->Down();
69             while( ( l = ep->Get() ) != NULL )
70             {
71                 if( MKV_IS_ID( l, KaxSeekID ) )
72                 {
73                     KaxSeekID &sid = *(KaxSeekID*)l;
74                     sid.ReadData( es.I_O() );
75                     id = EbmlId( sid.GetBuffer(), sid.GetSize() );
76                 }
77                 else if( MKV_IS_ID( l, KaxSeekPosition ) )
78                 {
79                     KaxSeekPosition &spos = *(KaxSeekPosition*)l;
80                     spos.ReadData( es.I_O() );
81                     i_pos = (int64_t)segment->GetGlobalPosition( uint64( spos ) );
82                 }
83                 else
84                 {
85                     /* Many mkvmerge files hit this case. It seems to be a broken SeekHead */
86                     msg_Dbg( &sys.demuxer, "|   |   + Unknown (%s)", typeid(*l).name()  );
87                 }
88             }
89             ep->Up();
90
91             if( i_pos >= 0 )
92             {
93                 if( id == EBML_ID(KaxCues) )
94                 {
95                     msg_Dbg( &sys.demuxer, "|   - cues at %"PRId64, i_pos );
96                     LoadSeekHeadItem( EBML_INFO(KaxCues), i_pos );
97                 }
98                 else if( id == EBML_ID(KaxInfo) )
99                 {
100                     msg_Dbg( &sys.demuxer, "|   - info at %"PRId64, i_pos );
101                     LoadSeekHeadItem( EBML_INFO(KaxInfo), i_pos );
102                 }
103                 else if( id == EBML_ID(KaxChapters) )
104                 {
105                     msg_Dbg( &sys.demuxer, "|   - chapters at %"PRId64, i_pos );
106                     LoadSeekHeadItem( EBML_INFO(KaxChapters), i_pos );
107                 }
108                 else if( id == EBML_ID(KaxTags) )
109                 {
110                     msg_Dbg( &sys.demuxer, "|   - tags at %"PRId64, i_pos );
111                     LoadSeekHeadItem( EBML_INFO(KaxTags), i_pos );
112                 }
113                 else if( id == EBML_ID(KaxSeekHead) )
114                 {
115                     msg_Dbg( &sys.demuxer, "|   - chained seekhead at %"PRId64, i_pos );
116                     LoadSeekHeadItem( EBML_INFO(KaxSeekHead), i_pos );
117                 }
118                 else if( id == EBML_ID(KaxTracks) )
119                 {
120                     msg_Dbg( &sys.demuxer, "|   - tracks at %"PRId64, i_pos );
121                     LoadSeekHeadItem( EBML_INFO(KaxTracks), i_pos );
122                 }
123                 else if( id == EBML_ID(KaxAttachments) )
124                 {
125                     msg_Dbg( &sys.demuxer, "|   - attachments at %"PRId64, i_pos );
126                     LoadSeekHeadItem( EBML_INFO(KaxAttachments), i_pos );
127                 }
128 #ifdef MKV_DEBUG
129                 else
130                     msg_Dbg( &sys.demuxer, "|   - unknown seekhead reference at %"PRId64, i_pos );
131 #endif
132             }
133         }
134         else
135             msg_Dbg( &sys.demuxer, "|   |   + ParseSeekHead Unknown (%s)", typeid(*l).name() );
136     }
137     delete ep;
138 }
139
140
141 /**
142  * Helper function to print the mkv parse tree
143  */
144 static void MkvTree( demux_t & demuxer, int i_level, const char *psz_format, ... )
145 {
146     va_list args;
147     if( i_level > 9 )
148     {
149         msg_Err( &demuxer, "MKV tree is too deep" );
150         return;
151     }
152     va_start( args, psz_format );
153     static const char psz_foo[] = "|   |   |   |   |   |   |   |   |   |";
154     char *psz_foo2 = (char*)malloc( i_level * 4 + 3 + strlen( psz_format ) );
155     strncpy( psz_foo2, psz_foo, 4 * i_level );
156     psz_foo2[ 4 * i_level ] = '+';
157     psz_foo2[ 4 * i_level + 1 ] = ' ';
158     strcpy( &psz_foo2[ 4 * i_level + 2 ], psz_format );
159     msg_GenericVa( &demuxer,VLC_MSG_DBG, "mkv", psz_foo2, args );
160     free( psz_foo2 );
161     va_end( args );
162 }
163
164
165 /*****************************************************************************
166  * ParseTrackEntry:
167  *****************************************************************************/
168 void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
169 {
170     bool bSupported = true;
171
172     /* Init the track */
173     mkv_track_t *tk = new mkv_track_t();
174     memset( tk, 0, sizeof( mkv_track_t ) );
175
176     es_format_Init( &tk->fmt, UNKNOWN_ES, 0 );
177     tk->fmt.psz_language       = strdup("English");
178     tk->fmt.psz_description    = NULL;
179
180     tk->b_default              = true;
181     tk->b_enabled              = true;
182     tk->b_forced               = false;
183     tk->b_silent               = false;
184     tk->i_number               = tracks.size() - 1;
185     tk->i_extra_data           = 0;
186     tk->p_extra_data           = NULL;
187     tk->psz_codec              = NULL;
188     tk->b_dts_only             = false;
189     tk->i_default_duration     = 0;
190     tk->f_timecodescale        = 1.0;
191
192     tk->b_inited               = false;
193     tk->i_data_init            = 0;
194     tk->p_data_init            = NULL;
195
196     tk->psz_codec_name         = NULL;
197     tk->psz_codec_settings     = NULL;
198     tk->psz_codec_info_url     = NULL;
199     tk->psz_codec_download_url = NULL;
200
201     tk->i_compression_type     = MATROSKA_COMPRESSION_NONE;
202     tk->p_compression_data     = NULL;
203
204     msg_Dbg( &sys.demuxer, "|   |   + Track Entry" );
205
206     for( size_t i = 0; i < m->ListSize(); i++ )
207     {
208         EbmlElement *l = (*m)[i];
209
210         if( MKV_IS_ID( l, KaxTrackNumber ) )
211         {
212             KaxTrackNumber &tnum = *(KaxTrackNumber*)l;
213
214             tk->i_number = uint32( tnum );
215             msg_Dbg( &sys.demuxer, "|   |   |   + Track Number=%u", uint32( tnum ) );
216         }
217         else  if( MKV_IS_ID( l, KaxTrackUID ) )
218         {
219             KaxTrackUID &tuid = *(KaxTrackUID*)l;
220
221             msg_Dbg( &sys.demuxer, "|   |   |   + Track UID=%u",  uint32( tuid ) );
222         }
223         else  if( MKV_IS_ID( l, KaxTrackType ) )
224         {
225             const char *psz_type;
226             KaxTrackType &ttype = *(KaxTrackType*)l;
227
228             switch( uint8(ttype) )
229             {
230                 case track_audio:
231                     psz_type = "audio";
232                     tk->fmt.i_cat = AUDIO_ES;
233                     break;
234                 case track_video:
235                     psz_type = "video";
236                     tk->fmt.i_cat = VIDEO_ES;
237                     break;
238                 case track_subtitle:
239                     psz_type = "subtitle";
240                     tk->fmt.i_cat = SPU_ES;
241                     break;
242                 case track_buttons:
243                     psz_type = "buttons";
244                     tk->fmt.i_cat = SPU_ES;
245                     break;
246                 default:
247                     psz_type = "unknown";
248                     tk->fmt.i_cat = UNKNOWN_ES;
249                     break;
250             }
251
252             msg_Dbg( &sys.demuxer, "|   |   |   + Track Type=%s", psz_type );
253         }
254         else  if( MKV_IS_ID( l, KaxTrackFlagEnabled ) ) // UNUSED
255         {
256             KaxTrackFlagEnabled &fenb = *(KaxTrackFlagEnabled*)l;
257
258             tk->b_enabled = uint32( fenb );
259             msg_Dbg( &sys.demuxer, "|   |   |   + Track Enabled=%u", uint32( fenb ) );
260         }
261         else  if( MKV_IS_ID( l, KaxTrackFlagDefault ) )
262         {
263             KaxTrackFlagDefault &fdef = *(KaxTrackFlagDefault*)l;
264
265             tk->b_default = uint32( fdef );
266             msg_Dbg( &sys.demuxer, "|   |   |   + Track Default=%u", uint32( fdef ) );
267         }
268         else  if( MKV_IS_ID( l, KaxTrackFlagForced ) ) // UNUSED
269         {
270             KaxTrackFlagForced &ffor = *(KaxTrackFlagForced*)l;
271             tk->b_forced = uint32( ffor );
272
273             msg_Dbg( &sys.demuxer, "|   |   |   + Track Forced=%u", uint32( ffor ) );
274         }
275         else  if( MKV_IS_ID( l, KaxTrackFlagLacing ) ) // UNUSED
276         {
277             KaxTrackFlagLacing &lac = *(KaxTrackFlagLacing*)l;
278
279             msg_Dbg( &sys.demuxer, "|   |   |   + Track Lacing=%d", uint32( lac ) );
280         }
281         else  if( MKV_IS_ID( l, KaxTrackMinCache ) ) // UNUSED
282         {
283             KaxTrackMinCache &cmin = *(KaxTrackMinCache*)l;
284
285             msg_Dbg( &sys.demuxer, "|   |   |   + Track MinCache=%d", uint32( cmin ) );
286         }
287         else  if( MKV_IS_ID( l, KaxTrackMaxCache ) ) // UNUSED
288         {
289             KaxTrackMaxCache &cmax = *(KaxTrackMaxCache*)l;
290
291             msg_Dbg( &sys.demuxer, "|   |   |   + Track MaxCache=%d", uint32( cmax ) );
292         }
293         else  if( MKV_IS_ID( l, KaxTrackDefaultDuration ) )
294         {
295             KaxTrackDefaultDuration &defd = *(KaxTrackDefaultDuration*)l;
296
297             tk->i_default_duration = uint64(defd);
298             msg_Dbg( &sys.demuxer, "|   |   |   + Track Default Duration=%"PRId64, uint64(defd) );
299         }
300         else  if( MKV_IS_ID( l, KaxTrackTimecodeScale ) )
301         {
302             KaxTrackTimecodeScale &ttcs = *(KaxTrackTimecodeScale*)l;
303
304             tk->f_timecodescale = float( ttcs );
305             msg_Dbg( &sys.demuxer, "|   |   |   + Track TimeCodeScale=%f", tk->f_timecodescale );
306         }
307         else  if( MKV_IS_ID( l, KaxMaxBlockAdditionID ) ) // UNUSED
308         {
309             KaxMaxBlockAdditionID &mbl = *(KaxMaxBlockAdditionID*)l;
310
311             msg_Dbg( &sys.demuxer, "|   |   |   + Track Max BlockAdditionID=%d", uint32( mbl ) );
312         }
313         else if( MKV_IS_ID( l, KaxTrackName ) )
314         {
315             KaxTrackName &tname = *(KaxTrackName*)l;
316
317             tk->fmt.psz_description = ToUTF8( UTFstring( tname ) );
318             msg_Dbg( &sys.demuxer, "|   |   |   + Track Name=%s", tk->fmt.psz_description );
319         }
320         else  if( MKV_IS_ID( l, KaxTrackLanguage ) )
321         {
322             KaxTrackLanguage &lang = *(KaxTrackLanguage*)l;
323
324             free( tk->fmt.psz_language );
325             tk->fmt.psz_language = strdup( string( lang ).c_str() );
326             msg_Dbg( &sys.demuxer,
327                      "|   |   |   + Track Language=`%s'", tk->fmt.psz_language );
328         }
329         else  if( MKV_IS_ID( l, KaxCodecID ) )
330         {
331             KaxCodecID &codecid = *(KaxCodecID*)l;
332
333             tk->psz_codec = strdup( string( codecid ).c_str() );
334             msg_Dbg( &sys.demuxer, "|   |   |   + Track CodecId=%s", string( codecid ).c_str() );
335         }
336         else  if( MKV_IS_ID( l, KaxCodecPrivate ) )
337         {
338             KaxCodecPrivate &cpriv = *(KaxCodecPrivate*)l;
339
340             tk->i_extra_data = cpriv.GetSize();
341             if( tk->i_extra_data > 0 )
342             {
343                 tk->p_extra_data = (uint8_t*)malloc( tk->i_extra_data );
344                 memcpy( tk->p_extra_data, cpriv.GetBuffer(), tk->i_extra_data );
345             }
346             msg_Dbg( &sys.demuxer, "|   |   |   + Track CodecPrivate size=%"PRId64, cpriv.GetSize() );
347         }
348         else if( MKV_IS_ID( l, KaxCodecName ) )
349         {
350             KaxCodecName &cname = *(KaxCodecName*)l;
351
352             tk->psz_codec_name = ToUTF8( UTFstring( cname ) );
353             msg_Dbg( &sys.demuxer, "|   |   |   + Track Codec Name=%s", tk->psz_codec_name );
354         }
355         //AttachmentLink
356         else if( MKV_IS_ID( l, KaxCodecDecodeAll ) ) // UNUSED
357         {
358             KaxCodecDecodeAll &cdall = *(KaxCodecDecodeAll*)l;
359
360             msg_Dbg( &sys.demuxer, "|   |   |   + Track Codec Decode All=%u", uint8( cdall ) );
361         }
362         else if( MKV_IS_ID( l, KaxTrackOverlay ) ) // UNUSED
363         {
364             KaxTrackOverlay &tovr = *(KaxTrackOverlay*)l;
365
366             msg_Dbg( &sys.demuxer, "|   |   |   + Track Overlay=%u", uint32( tovr ) );
367         }
368         else if( MKV_IS_ID( l, KaxContentEncodings ) )
369         {
370             EbmlMaster *cencs = static_cast<EbmlMaster*>(l);
371             MkvTree( sys.demuxer, 3, "Content Encodings" );
372             if ( cencs->ListSize() > 1 )
373             {
374                 msg_Err( &sys.demuxer, "Multiple Compression method not supported" );
375                 bSupported = false;
376             }
377             for( size_t j = 0; j < cencs->ListSize(); j++ )
378             {
379                 EbmlElement *l2 = (*cencs)[j];
380                 if( MKV_IS_ID( l2, KaxContentEncoding ) )
381                 {
382                     MkvTree( sys.demuxer, 4, "Content Encoding" );
383                     EbmlMaster *cenc = static_cast<EbmlMaster*>(l2);
384                     for( size_t k = 0; k < cenc->ListSize(); k++ )
385                     {
386                         EbmlElement *l3 = (*cenc)[k];
387                         if( MKV_IS_ID( l3, KaxContentEncodingOrder ) )
388                         {
389                             KaxContentEncodingOrder &encord = *(KaxContentEncodingOrder*)l3;
390                             MkvTree( sys.demuxer, 5, "Order: %i", uint32( encord ) );
391                         }
392                         else if( MKV_IS_ID( l3, KaxContentEncodingScope ) )
393                         {
394                             KaxContentEncodingScope &encscope = *(KaxContentEncodingScope*)l3;
395                             MkvTree( sys.demuxer, 5, "Scope: %i", uint32( encscope ) );
396                         }
397                         else if( MKV_IS_ID( l3, KaxContentEncodingType ) )
398                         {
399                             KaxContentEncodingType &enctype = *(KaxContentEncodingType*)l3;
400                             MkvTree( sys.demuxer, 5, "Type: %i", uint32( enctype ) );
401                         }
402                         else if( MKV_IS_ID( l3, KaxContentCompression ) )
403                         {
404                             EbmlMaster *compr = static_cast<EbmlMaster*>(l3);
405                             MkvTree( sys.demuxer, 5, "Content Compression" );
406                             //Default compression type is 0 (Zlib)
407                             tk->i_compression_type = MATROSKA_COMPRESSION_ZLIB;
408                             for( size_t n = 0; n < compr->ListSize(); n++ )
409                             {
410                                 EbmlElement *l4 = (*compr)[n];
411                                 if( MKV_IS_ID( l4, KaxContentCompAlgo ) )
412                                 {
413                                     KaxContentCompAlgo &compalg = *(KaxContentCompAlgo*)l4;
414                                     MkvTree( sys.demuxer, 6, "Compression Algorithm: %i", uint32(compalg) );
415                                     tk->i_compression_type = uint32( compalg );
416                                     if ( ( tk->i_compression_type != MATROSKA_COMPRESSION_ZLIB ) &&
417                                          ( tk->i_compression_type != MATROSKA_COMPRESSION_HEADER ) )
418                                     {
419                                         msg_Err( &sys.demuxer, "Track Compression method %d not supported", tk->i_compression_type );
420                                         bSupported = false;
421                                     }
422                                 }
423                                 else if( MKV_IS_ID( l4, KaxContentCompSettings ) )
424                                 {
425                                     tk->p_compression_data = new KaxContentCompSettings( *(KaxContentCompSettings*)l4 );
426                                 }
427                                 else
428                                 {
429                                     MkvTree( sys.demuxer, 6, "Unknown (%s)", typeid(*l4).name() );
430                                 }
431                             }
432                         }
433                         // ContentEncryption Unsupported
434                         else
435                         {
436                             MkvTree( sys.demuxer, 5, "Unknown (%s)", typeid(*l3).name() );
437                         }
438                     }
439                 }
440                 else
441                 {
442                     MkvTree( sys.demuxer, 4, "Unknown (%s)", typeid(*l2).name() );
443                 }
444             }
445         }
446 //        else if( MKV_IS_ID( l, KaxCodecSettings) ) DEPRECATED by matroska
447 //        {
448 //            KaxCodecSettings &cset = *(KaxCodecSettings*)l;
449
450 //            tk->psz_codec_settings = ToUTF8( UTFstring( cset ) );
451 //            msg_Dbg( &sys.demuxer, "|   |   |   + Track Codec Settings=%s", tk->psz_codec_settings );
452 //        }
453 //        else if( MKV_IS_ID( l, KaxCodecInfoURL) ) DEPRECATED by matroska
454 //        {
455 //            KaxCodecInfoURL &ciurl = *(KaxCodecInfoURL*)l;
456
457 //            tk->psz_codec_info_url = strdup( string( ciurl ).c_str() );
458 //            msg_Dbg( &sys.demuxer, "|   |   |   + Track Codec Info URL=%s", tk->psz_codec_info_url );
459 //        }
460 //        else if( MKV_IS_ID( l, KaxCodecDownloadURL) ) DEPRECATED by matroska
461 //        {
462 //            KaxCodecDownloadURL &cdurl = *(KaxCodecDownloadURL*)l;
463
464 //            tk->psz_codec_download_url = strdup( string( cdurl ).c_str() );
465 //            msg_Dbg( &sys.demuxer, "|   |   |   + Track Codec Info URL=%s", tk->psz_codec_download_url );
466 //        }
467         else  if( MKV_IS_ID( l, KaxTrackVideo ) )
468         {
469             EbmlMaster *tkv = static_cast<EbmlMaster*>(l);
470             unsigned int i_crop_right = 0, i_crop_left = 0, i_crop_top = 0, i_crop_bottom = 0;
471             unsigned int i_display_unit = 0, i_display_width = 0, i_display_height = 0;
472
473             msg_Dbg( &sys.demuxer, "|   |   |   + Track Video" );
474             tk->f_fps = 0.0;
475
476             tk->fmt.video.i_frame_rate_base = (unsigned int)(tk->i_default_duration / 1000);
477             tk->fmt.video.i_frame_rate = 1000000;
478
479             for( unsigned int j = 0; j < tkv->ListSize(); j++ )
480             {
481                 EbmlElement *l = (*tkv)[j];
482                 if( MKV_IS_ID( l, KaxVideoFlagInterlaced ) ) // UNUSED
483                 {
484                     KaxVideoFlagInterlaced &fint = *(KaxVideoFlagInterlaced*)l;
485
486                     msg_Dbg( &sys.demuxer, "|   |   |   |   + Track Video Interlaced=%u", uint8( fint ) );
487                 }
488                 else if( MKV_IS_ID( l, KaxVideoStereoMode ) ) // UNUSED
489                 {
490                     KaxVideoStereoMode &stereo = *(KaxVideoStereoMode*)l;
491
492                     msg_Dbg( &sys.demuxer, "|   |   |   |   + Track Video Stereo Mode=%u", uint8( stereo ) );
493                 }
494                 else if( MKV_IS_ID( l, KaxVideoPixelWidth ) )
495                 {
496                     KaxVideoPixelWidth &vwidth = *(KaxVideoPixelWidth*)l;
497
498                     tk->fmt.video.i_width += uint16( vwidth );
499                     msg_Dbg( &sys.demuxer, "|   |   |   |   + width=%d", uint16( vwidth ) );
500                 }
501                 else if( MKV_IS_ID( l, KaxVideoPixelHeight ) )
502                 {
503                     KaxVideoPixelWidth &vheight = *(KaxVideoPixelWidth*)l;
504
505                     tk->fmt.video.i_height += uint16( vheight );
506                     msg_Dbg( &sys.demuxer, "|   |   |   |   + height=%d", uint16( vheight ) );
507                 }
508                 else if( MKV_IS_ID( l, KaxVideoDisplayWidth ) )
509                 {
510                     KaxVideoDisplayWidth &vwidth = *(KaxVideoDisplayWidth*)l;
511
512                     i_display_width = uint16( vwidth );
513                     msg_Dbg( &sys.demuxer, "|   |   |   |   + display width=%d", uint16( vwidth ) );
514                 }
515                 else if( MKV_IS_ID( l, KaxVideoDisplayHeight ) )
516                 {
517                     KaxVideoDisplayWidth &vheight = *(KaxVideoDisplayWidth*)l;
518
519                     i_display_height = uint16( vheight );
520                     msg_Dbg( &sys.demuxer, "|   |   |   |   + display height=%d", uint16( vheight ) );
521                 }
522                 else if( MKV_IS_ID( l, KaxVideoPixelCropBottom ) )
523                 {
524                     KaxVideoPixelCropBottom &cropval = *(KaxVideoPixelCropBottom*)l;
525
526                     i_crop_bottom = uint16( cropval );
527                     msg_Dbg( &sys.demuxer, "|   |   |   |   + crop pixel bottom=%d", uint16( cropval ) );
528                 }
529                 else if( MKV_IS_ID( l, KaxVideoPixelCropTop ) )
530                 {
531                     KaxVideoPixelCropTop &cropval = *(KaxVideoPixelCropTop*)l;
532
533                     i_crop_top = uint16( cropval );
534                     msg_Dbg( &sys.demuxer, "|   |   |   |   + crop pixel top=%d", uint16( cropval ) );
535                 }
536                 else if( MKV_IS_ID( l, KaxVideoPixelCropRight ) )
537                 {
538                     KaxVideoPixelCropRight &cropval = *(KaxVideoPixelCropRight*)l;
539
540                     i_crop_right = uint16( cropval );
541                     msg_Dbg( &sys.demuxer, "|   |   |   |   + crop pixel right=%d", uint16( cropval ) );
542                 }
543                 else if( MKV_IS_ID( l, KaxVideoPixelCropLeft ) )
544                 {
545                     KaxVideoPixelCropLeft &cropval = *(KaxVideoPixelCropLeft*)l;
546
547                     i_crop_left = uint16( cropval );
548                     msg_Dbg( &sys.demuxer, "|   |   |   |   + crop pixel left=%d", uint16( cropval ) );
549                 }
550                 else if( MKV_IS_ID( l, KaxVideoDisplayUnit ) )
551                 {
552                     KaxVideoDisplayUnit &vdmode = *(KaxVideoDisplayUnit*)l;
553
554                     i_display_unit = uint8( vdmode );
555                     msg_Dbg( &sys.demuxer, "|   |   |   |   + Track Video Display Unit=%s",
556                              i_display_unit == 0 ? "pixels" : ( i_display_unit == 1 ? "centimeters": "inches" ) );
557                 }
558                 else if( MKV_IS_ID( l, KaxVideoAspectRatio ) ) // UNUSED
559                 {
560                     KaxVideoAspectRatio &ratio = *(KaxVideoAspectRatio*)l;
561
562                     msg_Dbg( &sys.demuxer, "   |   |   |   + Track Video Aspect Ratio Type=%u", uint8( ratio ) );
563                 }
564                 // ColourSpace UNUSED
565                 else if( MKV_IS_ID( l, KaxVideoFrameRate ) )
566                 {
567                     KaxVideoFrameRate &vfps = *(KaxVideoFrameRate*)l;
568
569                     tk->f_fps = float( vfps );
570                     msg_Dbg( &sys.demuxer, "   |   |   |   + fps=%f", float( vfps ) );
571                 }
572 //                else if( MKV_IS_ID( l, KaxVideoGamma) ) //DEPRECATED by Matroska
573 //                {
574 //                    KaxVideoGamma &gamma = *(KaxVideoGamma*)l;
575
576 //                    msg_Dbg( &sys.demuxer, "   |   |   |   + gamma=%f", float( gamma ) );
577 //                }
578                 else
579                 {
580                     msg_Dbg( &sys.demuxer, "|   |   |   |   + Unknown (%s)", typeid(*l).name() );
581                 }
582             }
583             if( i_display_height && i_display_width )
584             {
585                 tk->fmt.video.i_sar_num = i_display_width  * tk->fmt.video.i_height;
586                 tk->fmt.video.i_sar_den = i_display_height * tk->fmt.video.i_width;
587             }
588             if( i_crop_left || i_crop_right || i_crop_top || i_crop_bottom )
589             {
590                 tk->fmt.video.i_visible_width   = tk->fmt.video.i_width;
591                 tk->fmt.video.i_visible_height  = tk->fmt.video.i_height;
592                 tk->fmt.video.i_x_offset        = i_crop_left;
593                 tk->fmt.video.i_y_offset        = i_crop_top;
594                 tk->fmt.video.i_visible_width  -= i_crop_left + i_crop_right;
595                 tk->fmt.video.i_visible_height -= i_crop_top + i_crop_bottom;
596             }
597             /* FIXME: i_display_* allows you to not only set DAR, but also a zoom factor.
598                we do not support this atm */
599         }
600         else  if( MKV_IS_ID( l, KaxTrackAudio ) )
601         {
602             EbmlMaster *tka = static_cast<EbmlMaster*>(l);
603
604             msg_Dbg( &sys.demuxer, "|   |   |   + Track Audio" );
605
606             for( unsigned int j = 0; j < tka->ListSize(); j++ )
607             {
608                 EbmlElement *l = (*tka)[j];
609
610                 if( MKV_IS_ID( l, KaxAudioSamplingFreq ) )
611                 {
612                     KaxAudioSamplingFreq &afreq = *(KaxAudioSamplingFreq*)l;
613
614                     tk->i_original_rate = tk->fmt.audio.i_rate = (int)float( afreq );
615                     msg_Dbg( &sys.demuxer, "|   |   |   |   + afreq=%d", tk->fmt.audio.i_rate );
616                 }
617                 else if( MKV_IS_ID( l, KaxAudioOutputSamplingFreq ) )
618                 {
619                     KaxAudioOutputSamplingFreq &afreq = *(KaxAudioOutputSamplingFreq*)l;
620
621                     tk->fmt.audio.i_rate = (int)float( afreq );
622                     msg_Dbg( &sys.demuxer, "|   |   |   |   + aoutfreq=%d", tk->fmt.audio.i_rate );
623                 }
624                 else if( MKV_IS_ID( l, KaxAudioChannels ) )
625                 {
626                     KaxAudioChannels &achan = *(KaxAudioChannels*)l;
627
628                     tk->fmt.audio.i_channels = uint8( achan );
629                     msg_Dbg( &sys.demuxer, "|   |   |   |   + achan=%u", uint8( achan ) );
630                 }
631                 else if( MKV_IS_ID( l, KaxAudioBitDepth ) )
632                 {
633                     KaxAudioBitDepth &abits = *(KaxAudioBitDepth*)l;
634
635                     tk->fmt.audio.i_bitspersample = uint8( abits );
636                     msg_Dbg( &sys.demuxer, "|   |   |   |   + abits=%u", uint8( abits ) );
637                 }
638                 else
639                 {
640                     msg_Dbg( &sys.demuxer, "|   |   |   |   + Unknown (%s)", typeid(*l).name() );
641                 }
642             }
643         }
644         else
645         {
646             msg_Dbg( &sys.demuxer, "|   |   |   + Unknown (%s)",
647                      typeid(*l).name() );
648         }
649     }
650
651     if ( bSupported )
652     {
653         tracks.push_back( tk );
654     }
655     else
656     {
657         msg_Err( &sys.demuxer, "Track Entry %d not supported", tk->i_number );
658         delete tk;
659     }
660 }
661
662 /*****************************************************************************
663  * ParseTracks:
664  *****************************************************************************/
665 void matroska_segment_c::ParseTracks( KaxTracks *tracks )
666 {
667     EbmlElement *el;
668     int i_upper_level = 0;
669
670     /* Master elements */
671     tracks->Read( es, EBML_CONTEXT(tracks), i_upper_level, el, true );
672
673     for( size_t i = 0; i < tracks->ListSize(); i++ )
674     {
675         EbmlElement *l = (*tracks)[i];
676
677         if( MKV_IS_ID( l, KaxTrackEntry ) )
678         {
679             ParseTrackEntry( static_cast<KaxTrackEntry *>(l) );
680         }
681         else
682         {
683             msg_Dbg( &sys.demuxer, "|   |   + Unknown (%s)", typeid(*l).name() );
684         }
685     }
686 }
687
688 /*****************************************************************************
689  * ParseInfo:
690  *****************************************************************************/
691 void matroska_segment_c::ParseInfo( KaxInfo *info )
692 {
693     EbmlElement *el;
694     EbmlMaster  *m;
695     int i_upper_level = 0;
696
697     /* Master elements */
698     m = static_cast<EbmlMaster *>(info);
699     m->Read( es, EBML_CONTEXT(info), i_upper_level, el, true );
700
701     for( size_t i = 0; i < m->ListSize(); i++ )
702     {
703         EbmlElement *l = (*m)[i];
704
705         if( MKV_IS_ID( l, KaxSegmentUID ) )
706         {
707             if ( p_segment_uid == NULL )
708                 p_segment_uid = new KaxSegmentUID(*static_cast<KaxSegmentUID*>(l));
709
710             msg_Dbg( &sys.demuxer, "|   |   + UID=%d", *(uint32*)p_segment_uid->GetBuffer() );
711         }
712         else if( MKV_IS_ID( l, KaxPrevUID ) )
713         {
714             if ( p_prev_segment_uid == NULL )
715             {
716                 p_prev_segment_uid = new KaxPrevUID(*static_cast<KaxPrevUID*>(l));
717                 b_ref_external_segments = true;
718             }
719
720             msg_Dbg( &sys.demuxer, "|   |   + PrevUID=%d", *(uint32*)p_prev_segment_uid->GetBuffer() );
721         }
722         else if( MKV_IS_ID( l, KaxNextUID ) )
723         {
724             if ( p_next_segment_uid == NULL )
725             {
726                 p_next_segment_uid = new KaxNextUID(*static_cast<KaxNextUID*>(l));
727                 b_ref_external_segments = true;
728             }
729
730             msg_Dbg( &sys.demuxer, "|   |   + NextUID=%d", *(uint32*)p_next_segment_uid->GetBuffer() );
731         }
732         else if( MKV_IS_ID( l, KaxTimecodeScale ) )
733         {
734             KaxTimecodeScale &tcs = *(KaxTimecodeScale*)l;
735
736             i_timescale = uint64(tcs);
737
738             msg_Dbg( &sys.demuxer, "|   |   + TimecodeScale=%"PRId64,
739                      i_timescale );
740         }
741         else if( MKV_IS_ID( l, KaxDuration ) )
742         {
743             KaxDuration &dur = *(KaxDuration*)l;
744
745             i_duration = mtime_t( double( dur ) );
746
747             msg_Dbg( &sys.demuxer, "|   |   + Duration=%"PRId64,
748                      i_duration );
749         }
750         else if( MKV_IS_ID( l, KaxMuxingApp ) )
751         {
752             KaxMuxingApp &mapp = *(KaxMuxingApp*)l;
753
754             psz_muxing_application = ToUTF8( UTFstring( mapp ) );
755
756             msg_Dbg( &sys.demuxer, "|   |   + Muxing Application=%s",
757                      psz_muxing_application );
758         }
759         else if( MKV_IS_ID( l, KaxWritingApp ) )
760         {
761             KaxWritingApp &wapp = *(KaxWritingApp*)l;
762
763             psz_writing_application = ToUTF8( UTFstring( wapp ) );
764
765             msg_Dbg( &sys.demuxer, "|   |   + Writing Application=%s",
766                      psz_writing_application );
767         }
768         else if( MKV_IS_ID( l, KaxSegmentFilename ) )
769         {
770             KaxSegmentFilename &sfn = *(KaxSegmentFilename*)l;
771
772             psz_segment_filename = ToUTF8( UTFstring( sfn ) );
773
774             msg_Dbg( &sys.demuxer, "|   |   + Segment Filename=%s",
775                      psz_segment_filename );
776         }
777         else if( MKV_IS_ID( l, KaxTitle ) )
778         {
779             KaxTitle &title = *(KaxTitle*)l;
780
781             psz_title = ToUTF8( UTFstring( title ) );
782
783             msg_Dbg( &sys.demuxer, "|   |   + Title=%s", psz_title );
784         }
785         else if( MKV_IS_ID( l, KaxSegmentFamily ) )
786         {
787             KaxSegmentFamily *uid = static_cast<KaxSegmentFamily*>(l);
788
789             families.push_back( new KaxSegmentFamily(*uid) );
790
791             msg_Dbg( &sys.demuxer, "|   |   + family=%d", *(uint32*)uid->GetBuffer() );
792         }
793         else if( MKV_IS_ID( l, KaxDateUTC ) )
794         {
795             KaxDateUTC &date = *(KaxDateUTC*)l;
796             time_t i_date;
797             struct tm tmres;
798             char   buffer[25];
799
800             i_date = date.GetEpochDate();
801             if( gmtime_r( &i_date, &tmres ) &&
802                 strftime( buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Y",
803                           &tmres ) )
804             {
805                 psz_date_utc = strdup( buffer );
806                 msg_Dbg( &sys.demuxer, "|   |   + Date=%s", buffer );
807             }
808         }
809         else if( MKV_IS_ID( l, KaxChapterTranslate ) )
810         {
811             KaxChapterTranslate *p_trans = static_cast<KaxChapterTranslate*>( l );
812             chapter_translation_c *p_translate = new chapter_translation_c();
813
814             p_trans->Read( es, EBML_CONTEXT(p_trans), i_upper_level, el, true );
815             for( size_t j = 0; j < p_trans->ListSize(); j++ )
816             {
817                 EbmlElement *l = (*p_trans)[j];
818
819                 if( MKV_IS_ID( l, KaxChapterTranslateEditionUID ) )
820                 {
821                     p_translate->editions.push_back( uint64( *static_cast<KaxChapterTranslateEditionUID*>( l ) ) );
822                 }
823                 else if( MKV_IS_ID( l, KaxChapterTranslateCodec ) )
824                 {
825                     p_translate->codec_id = uint32( *static_cast<KaxChapterTranslateCodec*>( l ) );
826                 }
827                 else if( MKV_IS_ID( l, KaxChapterTranslateID ) )
828                 {
829                     p_translate->p_translated = new KaxChapterTranslateID( *static_cast<KaxChapterTranslateID*>( l ) );
830                 }
831             }
832
833             translations.push_back( p_translate );
834         }
835         else
836         {
837             msg_Dbg( &sys.demuxer, "|   |   + Unknown (%s)", typeid(*l).name() );
838         }
839     }
840
841     double f_dur = double(i_duration) * double(i_timescale) / 1000000.0;
842     i_duration = mtime_t(f_dur);
843     if( !i_duration ) i_duration = -1;
844 }
845
846
847 /*****************************************************************************
848  * ParseChapterAtom
849  *****************************************************************************/
850 void matroska_segment_c::ParseChapterAtom( int i_level, KaxChapterAtom *ca, chapter_item_c & chapters )
851 {
852     msg_Dbg( &sys.demuxer, "|   |   |   + ChapterAtom (level=%d)", i_level );
853     for( size_t i = 0; i < ca->ListSize(); i++ )
854     {
855         EbmlElement *l = (*ca)[i];
856
857         if( MKV_IS_ID( l, KaxChapterUID ) )
858         {
859             chapters.i_uid = uint64_t(*(KaxChapterUID*)l);
860             msg_Dbg( &sys.demuxer, "|   |   |   |   + ChapterUID: %"PRIu64"", chapters.i_uid );
861         }
862         else if( MKV_IS_ID( l, KaxChapterFlagHidden ) )
863         {
864             KaxChapterFlagHidden &flag =*(KaxChapterFlagHidden*)l;
865             chapters.b_display_seekpoint = uint8( flag ) == 0;
866
867             msg_Dbg( &sys.demuxer, "|   |   |   |   + ChapterFlagHidden: %s", chapters.b_display_seekpoint ? "no":"yes" );
868         }
869         else if( MKV_IS_ID( l, KaxChapterSegmentUID ) )
870         {
871             chapters.p_segment_uid = new KaxChapterSegmentUID( *static_cast<KaxChapterSegmentUID*>(l) );
872             b_ref_external_segments = true;
873             msg_Dbg( &sys.demuxer, "|   |   |   |   + ChapterSegmentUID= %u", *(uint32*)chapters.p_segment_uid->GetBuffer() );
874         }
875         else if( MKV_IS_ID( l, KaxChapterSegmentEditionUID ) )
876         {
877             chapters.p_segment_edition_uid = new KaxChapterSegmentEditionUID( *static_cast<KaxChapterSegmentEditionUID*>(l) );
878             msg_Dbg( &sys.demuxer, "|   |   |   |   + ChapterSegmentEditionUID= %u",
879 #if LIBMATROSKA_VERSION < 0x010300
880             *(uint32*)chapters.p_segment_edition_uid->GetBuffer()
881 #else
882             *(uint32*)chapters.p_segment_edition_uid
883 #endif
884             );
885         }
886         else if( MKV_IS_ID( l, KaxChapterTimeStart ) )
887         {
888             KaxChapterTimeStart &start =*(KaxChapterTimeStart*)l;
889             chapters.i_start_time = uint64( start ) / INT64_C(1000);
890
891             msg_Dbg( &sys.demuxer, "|   |   |   |   + ChapterTimeStart: %"PRId64"", chapters.i_start_time );
892         }
893         else if( MKV_IS_ID( l, KaxChapterTimeEnd ) )
894         {
895             KaxChapterTimeEnd &end =*(KaxChapterTimeEnd*)l;
896             chapters.i_end_time = uint64( end ) / INT64_C(1000);
897
898             msg_Dbg( &sys.demuxer, "|   |   |   |   + ChapterTimeEnd: %"PRId64"", chapters.i_end_time );
899         }
900         else if( MKV_IS_ID( l, KaxChapterDisplay ) )
901         {
902             EbmlMaster *cd = static_cast<EbmlMaster *>(l);
903
904             msg_Dbg( &sys.demuxer, "|   |   |   |   + ChapterDisplay" );
905             for( size_t j = 0; j < cd->ListSize(); j++ )
906             {
907                 EbmlElement *l= (*cd)[j];
908
909                 if( MKV_IS_ID( l, KaxChapterString ) )
910                 {
911                     KaxChapterString &name =*(KaxChapterString*)l;
912                     for ( int k = 0; k < i_level; k++)
913                         chapters.psz_name += '+';
914                     chapters.psz_name += ' ';
915                     char *psz_tmp_utf8 = ToUTF8( UTFstring( name ) );
916                     chapters.psz_name += psz_tmp_utf8;
917                     chapters.b_user_display = true;
918
919                     msg_Dbg( &sys.demuxer, "|   |   |   |   |    + ChapterString '%s'", psz_tmp_utf8 );
920                     free( psz_tmp_utf8 );
921                 }
922                 else if( MKV_IS_ID( l, KaxChapterLanguage ) )
923                 {
924                     KaxChapterLanguage &lang =*(KaxChapterLanguage*)l;
925                     const char *psz = string( lang ).c_str();
926
927                     msg_Dbg( &sys.demuxer, "|   |   |   |   |    + ChapterLanguage '%s'", psz );
928                 }
929                 else if( MKV_IS_ID( l, KaxChapterCountry ) )
930                 {
931                     KaxChapterCountry &ct =*(KaxChapterCountry*)l;
932                     const char *psz = string( ct ).c_str();
933
934                     msg_Dbg( &sys.demuxer, "|   |   |   |   |    + ChapterCountry '%s'", psz );
935                 }
936             }
937         }
938         else if( MKV_IS_ID( l, KaxChapterProcess ) )
939         {
940             msg_Dbg( &sys.demuxer, "|   |   |   |   + ChapterProcess" );
941
942             KaxChapterProcess *cp = static_cast<KaxChapterProcess *>(l);
943             chapter_codec_cmds_c *p_ccodec = NULL;
944
945             for( size_t j = 0; j < cp->ListSize(); j++ )
946             {
947                 EbmlElement *k= (*cp)[j];
948
949                 if( MKV_IS_ID( k, KaxChapterProcessCodecID ) )
950                 {
951                     KaxChapterProcessCodecID *p_codec_id = static_cast<KaxChapterProcessCodecID*>( k );
952                     if ( uint32(*p_codec_id) == 0 )
953                         p_ccodec = new matroska_script_codec_c( sys );
954                     else if ( uint32(*p_codec_id) == 1 )
955                         p_ccodec = new dvd_chapter_codec_c( sys );
956                     break;
957                 }
958             }
959
960             if ( p_ccodec != NULL )
961             {
962                 for( size_t j = 0; j < cp->ListSize(); j++ )
963                 {
964                     EbmlElement *k= (*cp)[j];
965
966                     if( MKV_IS_ID( k, KaxChapterProcessPrivate ) )
967                     {
968                         KaxChapterProcessPrivate * p_private = static_cast<KaxChapterProcessPrivate*>( k );
969                         p_ccodec->SetPrivate( *p_private );
970                     }
971                     else if( MKV_IS_ID( k, KaxChapterProcessCommand ) )
972                     {
973                         p_ccodec->AddCommand( *static_cast<KaxChapterProcessCommand*>( k ) );
974                     }
975                 }
976                 chapters.codecs.push_back( p_ccodec );
977             }
978         }
979         else if( MKV_IS_ID( l, KaxChapterAtom ) )
980         {
981             chapter_item_c *new_sub_chapter = new chapter_item_c();
982             ParseChapterAtom( i_level+1, static_cast<KaxChapterAtom *>(l), *new_sub_chapter );
983             new_sub_chapter->p_parent = &chapters;
984             chapters.sub_chapters.push_back( new_sub_chapter );
985         }
986     }
987 }
988
989 /*****************************************************************************
990  * ParseAttachments:
991  *****************************************************************************/
992 void matroska_segment_c::ParseAttachments( KaxAttachments *attachments )
993 {
994     EbmlElement *el;
995     int i_upper_level = 0;
996
997     attachments->Read( es, EBML_CONTEXT(attachments), i_upper_level, el, true );
998
999     KaxAttached *attachedFile = FindChild<KaxAttached>( *attachments );
1000
1001     while( attachedFile && ( attachedFile->GetSize() > 0 ) )
1002     {
1003         KaxFileData  &img_data     = GetChild<KaxFileData>( *attachedFile );
1004         attachment_c *new_attachment = new attachment_c( ToUTF8( UTFstring( GetChild<KaxFileName>( *attachedFile ) ) ),
1005                                                         GetChild<KaxMimeType>( *attachedFile ),
1006                                                         img_data.GetSize() );
1007
1008         msg_Dbg( &sys.demuxer, "|   |   - %s (%s)", new_attachment->fileName(), new_attachment->mimeType() );
1009
1010         if( new_attachment->init() )
1011         {
1012              memcpy( new_attachment->p_data, img_data.GetBuffer(), img_data.GetSize() );
1013              sys.stored_attachments.push_back( new_attachment );
1014              if( !strncmp( new_attachment->mimeType(), "image/", 6 ) )
1015              {
1016                  char *psz_url;
1017                  if( asprintf( &psz_url, "attachment://%s",
1018                              new_attachment->fileName() ) == -1 )
1019                      continue;
1020                  if( !sys.meta )
1021                      sys.meta = vlc_meta_New();
1022                  vlc_meta_SetArtURL( sys.meta, psz_url );
1023                  free( psz_url );
1024              }
1025         }
1026         else
1027         {
1028             delete new_attachment;
1029         }
1030
1031         attachedFile = &GetNextChild<KaxAttached>( *attachments, *attachedFile );
1032     }
1033 }
1034
1035 /*****************************************************************************
1036  * ParseChapters:
1037  *****************************************************************************/
1038 void matroska_segment_c::ParseChapters( KaxChapters *chapters )
1039 {
1040     EbmlElement *el;
1041     int i_upper_level = 0;
1042
1043     /* Master elements */
1044     chapters->Read( es, EBML_CONTEXT(chapters), i_upper_level, el, true );
1045
1046     for( size_t i = 0; i < chapters->ListSize(); i++ )
1047     {
1048         EbmlElement *l = (*chapters)[i];
1049
1050         if( MKV_IS_ID( l, KaxEditionEntry ) )
1051         {
1052             chapter_edition_c *p_edition = new chapter_edition_c();
1053
1054             EbmlMaster *E = static_cast<EbmlMaster *>(l );
1055             msg_Dbg( &sys.demuxer, "|   |   + EditionEntry" );
1056             for( size_t j = 0; j < E->ListSize(); j++ )
1057             {
1058                 EbmlElement *l = (*E)[j];
1059
1060                 if( MKV_IS_ID( l, KaxChapterAtom ) )
1061                 {
1062                     chapter_item_c *new_sub_chapter = new chapter_item_c();
1063                     ParseChapterAtom( 0, static_cast<KaxChapterAtom *>(l), *new_sub_chapter );
1064                     p_edition->sub_chapters.push_back( new_sub_chapter );
1065                 }
1066                 else if( MKV_IS_ID( l, KaxEditionUID ) )
1067                 {
1068                     p_edition->i_uid = uint64(*static_cast<KaxEditionUID *>( l ));
1069                 }
1070                 else if( MKV_IS_ID( l, KaxEditionFlagOrdered ) )
1071                 {
1072                     p_edition->b_ordered = var_InheritBool( &sys.demuxer, "mkv-use-ordered-chapters" ) ? (uint8(*static_cast<KaxEditionFlagOrdered *>( l )) != 0) : 0;
1073                 }
1074                 else if( MKV_IS_ID( l, KaxEditionFlagDefault ) )
1075                 {
1076                     if (uint8(*static_cast<KaxEditionFlagDefault *>( l )) != 0)
1077                         i_default_edition = stored_editions.size();
1078                 }
1079                 else if( MKV_IS_ID( l, KaxEditionFlagHidden ) )
1080                 {
1081                     // FIXME to implement
1082                 }
1083                 else
1084                 {
1085                     msg_Dbg( &sys.demuxer, "|   |   |   + Unknown (%s)", typeid(*l).name() );
1086                 }
1087             }
1088             stored_editions.push_back( p_edition );
1089         }
1090         else
1091         {
1092             msg_Dbg( &sys.demuxer, "|   |   + Unknown (%s)", typeid(*l).name() );
1093         }
1094     }
1095 }
1096
1097 void matroska_segment_c::ParseCluster( )
1098 {
1099     EbmlElement *el;
1100     EbmlMaster  *m;
1101     int i_upper_level = 0;
1102
1103     /* Master elements */
1104     m = static_cast<EbmlMaster *>( cluster );
1105     m->Read( es, EBML_CONTEXT(cluster), i_upper_level, el, true );
1106
1107     for( unsigned int i = 0; i < m->ListSize(); i++ )
1108     {
1109         EbmlElement *l = (*m)[i];
1110
1111         if( MKV_IS_ID( l, KaxClusterTimecode ) )
1112         {
1113             KaxClusterTimecode &ctc = *(KaxClusterTimecode*)l;
1114
1115             cluster->InitTimecode( uint64( ctc ), i_timescale );
1116             break;
1117         }
1118     }
1119
1120     i_start_time = cluster->GlobalTimecode() / 1000;
1121 }
1122