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