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