1 /*****************************************************************************
2 * mkv.cpp : matroska demuxer
3 *****************************************************************************
4 * Copyright (C) 2003-2004 the VideoLAN team
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Steve Lhomme <steve.lhomme@free.fr>
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.
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.
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 *****************************************************************************/
25 #include "matroska_segment.hpp"
27 #include "chapters.hpp"
31 /*****************************************************************************
32 * Some functions to manipulate memory
33 *****************************************************************************/
34 static inline char * ToUTF8( const UTFstring
&u
)
36 return strdup( u
.GetUTF8().c_str() );
39 /*****************************************************************************
41 *****************************************************************************/
42 void matroska_segment_c::ParseSeekHead( KaxSeekHead
*seekhead
)
50 stream_Control( sys
.demuxer
.s
, STREAM_CAN_SEEK
, &b_seekable
);
54 ep
= new EbmlParser( &es
, seekhead
, &sys
.demuxer
);
56 while( ( l
= ep
->Get() ) != NULL
)
58 if( MKV_IS_ID( l
, KaxSeek
) )
60 EbmlId id
= EbmlVoid::ClassInfos
.GlobalId
;
63 msg_Dbg( &sys
.demuxer
, "| | + Seek" );
65 while( ( l
= ep
->Get() ) != NULL
)
67 if( MKV_IS_ID( l
, KaxSeekID
) )
69 KaxSeekID
&sid
= *(KaxSeekID
*)l
;
70 sid
.ReadData( es
.I_O() );
71 id
= EbmlId( sid
.GetBuffer(), sid
.GetSize() );
73 else if( MKV_IS_ID( l
, KaxSeekPosition
) )
75 KaxSeekPosition
&spos
= *(KaxSeekPosition
*)l
;
76 spos
.ReadData( es
.I_O() );
77 i_pos
= (int64_t)segment
->GetGlobalPosition( uint64( spos
) );
81 /* Many mkvmerge files hit this case. It seems to be a broken SeekHead */
82 msg_Dbg( &sys
.demuxer
, "| | + Unknown (%s)", typeid(*l
).name() );
89 if( id
== KaxCues::ClassInfos
.GlobalId
)
91 msg_Dbg( &sys
.demuxer
, "| - cues at %"PRId64
, i_pos
);
92 LoadSeekHeadItem( KaxCues::ClassInfos
, i_pos
);
94 else if( id
== KaxInfo::ClassInfos
.GlobalId
)
96 msg_Dbg( &sys
.demuxer
, "| - info at %"PRId64
, i_pos
);
97 LoadSeekHeadItem( KaxInfo::ClassInfos
, i_pos
);
99 else if( id
== KaxChapters::ClassInfos
.GlobalId
)
101 msg_Dbg( &sys
.demuxer
, "| - chapters at %"PRId64
, i_pos
);
102 LoadSeekHeadItem( KaxChapters::ClassInfos
, i_pos
);
104 else if( id
== KaxTags::ClassInfos
.GlobalId
)
106 msg_Dbg( &sys
.demuxer
, "| - tags at %"PRId64
, i_pos
);
107 LoadSeekHeadItem( KaxTags::ClassInfos
, i_pos
);
109 else if( id
== KaxSeekHead::ClassInfos
.GlobalId
)
111 msg_Dbg( &sys
.demuxer
, "| - chained seekhead at %"PRId64
, i_pos
);
112 LoadSeekHeadItem( KaxSeekHead::ClassInfos
, i_pos
);
114 else if( id
== KaxTracks::ClassInfos
.GlobalId
)
116 msg_Dbg( &sys
.demuxer
, "| - tracks at %"PRId64
, i_pos
);
117 LoadSeekHeadItem( KaxTracks::ClassInfos
, i_pos
);
119 else if( id
== KaxAttachments::ClassInfos
.GlobalId
)
121 msg_Dbg( &sys
.demuxer
, "| - attachments at %"PRId64
, i_pos
);
122 LoadSeekHeadItem( KaxAttachments::ClassInfos
, i_pos
);
125 msg_Dbg( &sys
.demuxer
, "| - unknown seekhead reference at %"PRId64
, i_pos
);
129 msg_Dbg( &sys
.demuxer
, "| | + ParseSeekHead Unknown (%s)", typeid(*l
).name() );
136 * Helper function to print the mkv parse tree
138 static void MkvTree( demux_t
& demuxer
, int i_level
, const char *psz_format
, ... )
143 msg_Err( &demuxer
, "too deep tree" );
146 va_start( args
, psz_format
);
147 static const char psz_foo
[] = "| | | | | | | | | |";
148 char *psz_foo2
= (char*)malloc( i_level
* 4 + 3 + strlen( psz_format
) );
149 strncpy( psz_foo2
, psz_foo
, 4 * i_level
);
150 psz_foo2
[ 4 * i_level
] = '+';
151 psz_foo2
[ 4 * i_level
+ 1 ] = ' ';
152 strcpy( &psz_foo2
[ 4 * i_level
+ 2 ], psz_format
);
153 __msg_GenericVa( VLC_OBJECT(&demuxer
),VLC_MSG_DBG
, "mkv", psz_foo2
, args
);
159 /*****************************************************************************
161 *****************************************************************************/
162 void matroska_segment_c::ParseTrackEntry( KaxTrackEntry
*m
)
165 bool bSupported
= true;
169 msg_Dbg( &sys
.demuxer
, "| | + Track Entry" );
171 tk
= new mkv_track_t();
174 memset( tk
, 0, sizeof( mkv_track_t
) );
176 es_format_Init( &tk
->fmt
, UNKNOWN_ES
, 0 );
177 tk
->fmt
.psz_language
= strdup("English");
178 tk
->fmt
.psz_description
= NULL
;
180 tk
->b_default
= true;
181 tk
->b_enabled
= true;
182 tk
->b_silent
= false;
183 tk
->i_number
= tracks
.size() - 1;
184 tk
->i_extra_data
= 0;
185 tk
->p_extra_data
= NULL
;
186 tk
->psz_codec
= NULL
;
187 tk
->i_default_duration
= 0;
188 tk
->f_timecodescale
= 1.0;
190 tk
->b_inited
= false;
192 tk
->p_data_init
= NULL
;
194 tk
->psz_codec_name
= NULL
;
195 tk
->psz_codec_settings
= NULL
;
196 tk
->psz_codec_info_url
= NULL
;
197 tk
->psz_codec_download_url
= NULL
;
199 tk
->i_compression_type
= MATROSKA_COMPRESSION_NONE
;
200 tk
->p_compression_data
= NULL
;
202 for( i
= 0; i
< m
->ListSize(); i
++ )
204 EbmlElement
*l
= (*m
)[i
];
206 if( MKV_IS_ID( l
, KaxTrackNumber
) )
208 KaxTrackNumber
&tnum
= *(KaxTrackNumber
*)l
;
210 tk
->i_number
= uint32( tnum
);
211 msg_Dbg( &sys
.demuxer
, "| | | + Track Number=%u", uint32( tnum
) );
213 else if( MKV_IS_ID( l
, KaxTrackUID
) )
215 KaxTrackUID
&tuid
= *(KaxTrackUID
*)l
;
217 msg_Dbg( &sys
.demuxer
, "| | | + Track UID=%u", uint32( tuid
) );
219 else if( MKV_IS_ID( l
, KaxTrackType
) )
221 const char *psz_type
;
222 KaxTrackType
&ttype
= *(KaxTrackType
*)l
;
224 switch( uint8(ttype
) )
228 tk
->fmt
.i_cat
= AUDIO_ES
;
232 tk
->fmt
.i_cat
= VIDEO_ES
;
235 psz_type
= "subtitle";
236 tk
->fmt
.i_cat
= SPU_ES
;
239 psz_type
= "buttons";
240 tk
->fmt
.i_cat
= SPU_ES
;
243 psz_type
= "unknown";
244 tk
->fmt
.i_cat
= UNKNOWN_ES
;
248 msg_Dbg( &sys
.demuxer
, "| | | + Track Type=%s", psz_type
);
250 // else if( EbmlId( *l ) == KaxTrackFlagEnabled::ClassInfos.GlobalId )
252 // KaxTrackFlagEnabled &fenb = *(KaxTrackFlagEnabled*)l;
254 // tk->b_enabled = uint32( fenb );
255 // msg_Dbg( &sys.demuxer, "| | | + Track Enabled=%u",
258 else if( MKV_IS_ID( l
, KaxTrackFlagDefault
) )
260 KaxTrackFlagDefault
&fdef
= *(KaxTrackFlagDefault
*)l
;
262 tk
->b_default
= uint32( fdef
);
263 msg_Dbg( &sys
.demuxer
, "| | | + Track Default=%u", uint32( fdef
) );
265 else if( MKV_IS_ID( l
, KaxTrackFlagLacing
) )
267 KaxTrackFlagLacing
&lac
= *(KaxTrackFlagLacing
*)l
;
269 msg_Dbg( &sys
.demuxer
, "| | | + Track Lacing=%d", uint32( lac
) );
271 else if( MKV_IS_ID( l
, KaxTrackMinCache
) )
273 KaxTrackMinCache
&cmin
= *(KaxTrackMinCache
*)l
;
275 msg_Dbg( &sys
.demuxer
, "| | | + Track MinCache=%d", uint32( cmin
) );
277 else if( MKV_IS_ID( l
, KaxTrackMaxCache
) )
279 KaxTrackMaxCache
&cmax
= *(KaxTrackMaxCache
*)l
;
281 msg_Dbg( &sys
.demuxer
, "| | | + Track MaxCache=%d", uint32( cmax
) );
283 else if( MKV_IS_ID( l
, KaxTrackDefaultDuration
) )
285 KaxTrackDefaultDuration
&defd
= *(KaxTrackDefaultDuration
*)l
;
287 tk
->i_default_duration
= uint64(defd
);
288 msg_Dbg( &sys
.demuxer
, "| | | + Track Default Duration=%"PRId64
, uint64(defd
) );
290 else if( MKV_IS_ID( l
, KaxTrackTimecodeScale
) )
292 KaxTrackTimecodeScale
&ttcs
= *(KaxTrackTimecodeScale
*)l
;
294 tk
->f_timecodescale
= float( ttcs
);
295 msg_Dbg( &sys
.demuxer
, "| | | + Track TimeCodeScale=%f", tk
->f_timecodescale
);
297 else if( MKV_IS_ID( l
, KaxTrackName
) )
299 KaxTrackName
&tname
= *(KaxTrackName
*)l
;
301 tk
->fmt
.psz_description
= ToUTF8( UTFstring( tname
) );
302 msg_Dbg( &sys
.demuxer
, "| | | + Track Name=%s", tk
->fmt
.psz_description
);
304 else if( MKV_IS_ID( l
, KaxTrackLanguage
) )
306 KaxTrackLanguage
&lang
= *(KaxTrackLanguage
*)l
;
308 if ( tk
->fmt
.psz_language
!= NULL
)
309 free( tk
->fmt
.psz_language
);
310 tk
->fmt
.psz_language
= strdup( string( lang
).c_str() );
311 msg_Dbg( &sys
.demuxer
,
312 "| | | + Track Language=`%s'", tk
->fmt
.psz_language
);
314 else if( MKV_IS_ID( l
, KaxCodecID
) )
316 KaxCodecID
&codecid
= *(KaxCodecID
*)l
;
318 tk
->psz_codec
= strdup( string( codecid
).c_str() );
319 msg_Dbg( &sys
.demuxer
, "| | | + Track CodecId=%s", string( codecid
).c_str() );
321 else if( MKV_IS_ID( l
, KaxCodecPrivate
) )
323 KaxCodecPrivate
&cpriv
= *(KaxCodecPrivate
*)l
;
325 tk
->i_extra_data
= cpriv
.GetSize();
326 if( tk
->i_extra_data
> 0 )
328 tk
->p_extra_data
= (uint8_t*)malloc( tk
->i_extra_data
);
329 memcpy( tk
->p_extra_data
, cpriv
.GetBuffer(), tk
->i_extra_data
);
331 msg_Dbg( &sys
.demuxer
, "| | | + Track CodecPrivate size=%"PRId64
, cpriv
.GetSize() );
333 else if( MKV_IS_ID( l
, KaxCodecName
) )
335 KaxCodecName
&cname
= *(KaxCodecName
*)l
;
337 tk
->psz_codec_name
= ToUTF8( UTFstring( cname
) );
338 msg_Dbg( &sys
.demuxer
, "| | | + Track Codec Name=%s", tk
->psz_codec_name
);
340 else if( MKV_IS_ID( l
, KaxContentEncodings
) )
342 EbmlMaster
*cencs
= static_cast<EbmlMaster
*>(l
);
343 MkvTree( sys
.demuxer
, 3, "Content Encodings" );
344 if ( cencs
->ListSize() > 1 )
346 msg_Err( &sys
.demuxer
, "Multiple Compression method not supported" );
349 for( j
= 0; j
< cencs
->ListSize(); j
++ )
351 EbmlElement
*l2
= (*cencs
)[j
];
352 if( MKV_IS_ID( l2
, KaxContentEncoding
) )
354 MkvTree( sys
.demuxer
, 4, "Content Encoding" );
355 EbmlMaster
*cenc
= static_cast<EbmlMaster
*>(l2
);
356 for( k
= 0; k
< cenc
->ListSize(); k
++ )
358 EbmlElement
*l3
= (*cenc
)[k
];
359 if( MKV_IS_ID( l3
, KaxContentEncodingOrder
) )
361 KaxContentEncodingOrder
&encord
= *(KaxContentEncodingOrder
*)l3
;
362 MkvTree( sys
.demuxer
, 5, "Order: %i", uint32( encord
) );
364 else if( MKV_IS_ID( l3
, KaxContentEncodingScope
) )
366 KaxContentEncodingScope
&encscope
= *(KaxContentEncodingScope
*)l3
;
367 MkvTree( sys
.demuxer
, 5, "Scope: %i", uint32( encscope
) );
369 else if( MKV_IS_ID( l3
, KaxContentEncodingType
) )
371 KaxContentEncodingType
&enctype
= *(KaxContentEncodingType
*)l3
;
372 MkvTree( sys
.demuxer
, 5, "Type: %i", uint32( enctype
) );
374 else if( MKV_IS_ID( l3
, KaxContentCompression
) )
376 EbmlMaster
*compr
= static_cast<EbmlMaster
*>(l3
);
377 MkvTree( sys
.demuxer
, 5, "Content Compression" );
378 for( n
= 0; n
< compr
->ListSize(); n
++ )
380 EbmlElement
*l4
= (*compr
)[n
];
381 if( MKV_IS_ID( l4
, KaxContentCompAlgo
) )
383 KaxContentCompAlgo
&compalg
= *(KaxContentCompAlgo
*)l4
;
384 MkvTree( sys
.demuxer
, 6, "Compression Algorithm: %i", uint32(compalg
) );
385 tk
->i_compression_type
= uint32( compalg
);
386 if ( ( tk
->i_compression_type
!= MATROSKA_COMPRESSION_ZLIB
) &&
387 ( tk
->i_compression_type
!= MATROSKA_COMPRESSION_HEADER
) )
389 msg_Err( &sys
.demuxer
, "Track Compression method %d not supported", tk
->i_compression_type
);
393 else if( MKV_IS_ID( l4
, KaxContentCompSettings
) )
395 tk
->p_compression_data
= new KaxContentCompSettings( *(KaxContentCompSettings
*)l4
);
399 MkvTree( sys
.demuxer
, 6, "Unknown (%s)", typeid(*l4
).name() );
405 MkvTree( sys
.demuxer
, 5, "Unknown (%s)", typeid(*l3
).name() );
411 MkvTree( sys
.demuxer
, 4, "Unknown (%s)", typeid(*l2
).name() );
415 // else if( EbmlId( *l ) == KaxCodecSettings::ClassInfos.GlobalId )
417 // KaxCodecSettings &cset = *(KaxCodecSettings*)l;
419 // tk->psz_codec_settings = ToUTF8( UTFstring( cset ) );
420 // msg_Dbg( &sys.demuxer, "| | | + Track Codec Settings=%s", tk->psz_codec_settings );
422 // else if( EbmlId( *l ) == KaxCodecInfoURL::ClassInfos.GlobalId )
424 // KaxCodecInfoURL &ciurl = *(KaxCodecInfoURL*)l;
426 // tk->psz_codec_info_url = strdup( string( ciurl ).c_str() );
427 // msg_Dbg( &sys.demuxer, "| | | + Track Codec Info URL=%s", tk->psz_codec_info_url );
429 // else if( EbmlId( *l ) == KaxCodecDownloadURL::ClassInfos.GlobalId )
431 // KaxCodecDownloadURL &cdurl = *(KaxCodecDownloadURL*)l;
433 // tk->psz_codec_download_url = strdup( string( cdurl ).c_str() );
434 // msg_Dbg( &sys.demuxer, "| | | + Track Codec Info URL=%s", tk->psz_codec_download_url );
436 // else if( EbmlId( *l ) == KaxCodecDecodeAll::ClassInfos.GlobalId )
438 // KaxCodecDecodeAll &cdall = *(KaxCodecDecodeAll*)l;
440 // msg_Dbg( &sys.demuxer, "| | | + Track Codec Decode All=%u <== UNUSED", uint8( cdall ) );
442 // else if( EbmlId( *l ) == KaxTrackOverlay::ClassInfos.GlobalId )
444 // KaxTrackOverlay &tovr = *(KaxTrackOverlay*)l;
446 // msg_Dbg( &sys.demuxer, "| | | + Track Overlay=%u <== UNUSED", uint32( tovr ) );
448 else if( MKV_IS_ID( l
, KaxTrackVideo
) )
450 EbmlMaster
*tkv
= static_cast<EbmlMaster
*>(l
);
452 unsigned int i_crop_right
= 0, i_crop_left
= 0, i_crop_top
= 0, i_crop_bottom
= 0;
453 unsigned int i_display_unit
= 0, i_display_width
= 0, i_display_height
= 0;
455 msg_Dbg( &sys
.demuxer
, "| | | + Track Video" );
458 tk
->fmt
.video
.i_frame_rate_base
= (unsigned int)(tk
->i_default_duration
/ 1000);
459 tk
->fmt
.video
.i_frame_rate
= 1000000;
461 for( j
= 0; j
< tkv
->ListSize(); j
++ )
463 EbmlElement
*l
= (*tkv
)[j
];
464 // if( EbmlId( *el4 ) == KaxVideoFlagInterlaced::ClassInfos.GlobalId )
466 // KaxVideoFlagInterlaced &fint = *(KaxVideoFlagInterlaced*)el4;
468 // msg_Dbg( &sys.demuxer, "| | | | + Track Video Interlaced=%u", uint8( fint ) );
470 // else if( EbmlId( *el4 ) == KaxVideoStereoMode::ClassInfos.GlobalId )
472 // KaxVideoStereoMode &stereo = *(KaxVideoStereoMode*)el4;
474 // msg_Dbg( &sys.demuxer, "| | | | + Track Video Stereo Mode=%u", uint8( stereo ) );
477 if( MKV_IS_ID( l
, KaxVideoPixelWidth
) )
479 KaxVideoPixelWidth
&vwidth
= *(KaxVideoPixelWidth
*)l
;
481 tk
->fmt
.video
.i_width
+= uint16( vwidth
);
482 msg_Dbg( &sys
.demuxer
, "| | | | + width=%d", uint16( vwidth
) );
484 else if( MKV_IS_ID( l
, KaxVideoPixelHeight
) )
486 KaxVideoPixelWidth
&vheight
= *(KaxVideoPixelWidth
*)l
;
488 tk
->fmt
.video
.i_height
+= uint16( vheight
);
489 msg_Dbg( &sys
.demuxer
, "| | | | + height=%d", uint16( vheight
) );
491 else if( MKV_IS_ID( l
, KaxVideoDisplayWidth
) )
493 KaxVideoDisplayWidth
&vwidth
= *(KaxVideoDisplayWidth
*)l
;
495 i_display_width
= uint16( vwidth
);
496 msg_Dbg( &sys
.demuxer
, "| | | | + display width=%d", uint16( vwidth
) );
498 else if( MKV_IS_ID( l
, KaxVideoDisplayHeight
) )
500 KaxVideoDisplayWidth
&vheight
= *(KaxVideoDisplayWidth
*)l
;
502 i_display_height
= uint16( vheight
);
503 msg_Dbg( &sys
.demuxer
, "| | | | + display height=%d", uint16( vheight
) );
505 else if( MKV_IS_ID( l
, KaxVideoPixelCropBottom
) )
507 KaxVideoPixelCropBottom
&cropval
= *(KaxVideoPixelCropBottom
*)l
;
509 i_crop_bottom
= uint16( cropval
);
510 msg_Dbg( &sys
.demuxer
, "| | | | + crop pixel bottom=%d", uint16( cropval
) );
512 else if( MKV_IS_ID( l
, KaxVideoPixelCropTop
) )
514 KaxVideoPixelCropTop
&cropval
= *(KaxVideoPixelCropTop
*)l
;
516 i_crop_top
= uint16( cropval
);
517 msg_Dbg( &sys
.demuxer
, "| | | | + crop pixel top=%d", uint16( cropval
) );
519 else if( MKV_IS_ID( l
, KaxVideoPixelCropRight
) )
521 KaxVideoPixelCropRight
&cropval
= *(KaxVideoPixelCropRight
*)l
;
523 i_crop_right
= uint16( cropval
);
524 msg_Dbg( &sys
.demuxer
, "| | | | + crop pixel right=%d", uint16( cropval
) );
526 else if( MKV_IS_ID( l
, KaxVideoPixelCropLeft
) )
528 KaxVideoPixelCropLeft
&cropval
= *(KaxVideoPixelCropLeft
*)l
;
530 i_crop_left
= uint16( cropval
);
531 msg_Dbg( &sys
.demuxer
, "| | | | + crop pixel left=%d", uint16( cropval
) );
533 else if( MKV_IS_ID( l
, KaxVideoFrameRate
) )
535 KaxVideoFrameRate
&vfps
= *(KaxVideoFrameRate
*)l
;
537 tk
->f_fps
= float( vfps
);
538 msg_Dbg( &sys
.demuxer
, " | | | + fps=%f", float( vfps
) );
540 else if( EbmlId( *l
) == KaxVideoDisplayUnit::ClassInfos
.GlobalId
)
542 KaxVideoDisplayUnit
&vdmode
= *(KaxVideoDisplayUnit
*)l
;
544 i_display_unit
= uint8( vdmode
);
545 msg_Dbg( &sys
.demuxer
, "| | | | + Track Video Display Unit=%s",
546 uint8( vdmode
) == 0 ? "pixels" : ( uint8( vdmode
) == 1 ? "centimeters": "inches" ) );
548 // else if( EbmlId( *l ) == KaxVideoAspectRatio::ClassInfos.GlobalId )
550 // KaxVideoAspectRatio &ratio = *(KaxVideoAspectRatio*)l;
552 // msg_Dbg( &sys.demuxer, " | | | + Track Video Aspect Ratio Type=%u", uint8( ratio ) );
554 // else if( EbmlId( *l ) == KaxVideoGamma::ClassInfos.GlobalId )
556 // KaxVideoGamma &gamma = *(KaxVideoGamma*)l;
558 // msg_Dbg( &sys.demuxer, " | | | + gamma=%f", float( gamma ) );
562 msg_Dbg( &sys
.demuxer
, "| | | | + Unknown (%s)", typeid(*l
).name() );
565 if( i_display_height
&& i_display_width
)
566 tk
->fmt
.video
.i_aspect
= VOUT_ASPECT_FACTOR
* i_display_width
/ i_display_height
;
567 if( i_crop_left
|| i_crop_right
|| i_crop_top
|| i_crop_bottom
)
569 tk
->fmt
.video
.i_visible_width
= tk
->fmt
.video
.i_width
;
570 tk
->fmt
.video
.i_visible_height
= tk
->fmt
.video
.i_height
;
571 tk
->fmt
.video
.i_x_offset
= i_crop_left
;
572 tk
->fmt
.video
.i_y_offset
= i_crop_top
;
573 tk
->fmt
.video
.i_visible_width
-= i_crop_left
+ i_crop_right
;
574 tk
->fmt
.video
.i_visible_height
-= i_crop_top
+ i_crop_bottom
;
576 /* FIXME: i_display_* allows you to not only set DAR, but also a zoom factor.
577 we do not support this atm */
579 else if( MKV_IS_ID( l
, KaxTrackAudio
) )
581 EbmlMaster
*tka
= static_cast<EbmlMaster
*>(l
);
584 msg_Dbg( &sys
.demuxer
, "| | | + Track Audio" );
586 for( j
= 0; j
< tka
->ListSize(); j
++ )
588 EbmlElement
*l
= (*tka
)[j
];
590 if( MKV_IS_ID( l
, KaxAudioSamplingFreq
) )
592 KaxAudioSamplingFreq
&afreq
= *(KaxAudioSamplingFreq
*)l
;
594 tk
->i_original_rate
= tk
->fmt
.audio
.i_rate
= (int)float( afreq
);
595 msg_Dbg( &sys
.demuxer
, "| | | | + afreq=%d", tk
->fmt
.audio
.i_rate
);
597 else if( MKV_IS_ID( l
, KaxAudioOutputSamplingFreq
) )
599 KaxAudioOutputSamplingFreq
&afreq
= *(KaxAudioOutputSamplingFreq
*)l
;
601 tk
->fmt
.audio
.i_rate
= (int)float( afreq
);
602 msg_Dbg( &sys
.demuxer
, "| | | | + aoutfreq=%d", tk
->fmt
.audio
.i_rate
);
604 else if( MKV_IS_ID( l
, KaxAudioChannels
) )
606 KaxAudioChannels
&achan
= *(KaxAudioChannels
*)l
;
608 tk
->fmt
.audio
.i_channels
= uint8( achan
);
609 msg_Dbg( &sys
.demuxer
, "| | | | + achan=%u", uint8( achan
) );
611 else if( MKV_IS_ID( l
, KaxAudioBitDepth
) )
613 KaxAudioBitDepth
&abits
= *(KaxAudioBitDepth
*)l
;
615 tk
->fmt
.audio
.i_bitspersample
= uint8( abits
);
616 msg_Dbg( &sys
.demuxer
, "| | | | + abits=%u", uint8( abits
) );
620 msg_Dbg( &sys
.demuxer
, "| | | | + Unknown (%s)", typeid(*l
).name() );
626 msg_Dbg( &sys
.demuxer
, "| | | + Unknown (%s)",
633 tracks
.push_back( tk
);
637 msg_Err( &sys
.demuxer
, "Track Entry %d not supported", tk
->i_number
);
642 /*****************************************************************************
644 *****************************************************************************/
645 void matroska_segment_c::ParseTracks( KaxTracks
*tracks
)
649 int i_upper_level
= 0;
651 /* Master elements */
652 tracks
->Read( es
, tracks
->Generic().Context
, i_upper_level
, el
, true );
654 for( i
= 0; i
< tracks
->ListSize(); i
++ )
656 EbmlElement
*l
= (*tracks
)[i
];
658 if( MKV_IS_ID( l
, KaxTrackEntry
) )
660 ParseTrackEntry( static_cast<KaxTrackEntry
*>(l
) );
664 msg_Dbg( &sys
.demuxer
, "| | + Unknown (%s)", typeid(*l
).name() );
669 /*****************************************************************************
671 *****************************************************************************/
672 void matroska_segment_c::ParseInfo( KaxInfo
*info
)
677 int i_upper_level
= 0;
679 /* Master elements */
680 m
= static_cast<EbmlMaster
*>(info
);
681 m
->Read( es
, info
->Generic().Context
, i_upper_level
, el
, true );
683 for( i
= 0; i
< m
->ListSize(); i
++ )
685 EbmlElement
*l
= (*m
)[i
];
687 if( MKV_IS_ID( l
, KaxSegmentUID
) )
689 if ( p_segment_uid
== NULL
)
690 p_segment_uid
= new KaxSegmentUID(*static_cast<KaxSegmentUID
*>(l
));
692 msg_Dbg( &sys
.demuxer
, "| | + UID=%d", *(uint32
*)p_segment_uid
->GetBuffer() );
694 else if( MKV_IS_ID( l
, KaxPrevUID
) )
696 if ( p_prev_segment_uid
== NULL
)
697 p_prev_segment_uid
= new KaxPrevUID(*static_cast<KaxPrevUID
*>(l
));
699 msg_Dbg( &sys
.demuxer
, "| | + PrevUID=%d", *(uint32
*)p_prev_segment_uid
->GetBuffer() );
701 else if( MKV_IS_ID( l
, KaxNextUID
) )
703 if ( p_next_segment_uid
== NULL
)
704 p_next_segment_uid
= new KaxNextUID(*static_cast<KaxNextUID
*>(l
));
706 msg_Dbg( &sys
.demuxer
, "| | + NextUID=%d", *(uint32
*)p_next_segment_uid
->GetBuffer() );
708 else if( MKV_IS_ID( l
, KaxTimecodeScale
) )
710 KaxTimecodeScale
&tcs
= *(KaxTimecodeScale
*)l
;
712 i_timescale
= uint64(tcs
);
714 msg_Dbg( &sys
.demuxer
, "| | + TimecodeScale=%"PRId64
,
717 else if( MKV_IS_ID( l
, KaxDuration
) )
719 KaxDuration
&dur
= *(KaxDuration
*)l
;
721 i_duration
= mtime_t( double( dur
) );
723 msg_Dbg( &sys
.demuxer
, "| | + Duration=%"PRId64
,
726 else if( MKV_IS_ID( l
, KaxMuxingApp
) )
728 KaxMuxingApp
&mapp
= *(KaxMuxingApp
*)l
;
730 psz_muxing_application
= ToUTF8( UTFstring( mapp
) );
732 msg_Dbg( &sys
.demuxer
, "| | + Muxing Application=%s",
733 psz_muxing_application
);
735 else if( MKV_IS_ID( l
, KaxWritingApp
) )
737 KaxWritingApp
&wapp
= *(KaxWritingApp
*)l
;
739 psz_writing_application
= ToUTF8( UTFstring( wapp
) );
741 msg_Dbg( &sys
.demuxer
, "| | + Writing Application=%s",
742 psz_writing_application
);
744 else if( MKV_IS_ID( l
, KaxSegmentFilename
) )
746 KaxSegmentFilename
&sfn
= *(KaxSegmentFilename
*)l
;
748 psz_segment_filename
= ToUTF8( UTFstring( sfn
) );
750 msg_Dbg( &sys
.demuxer
, "| | + Segment Filename=%s",
751 psz_segment_filename
);
753 else if( MKV_IS_ID( l
, KaxTitle
) )
755 KaxTitle
&title
= *(KaxTitle
*)l
;
757 psz_title
= ToUTF8( UTFstring( title
) );
759 msg_Dbg( &sys
.demuxer
, "| | + Title=%s", psz_title
);
761 else if( MKV_IS_ID( l
, KaxSegmentFamily
) )
763 KaxSegmentFamily
*uid
= static_cast<KaxSegmentFamily
*>(l
);
765 families
.push_back( new KaxSegmentFamily(*uid
) );
767 msg_Dbg( &sys
.demuxer
, "| | + family=%d", *(uint32
*)uid
->GetBuffer() );
769 #if defined( HAVE_GMTIME_R )
770 else if( MKV_IS_ID( l
, KaxDateUTC
) )
772 KaxDateUTC
&date
= *(KaxDateUTC
*)l
;
777 i_date
= date
.GetEpochDate();
778 memset( buffer
, 0, 256 );
779 if( gmtime_r( &i_date
, &tmres
) &&
780 asctime_r( &tmres
, buffer
) )
782 buffer
[strlen( buffer
)-1]= '\0';
783 psz_date_utc
= strdup( buffer
);
784 msg_Dbg( &sys
.demuxer
, "| | + Date=%s", psz_date_utc
);
788 else if( MKV_IS_ID( l
, KaxChapterTranslate
) )
790 KaxChapterTranslate
*p_trans
= static_cast<KaxChapterTranslate
*>( l
);
791 chapter_translation_c
*p_translate
= new chapter_translation_c();
793 p_trans
->Read( es
, p_trans
->Generic().Context
, i_upper_level
, el
, true );
794 for( j
= 0; j
< p_trans
->ListSize(); j
++ )
796 EbmlElement
*l
= (*p_trans
)[j
];
798 if( MKV_IS_ID( l
, KaxChapterTranslateEditionUID
) )
800 p_translate
->editions
.push_back( uint64( *static_cast<KaxChapterTranslateEditionUID
*>( l
) ) );
802 else if( MKV_IS_ID( l
, KaxChapterTranslateCodec
) )
804 p_translate
->codec_id
= uint32( *static_cast<KaxChapterTranslateCodec
*>( l
) );
806 else if( MKV_IS_ID( l
, KaxChapterTranslateID
) )
808 p_translate
->p_translated
= new KaxChapterTranslateID( *static_cast<KaxChapterTranslateID
*>( l
) );
812 translations
.push_back( p_translate
);
816 msg_Dbg( &sys
.demuxer
, "| | + Unknown (%s)", typeid(*l
).name() );
820 double f_dur
= double(i_duration
) * double(i_timescale
) / 1000000.0;
821 i_duration
= mtime_t(f_dur
);
825 /*****************************************************************************
827 *****************************************************************************/
828 void matroska_segment_c::ParseChapterAtom( int i_level
, KaxChapterAtom
*ca
, chapter_item_c
& chapters
)
832 msg_Dbg( &sys
.demuxer
, "| | | + ChapterAtom (level=%d)", i_level
);
833 for( i
= 0; i
< ca
->ListSize(); i
++ )
835 EbmlElement
*l
= (*ca
)[i
];
837 if( MKV_IS_ID( l
, KaxChapterUID
) )
839 chapters
.i_uid
= uint64_t(*(KaxChapterUID
*)l
);
840 msg_Dbg( &sys
.demuxer
, "| | | | + ChapterUID: %lld", chapters
.i_uid
);
842 else if( MKV_IS_ID( l
, KaxChapterFlagHidden
) )
844 KaxChapterFlagHidden
&flag
=*(KaxChapterFlagHidden
*)l
;
845 chapters
.b_display_seekpoint
= uint8( flag
) == 0;
847 msg_Dbg( &sys
.demuxer
, "| | | | + ChapterFlagHidden: %s", chapters
.b_display_seekpoint
? "no":"yes" );
849 else if( MKV_IS_ID( l
, KaxChapterTimeStart
) )
851 KaxChapterTimeStart
&start
=*(KaxChapterTimeStart
*)l
;
852 chapters
.i_start_time
= uint64( start
) / INT64_C(1000);
854 msg_Dbg( &sys
.demuxer
, "| | | | + ChapterTimeStart: %lld", chapters
.i_start_time
);
856 else if( MKV_IS_ID( l
, KaxChapterTimeEnd
) )
858 KaxChapterTimeEnd
&end
=*(KaxChapterTimeEnd
*)l
;
859 chapters
.i_end_time
= uint64( end
) / INT64_C(1000);
861 msg_Dbg( &sys
.demuxer
, "| | | | + ChapterTimeEnd: %lld", chapters
.i_end_time
);
863 else if( MKV_IS_ID( l
, KaxChapterDisplay
) )
865 EbmlMaster
*cd
= static_cast<EbmlMaster
*>(l
);
867 msg_Dbg( &sys
.demuxer
, "| | | | + ChapterDisplay" );
868 for( j
= 0; j
< cd
->ListSize(); j
++ )
870 EbmlElement
*l
= (*cd
)[j
];
872 if( MKV_IS_ID( l
, KaxChapterString
) )
876 KaxChapterString
&name
=*(KaxChapterString
*)l
;
877 for (k
= 0; k
< i_level
; k
++)
878 chapters
.psz_name
+= '+';
879 chapters
.psz_name
+= ' ';
880 char *psz_tmp_utf8
= ToUTF8( UTFstring( name
) );
881 chapters
.psz_name
+= psz_tmp_utf8
;
882 chapters
.b_user_display
= true;
884 msg_Dbg( &sys
.demuxer
, "| | | | | + ChapterString '%s'", psz_tmp_utf8
);
885 free( psz_tmp_utf8
);
887 else if( MKV_IS_ID( l
, KaxChapterLanguage
) )
889 KaxChapterLanguage
&lang
=*(KaxChapterLanguage
*)l
;
890 const char *psz
= string( lang
).c_str();
892 msg_Dbg( &sys
.demuxer
, "| | | | | + ChapterLanguage '%s'", psz
);
894 else if( MKV_IS_ID( l
, KaxChapterCountry
) )
896 KaxChapterCountry
&ct
=*(KaxChapterCountry
*)l
;
897 const char *psz
= string( ct
).c_str();
899 msg_Dbg( &sys
.demuxer
, "| | | | | + ChapterCountry '%s'", psz
);
903 else if( MKV_IS_ID( l
, KaxChapterProcess
) )
905 msg_Dbg( &sys
.demuxer
, "| | | | + ChapterProcess" );
907 KaxChapterProcess
*cp
= static_cast<KaxChapterProcess
*>(l
);
908 chapter_codec_cmds_c
*p_ccodec
= NULL
;
910 for( j
= 0; j
< cp
->ListSize(); j
++ )
912 EbmlElement
*k
= (*cp
)[j
];
914 if( MKV_IS_ID( k
, KaxChapterProcessCodecID
) )
916 KaxChapterProcessCodecID
*p_codec_id
= static_cast<KaxChapterProcessCodecID
*>( k
);
917 if ( uint32(*p_codec_id
) == 0 )
918 p_ccodec
= new matroska_script_codec_c( sys
);
919 else if ( uint32(*p_codec_id
) == 1 )
920 p_ccodec
= new dvd_chapter_codec_c( sys
);
925 if ( p_ccodec
!= NULL
)
927 for( j
= 0; j
< cp
->ListSize(); j
++ )
929 EbmlElement
*k
= (*cp
)[j
];
931 if( MKV_IS_ID( k
, KaxChapterProcessPrivate
) )
933 KaxChapterProcessPrivate
* p_private
= static_cast<KaxChapterProcessPrivate
*>( k
);
934 p_ccodec
->SetPrivate( *p_private
);
936 else if( MKV_IS_ID( k
, KaxChapterProcessCommand
) )
938 p_ccodec
->AddCommand( *static_cast<KaxChapterProcessCommand
*>( k
) );
941 chapters
.codecs
.push_back( p_ccodec
);
944 else if( MKV_IS_ID( l
, KaxChapterAtom
) )
946 chapter_item_c
*new_sub_chapter
= new chapter_item_c();
947 ParseChapterAtom( i_level
+1, static_cast<KaxChapterAtom
*>(l
), *new_sub_chapter
);
948 new_sub_chapter
->psz_parent
= &chapters
;
949 chapters
.sub_chapters
.push_back( new_sub_chapter
);
954 /*****************************************************************************
956 *****************************************************************************/
957 void matroska_segment_c::ParseAttachments( KaxAttachments
*attachments
)
960 int i_upper_level
= 0;
962 attachments
->Read( es
, attachments
->Generic().Context
, i_upper_level
, el
, true );
964 KaxAttached
*attachedFile
= FindChild
<KaxAttached
>( *attachments
);
966 while( attachedFile
&& ( attachedFile
->GetSize() > 0 ) )
968 std::string psz_mime_type
= GetChild
<KaxMimeType
>( *attachedFile
);
969 KaxFileName
&file_name
= GetChild
<KaxFileName
>( *attachedFile
);
970 KaxFileData
&img_data
= GetChild
<KaxFileData
>( *attachedFile
);
972 attachment_c
*new_attachment
= new attachment_c();
976 new_attachment
->psz_file_name
= ToUTF8( UTFstring( file_name
) );
977 new_attachment
->psz_mime_type
= psz_mime_type
;
978 new_attachment
->i_size
= img_data
.GetSize();
979 new_attachment
->p_data
= malloc( img_data
.GetSize() );
981 if( new_attachment
->p_data
)
983 memcpy( new_attachment
->p_data
, img_data
.GetBuffer(), img_data
.GetSize() );
984 sys
.stored_attachments
.push_back( new_attachment
);
988 delete new_attachment
;
992 attachedFile
= &GetNextChild
<KaxAttached
>( *attachments
, *attachedFile
);
996 /*****************************************************************************
998 *****************************************************************************/
999 void matroska_segment_c::ParseChapters( KaxChapters
*chapters
)
1003 int i_upper_level
= 0;
1006 /* Master elements */
1007 chapters
->Read( es
, chapters
->Generic().Context
, i_upper_level
, el
, true );
1009 for( i
= 0; i
< chapters
->ListSize(); i
++ )
1011 EbmlElement
*l
= (*chapters
)[i
];
1013 if( MKV_IS_ID( l
, KaxEditionEntry
) )
1015 chapter_edition_c
*p_edition
= new chapter_edition_c();
1017 EbmlMaster
*E
= static_cast<EbmlMaster
*>(l
);
1019 msg_Dbg( &sys
.demuxer
, "| | + EditionEntry" );
1020 for( j
= 0; j
< E
->ListSize(); j
++ )
1022 EbmlElement
*l
= (*E
)[j
];
1024 if( MKV_IS_ID( l
, KaxChapterAtom
) )
1026 chapter_item_c
*new_sub_chapter
= new chapter_item_c();
1027 ParseChapterAtom( 0, static_cast<KaxChapterAtom
*>(l
), *new_sub_chapter
);
1028 p_edition
->sub_chapters
.push_back( new_sub_chapter
);
1030 else if( MKV_IS_ID( l
, KaxEditionUID
) )
1032 p_edition
->i_uid
= uint64(*static_cast<KaxEditionUID
*>( l
));
1034 else if( MKV_IS_ID( l
, KaxEditionFlagOrdered
) )
1036 p_edition
->b_ordered
= config_GetInt( &sys
.demuxer
, "mkv-use-ordered-chapters" ) ? (uint8(*static_cast<KaxEditionFlagOrdered
*>( l
)) != 0) : 0;
1038 else if( MKV_IS_ID( l
, KaxEditionFlagDefault
) )
1040 if (uint8(*static_cast<KaxEditionFlagDefault
*>( l
)) != 0)
1041 i_default_edition
= stored_editions
.size();
1045 msg_Dbg( &sys
.demuxer
, "| | | + Unknown (%s)", typeid(*l
).name() );
1048 stored_editions
.push_back( p_edition
);
1052 msg_Dbg( &sys
.demuxer
, "| | + Unknown (%s)", typeid(*l
).name() );
1056 for( i
= 0; i
< stored_editions
.size(); i
++ )
1058 stored_editions
[i
]->RefreshChapters( );
1061 if ( stored_editions
.size() != 0 && stored_editions
[i_default_edition
]->b_ordered
)
1063 /* update the duration of the segment according to the sum of all sub chapters */
1064 i_dur
= stored_editions
[i_default_edition
]->Duration() / INT64_C(1000);
1070 void matroska_segment_c::ParseCluster( )
1075 int i_upper_level
= 0;
1077 /* Master elements */
1078 m
= static_cast<EbmlMaster
*>( cluster
);
1079 m
->Read( es
, cluster
->Generic().Context
, i_upper_level
, el
, true );
1081 for( i
= 0; i
< m
->ListSize(); i
++ )
1083 EbmlElement
*l
= (*m
)[i
];
1085 if( MKV_IS_ID( l
, KaxClusterTimecode
) )
1087 KaxClusterTimecode
&ctc
= *(KaxClusterTimecode
*)l
;
1089 cluster
->InitTimecode( uint64( ctc
), i_timescale
);
1094 i_start_time
= cluster
->GlobalTimecode() / 1000;