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