+ ccpos.ReadData( es.I_O() );
+ idx.i_position = segment->GetGlobalPosition( uint64( ccpos ) );
+ }
+ else if( MKV_IS_ID( el, KaxCueBlockNumber ) )
+ {
+ KaxCueBlockNumber &cbnum = *(KaxCueBlockNumber*)el;
+
+ cbnum.ReadData( es.I_O() );
+ idx.i_block_number = uint32( cbnum );
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() );
+ }
+ }
+ ep->Up();
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() );
+ }
+ }
+ ep->Up();
+
+#if 0
+ msg_Dbg( &sys.demuxer, " * added time="I64Fd" pos="I64Fd
+ " track=%d bnum=%d", idx.i_time, idx.i_position,
+ idx.i_track, idx.i_block_number );
+#endif
+
+ i_index++;
+ if( i_index >= i_index_max )
+ {
+ i_index_max += 1024;
+ p_indexes = (mkv_index_t*)realloc( p_indexes, sizeof( mkv_index_t ) * i_index_max );
+ }
+#undef idx
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, " * Unknown (%s)", typeid(*el).name() );
+ }
+ }
+ delete ep;
+ delete cues;
+
+ b_cues = VLC_TRUE;
+
+ msg_Dbg( &sys.demuxer, "loading cues done." );
+ es.I_O().setFilePointer( i_sav_position, seek_beginning );
+}
+
+void matroska_segment_c::LoadTags( )
+{
+ int64_t i_sav_position = es.I_O().getFilePointer();
+ EbmlParser *ep;
+ EbmlElement *el, *tags;
+
+ msg_Dbg( &sys.demuxer, "loading tags" );
+ es.I_O().setFilePointer( i_tags_position, seek_beginning );
+ tags = es.FindNextID( KaxTags::ClassInfos, 0xFFFFFFFFL);
+
+ if( tags == NULL )
+ {
+ msg_Err( &sys.demuxer, "cannot load tags (broken seekhead or file)" );
+ es.I_O().setFilePointer( i_sav_position, seek_beginning );
+ return;
+ }
+
+ msg_Dbg( &sys.demuxer, "Tags" );
+ ep = new EbmlParser( &es, tags, &sys.demuxer );
+ while( ( el = ep->Get() ) != NULL )
+ {
+ if( MKV_IS_ID( el, KaxTag ) )
+ {
+ msg_Dbg( &sys.demuxer, "+ Tag" );
+ ep->Down();
+ while( ( el = ep->Get() ) != NULL )
+ {
+ if( MKV_IS_ID( el, KaxTagTargets ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + Targets" );
+ ep->Down();
+ while( ( el = ep->Get() ) != NULL )
+ {
+ msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid( *el ).name() );
+ }
+ ep->Up();
+ }
+ else if( MKV_IS_ID( el, KaxTagGeneral ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + General" );
+ ep->Down();
+ while( ( el = ep->Get() ) != NULL )
+ {
+ msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid( *el ).name() );
+ }
+ ep->Up();
+ }
+ else if( MKV_IS_ID( el, KaxTagGenres ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + Genres" );
+ ep->Down();
+ while( ( el = ep->Get() ) != NULL )
+ {
+ msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid( *el ).name() );
+ }
+ ep->Up();
+ }
+ else if( MKV_IS_ID( el, KaxTagAudioSpecific ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + Audio Specific" );
+ ep->Down();
+ while( ( el = ep->Get() ) != NULL )
+ {
+ msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid( *el ).name() );
+ }
+ ep->Up();
+ }
+ else if( MKV_IS_ID( el, KaxTagImageSpecific ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + Images Specific" );
+ ep->Down();
+ while( ( el = ep->Get() ) != NULL )
+ {
+ msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid( *el ).name() );
+ }
+ ep->Up();
+ }
+ else if( MKV_IS_ID( el, KaxTagMultiComment ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + Multi Comment" );
+ }
+ else if( MKV_IS_ID( el, KaxTagMultiCommercial ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + Multi Commercial" );
+ }
+ else if( MKV_IS_ID( el, KaxTagMultiDate ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + Multi Date" );
+ }
+ else if( MKV_IS_ID( el, KaxTagMultiEntity ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + Multi Entity" );
+ }
+ else if( MKV_IS_ID( el, KaxTagMultiIdentifier ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + Multi Identifier" );
+ }
+ else if( MKV_IS_ID( el, KaxTagMultiLegal ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + Multi Legal" );
+ }
+ else if( MKV_IS_ID( el, KaxTagMultiTitle ) )
+ {
+ msg_Dbg( &sys.demuxer, "| + Multi Title" );
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, "| + Unknown (%s)", typeid( *el ).name() );
+ }
+ }
+ ep->Up();
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, "+ Unknown (%s)", typeid( *el ).name() );
+ }
+ }
+ delete ep;
+ delete tags;
+
+ msg_Dbg( &sys.demuxer, "loading tags done." );
+ es.I_O().setFilePointer( i_sav_position, seek_beginning );
+}
+
+/*****************************************************************************
+ * ParseSeekHead:
+ *****************************************************************************/
+void matroska_segment_c::ParseSeekHead( KaxSeekHead *seekhead )
+{
+ EbmlElement *el;
+ size_t i, j;
+ int i_upper_level = 0;
+
+ msg_Dbg( &sys.demuxer, "| + Seek head" );
+
+ /* Master elements */
+ seekhead->Read( es, seekhead->Generic().Context, i_upper_level, el, true );
+
+ for( i = 0; i < seekhead->ListSize(); i++ )
+ {
+ EbmlElement *l = (*seekhead)[i];
+
+ if( MKV_IS_ID( l, KaxSeek ) )
+ {
+ EbmlMaster *sk = static_cast<EbmlMaster *>(l);
+ EbmlId id = EbmlVoid::ClassInfos.GlobalId;
+ int64_t i_pos = -1;
+
+ for( j = 0; j < sk->ListSize(); j++ )
+ {
+ EbmlElement *l = (*sk)[j];
+
+ if( MKV_IS_ID( l, KaxSeekID ) )
+ {
+ KaxSeekID &sid = *(KaxSeekID*)l;
+ id = EbmlId( sid.GetBuffer(), sid.GetSize() );
+ }
+ else if( MKV_IS_ID( l, KaxSeekPosition ) )
+ {
+ KaxSeekPosition &spos = *(KaxSeekPosition*)l;
+ i_pos = uint64( spos );
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, "| | | + Unknown (%s)", typeid(*l).name() );
+ }
+ }
+
+ if( i_pos >= 0 )
+ {
+ if( id == KaxCues::ClassInfos.GlobalId )
+ {
+ msg_Dbg( &sys.demuxer, "| | | = cues at "I64Fd, i_pos );
+ i_cues_position = segment->GetGlobalPosition( i_pos );
+ }
+ else if( id == KaxChapters::ClassInfos.GlobalId )
+ {
+ msg_Dbg( &sys.demuxer, "| | | = chapters at "I64Fd, i_pos );
+ i_chapters_position = segment->GetGlobalPosition( i_pos );
+ }
+ else if( id == KaxTags::ClassInfos.GlobalId )
+ {
+ msg_Dbg( &sys.demuxer, "| | | = tags at "I64Fd, i_pos );
+ i_tags_position = segment->GetGlobalPosition( i_pos );
+ }
+ }
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid(*l).name() );
+ }
+ }
+}
+
+/*****************************************************************************
+ * ParseTrackEntry:
+ *****************************************************************************/
+void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
+{
+ size_t i, j, k, n;
+ bool bSupported = true;
+
+ mkv_track_t *tk;
+
+ msg_Dbg( &sys.demuxer, "| | + Track Entry" );
+
+ tk = new mkv_track_t();
+
+ /* Init the track */
+ memset( tk, 0, sizeof( mkv_track_t ) );
+
+ es_format_Init( &tk->fmt, UNKNOWN_ES, 0 );
+ tk->fmt.psz_language = strdup("English");
+ tk->fmt.psz_description = NULL;
+
+ tk->b_default = VLC_TRUE;
+ tk->b_enabled = VLC_TRUE;
+ tk->b_silent = VLC_FALSE;
+ tk->i_number = tracks.size() - 1;
+ tk->i_extra_data = 0;
+ tk->p_extra_data = NULL;
+ tk->psz_codec = NULL;
+ tk->i_default_duration = 0;
+ tk->f_timecodescale = 1.0;
+
+ tk->b_inited = VLC_FALSE;
+ tk->i_data_init = 0;
+ tk->p_data_init = NULL;
+
+ tk->psz_codec_name = NULL;
+ tk->psz_codec_settings = NULL;
+ tk->psz_codec_info_url = NULL;
+ tk->psz_codec_download_url = NULL;
+
+ tk->i_compression_type = MATROSKA_COMPRESSION_NONE;
+ tk->p_compression_data = NULL;
+
+ for( i = 0; i < m->ListSize(); i++ )
+ {
+ EbmlElement *l = (*m)[i];
+
+ if( MKV_IS_ID( l, KaxTrackNumber ) )
+ {
+ KaxTrackNumber &tnum = *(KaxTrackNumber*)l;
+
+ tk->i_number = uint32( tnum );
+ msg_Dbg( &sys.demuxer, "| | | + Track Number=%u", uint32( tnum ) );
+ }
+ else if( MKV_IS_ID( l, KaxTrackUID ) )
+ {
+ KaxTrackUID &tuid = *(KaxTrackUID*)l;
+
+ msg_Dbg( &sys.demuxer, "| | | + Track UID=%u", uint32( tuid ) );
+ }
+ else if( MKV_IS_ID( l, KaxTrackType ) )
+ {
+ const char *psz_type;
+ KaxTrackType &ttype = *(KaxTrackType*)l;
+
+ switch( uint8(ttype) )
+ {
+ case track_audio:
+ psz_type = "audio";
+ tk->fmt.i_cat = AUDIO_ES;
+ break;
+ case track_video:
+ psz_type = "video";
+ tk->fmt.i_cat = VIDEO_ES;
+ break;
+ case track_subtitle:
+ psz_type = "subtitle";
+ tk->fmt.i_cat = SPU_ES;
+ break;
+ case track_buttons:
+ psz_type = "buttons";
+ tk->fmt.i_cat = SPU_ES;
+ break;
+ default:
+ psz_type = "unknown";
+ tk->fmt.i_cat = UNKNOWN_ES;
+ break;
+ }
+
+ msg_Dbg( &sys.demuxer, "| | | + Track Type=%s", psz_type );
+ }
+// else if( EbmlId( *l ) == KaxTrackFlagEnabled::ClassInfos.GlobalId )
+// {
+// KaxTrackFlagEnabled &fenb = *(KaxTrackFlagEnabled*)l;
+
+// tk->b_enabled = uint32( fenb );
+// msg_Dbg( &sys.demuxer, "| | | + Track Enabled=%u",
+// uint32( fenb ) );
+// }
+ else if( MKV_IS_ID( l, KaxTrackFlagDefault ) )
+ {
+ KaxTrackFlagDefault &fdef = *(KaxTrackFlagDefault*)l;
+
+ tk->b_default = uint32( fdef );
+ msg_Dbg( &sys.demuxer, "| | | + Track Default=%u", uint32( fdef ) );
+ }
+ else if( MKV_IS_ID( l, KaxTrackFlagLacing ) )
+ {
+ KaxTrackFlagLacing &lac = *(KaxTrackFlagLacing*)l;
+
+ msg_Dbg( &sys.demuxer, "| | | + Track Lacing=%d", uint32( lac ) );
+ }
+ else if( MKV_IS_ID( l, KaxTrackMinCache ) )
+ {
+ KaxTrackMinCache &cmin = *(KaxTrackMinCache*)l;
+
+ msg_Dbg( &sys.demuxer, "| | | + Track MinCache=%d", uint32( cmin ) );
+ }
+ else if( MKV_IS_ID( l, KaxTrackMaxCache ) )
+ {
+ KaxTrackMaxCache &cmax = *(KaxTrackMaxCache*)l;
+
+ msg_Dbg( &sys.demuxer, "| | | + Track MaxCache=%d", uint32( cmax ) );
+ }
+ else if( MKV_IS_ID( l, KaxTrackDefaultDuration ) )
+ {
+ KaxTrackDefaultDuration &defd = *(KaxTrackDefaultDuration*)l;
+
+ tk->i_default_duration = uint64(defd);
+ msg_Dbg( &sys.demuxer, "| | | + Track Default Duration="I64Fd, uint64(defd) );
+ }
+ else if( MKV_IS_ID( l, KaxTrackTimecodeScale ) )
+ {
+ KaxTrackTimecodeScale &ttcs = *(KaxTrackTimecodeScale*)l;
+
+ tk->f_timecodescale = float( ttcs );
+ msg_Dbg( &sys.demuxer, "| | | + Track TimeCodeScale=%f", tk->f_timecodescale );
+ }
+ else if( MKV_IS_ID( l, KaxTrackName ) )
+ {
+ KaxTrackName &tname = *(KaxTrackName*)l;
+
+ tk->fmt.psz_description = ToUTF8( UTFstring( tname ) );
+ msg_Dbg( &sys.demuxer, "| | | + Track Name=%s", tk->fmt.psz_description );
+ }
+ else if( MKV_IS_ID( l, KaxTrackLanguage ) )
+ {
+ KaxTrackLanguage &lang = *(KaxTrackLanguage*)l;
+
+ if ( tk->fmt.psz_language != NULL )
+ free( tk->fmt.psz_language );
+ tk->fmt.psz_language = strdup( string( lang ).c_str() );
+ msg_Dbg( &sys.demuxer,
+ "| | | + Track Language=`%s'", tk->fmt.psz_language );
+ }
+ else if( MKV_IS_ID( l, KaxCodecID ) )
+ {
+ KaxCodecID &codecid = *(KaxCodecID*)l;
+
+ tk->psz_codec = strdup( string( codecid ).c_str() );
+ msg_Dbg( &sys.demuxer, "| | | + Track CodecId=%s", string( codecid ).c_str() );
+ }
+ else if( MKV_IS_ID( l, KaxCodecPrivate ) )
+ {
+ KaxCodecPrivate &cpriv = *(KaxCodecPrivate*)l;
+
+ tk->i_extra_data = cpriv.GetSize();
+ if( tk->i_extra_data > 0 )
+ {
+ tk->p_extra_data = (uint8_t*)malloc( tk->i_extra_data );
+ memcpy( tk->p_extra_data, cpriv.GetBuffer(), tk->i_extra_data );
+ }
+ msg_Dbg( &sys.demuxer, "| | | + Track CodecPrivate size="I64Fd, cpriv.GetSize() );
+ }
+ else if( MKV_IS_ID( l, KaxCodecName ) )
+ {
+ KaxCodecName &cname = *(KaxCodecName*)l;
+
+ tk->psz_codec_name = ToUTF8( UTFstring( cname ) );
+ msg_Dbg( &sys.demuxer, "| | | + Track Codec Name=%s", tk->psz_codec_name );
+ }
+ else if( MKV_IS_ID( l, KaxContentEncodings ) )
+ {
+ EbmlMaster *cencs = static_cast<EbmlMaster*>(l);
+ MkvTree( sys.demuxer, 3, "Content Encodings" );
+ if ( cencs->ListSize() > 1 )
+ {
+ msg_Err( &sys.demuxer, "Multiple Compression method not supported" );
+ bSupported = false;
+ }
+ for( j = 0; j < cencs->ListSize(); j++ )
+ {
+ EbmlElement *l2 = (*cencs)[j];
+ if( MKV_IS_ID( l2, KaxContentEncoding ) )
+ {
+ MkvTree( sys.demuxer, 4, "Content Encoding" );
+ EbmlMaster *cenc = static_cast<EbmlMaster*>(l2);
+ for( k = 0; k < cenc->ListSize(); k++ )
+ {
+ EbmlElement *l3 = (*cenc)[k];
+ if( MKV_IS_ID( l3, KaxContentEncodingOrder ) )
+ {
+ KaxContentEncodingOrder &encord = *(KaxContentEncodingOrder*)l3;
+ MkvTree( sys.demuxer, 5, "Order: %i", uint32( encord ) );
+ }
+ else if( MKV_IS_ID( l3, KaxContentEncodingScope ) )
+ {
+ KaxContentEncodingScope &encscope = *(KaxContentEncodingScope*)l3;
+ MkvTree( sys.demuxer, 5, "Scope: %i", uint32( encscope ) );
+ }
+ else if( MKV_IS_ID( l3, KaxContentEncodingType ) )
+ {
+ KaxContentEncodingType &enctype = *(KaxContentEncodingType*)l3;
+ MkvTree( sys.demuxer, 5, "Type: %i", uint32( enctype ) );
+ }
+ else if( MKV_IS_ID( l3, KaxContentCompression ) )
+ {
+ EbmlMaster *compr = static_cast<EbmlMaster*>(l3);
+ MkvTree( sys.demuxer, 5, "Content Compression" );
+ for( n = 0; n < compr->ListSize(); n++ )
+ {
+ EbmlElement *l4 = (*compr)[n];
+ if( MKV_IS_ID( l4, KaxContentCompAlgo ) )
+ {
+ KaxContentCompAlgo &compalg = *(KaxContentCompAlgo*)l4;
+ MkvTree( sys.demuxer, 6, "Compression Algorithm: %i", uint32(compalg) );
+ tk->i_compression_type = uint32( compalg );
+ if ( ( tk->i_compression_type != MATROSKA_COMPRESSION_ZLIB ) &&
+ ( tk->i_compression_type != MATROSKA_COMPRESSION_HEADER ) )
+ {
+ msg_Err( &sys.demuxer, "Track Compression method %d not supported", tk->i_compression_type );
+ bSupported = false;
+ }
+ }
+ else if( MKV_IS_ID( l4, KaxContentCompSettings ) )
+ {
+ tk->p_compression_data = new KaxContentCompSettings( *(KaxContentCompSettings*)l4 );
+ }
+ else
+ {
+ MkvTree( sys.demuxer, 6, "Unknown (%s)", typeid(*l4).name() );
+ }
+ }
+ }
+ else
+ {
+ MkvTree( sys.demuxer, 5, "Unknown (%s)", typeid(*l3).name() );
+ }
+ }
+ }
+ else
+ {
+ MkvTree( sys.demuxer, 4, "Unknown (%s)", typeid(*l2).name() );
+ }
+ }
+ }
+// else if( EbmlId( *l ) == KaxCodecSettings::ClassInfos.GlobalId )
+// {
+// KaxCodecSettings &cset = *(KaxCodecSettings*)l;
+
+// tk->psz_codec_settings = ToUTF8( UTFstring( cset ) );
+// msg_Dbg( &sys.demuxer, "| | | + Track Codec Settings=%s", tk->psz_codec_settings );
+// }
+// else if( EbmlId( *l ) == KaxCodecInfoURL::ClassInfos.GlobalId )
+// {
+// KaxCodecInfoURL &ciurl = *(KaxCodecInfoURL*)l;
+
+// tk->psz_codec_info_url = strdup( string( ciurl ).c_str() );
+// msg_Dbg( &sys.demuxer, "| | | + Track Codec Info URL=%s", tk->psz_codec_info_url );
+// }
+// else if( EbmlId( *l ) == KaxCodecDownloadURL::ClassInfos.GlobalId )
+// {
+// KaxCodecDownloadURL &cdurl = *(KaxCodecDownloadURL*)l;
+
+// tk->psz_codec_download_url = strdup( string( cdurl ).c_str() );
+// msg_Dbg( &sys.demuxer, "| | | + Track Codec Info URL=%s", tk->psz_codec_download_url );
+// }
+// else if( EbmlId( *l ) == KaxCodecDecodeAll::ClassInfos.GlobalId )
+// {
+// KaxCodecDecodeAll &cdall = *(KaxCodecDecodeAll*)l;
+
+// msg_Dbg( &sys.demuxer, "| | | + Track Codec Decode All=%u <== UNUSED", uint8( cdall ) );
+// }
+// else if( EbmlId( *l ) == KaxTrackOverlay::ClassInfos.GlobalId )
+// {
+// KaxTrackOverlay &tovr = *(KaxTrackOverlay*)l;
+
+// msg_Dbg( &sys.demuxer, "| | | + Track Overlay=%u <== UNUSED", uint32( tovr ) );
+// }
+ else if( MKV_IS_ID( l, KaxTrackVideo ) )
+ {
+ EbmlMaster *tkv = static_cast<EbmlMaster*>(l);
+ unsigned int j;
+ unsigned int i_crop_right = 0, i_crop_left = 0, i_crop_top = 0, i_crop_bottom = 0;
+ unsigned int i_display_unit = 0, i_display_width = 0, i_display_height = 0;
+
+ msg_Dbg( &sys.demuxer, "| | | + Track Video" );
+ tk->f_fps = 0.0;
+
+ tk->fmt.video.i_frame_rate_base = (unsigned int)(tk->i_default_duration / 1000);
+ tk->fmt.video.i_frame_rate = 1000000;
+
+ for( j = 0; j < tkv->ListSize(); j++ )
+ {
+ EbmlElement *l = (*tkv)[j];
+// if( EbmlId( *el4 ) == KaxVideoFlagInterlaced::ClassInfos.GlobalId )
+// {
+// KaxVideoFlagInterlaced &fint = *(KaxVideoFlagInterlaced*)el4;
+
+// msg_Dbg( &sys.demuxer, "| | | | + Track Video Interlaced=%u", uint8( fint ) );
+// }
+// else if( EbmlId( *el4 ) == KaxVideoStereoMode::ClassInfos.GlobalId )
+// {
+// KaxVideoStereoMode &stereo = *(KaxVideoStereoMode*)el4;
+
+// msg_Dbg( &sys.demuxer, "| | | | + Track Video Stereo Mode=%u", uint8( stereo ) );
+// }
+// else
+ if( MKV_IS_ID( l, KaxVideoPixelWidth ) )
+ {
+ KaxVideoPixelWidth &vwidth = *(KaxVideoPixelWidth*)l;
+
+ tk->fmt.video.i_width += uint16( vwidth );
+ msg_Dbg( &sys.demuxer, "| | | | + width=%d", uint16( vwidth ) );
+ }
+ else if( MKV_IS_ID( l, KaxVideoPixelHeight ) )
+ {
+ KaxVideoPixelWidth &vheight = *(KaxVideoPixelWidth*)l;
+
+ tk->fmt.video.i_height += uint16( vheight );
+ msg_Dbg( &sys.demuxer, "| | | | + height=%d", uint16( vheight ) );
+ }
+ else if( MKV_IS_ID( l, KaxVideoDisplayWidth ) )
+ {
+ KaxVideoDisplayWidth &vwidth = *(KaxVideoDisplayWidth*)l;
+
+ i_display_width = uint16( vwidth );
+ msg_Dbg( &sys.demuxer, "| | | | + display width=%d", uint16( vwidth ) );
+ }
+ else if( MKV_IS_ID( l, KaxVideoDisplayHeight ) )
+ {
+ KaxVideoDisplayWidth &vheight = *(KaxVideoDisplayWidth*)l;
+
+ i_display_height = uint16( vheight );
+ msg_Dbg( &sys.demuxer, "| | | | + display height=%d", uint16( vheight ) );
+ }
+ else if( MKV_IS_ID( l, KaxVideoPixelCropBottom ) )
+ {
+ KaxVideoPixelCropBottom &cropval = *(KaxVideoPixelCropBottom*)l;
+
+ i_crop_bottom = uint16( cropval );
+ msg_Dbg( &sys.demuxer, "| | | | + crop pixel bottom=%d", uint16( cropval ) );
+ }
+ else if( MKV_IS_ID( l, KaxVideoPixelCropTop ) )
+ {
+ KaxVideoPixelCropTop &cropval = *(KaxVideoPixelCropTop*)l;
+
+ i_crop_top = uint16( cropval );
+ msg_Dbg( &sys.demuxer, "| | | | + crop pixel top=%d", uint16( cropval ) );
+ }
+ else if( MKV_IS_ID( l, KaxVideoPixelCropRight ) )
+ {
+ KaxVideoPixelCropRight &cropval = *(KaxVideoPixelCropRight*)l;
+
+ i_crop_right = uint16( cropval );
+ msg_Dbg( &sys.demuxer, "| | | | + crop pixel right=%d", uint16( cropval ) );
+ }
+ else if( MKV_IS_ID( l, KaxVideoPixelCropLeft ) )
+ {
+ KaxVideoPixelCropLeft &cropval = *(KaxVideoPixelCropLeft*)l;
+
+ i_crop_left = uint16( cropval );
+ msg_Dbg( &sys.demuxer, "| | | | + crop pixel left=%d", uint16( cropval ) );
+ }
+ else if( MKV_IS_ID( l, KaxVideoFrameRate ) )
+ {
+ KaxVideoFrameRate &vfps = *(KaxVideoFrameRate*)l;
+
+ tk->f_fps = float( vfps );
+ msg_Dbg( &sys.demuxer, " | | | + fps=%f", float( vfps ) );
+ }
+ else if( EbmlId( *l ) == KaxVideoDisplayUnit::ClassInfos.GlobalId )
+ {
+ KaxVideoDisplayUnit &vdmode = *(KaxVideoDisplayUnit*)l;
+
+ i_display_unit = uint8( vdmode );
+ msg_Dbg( &sys.demuxer, "| | | | + Track Video Display Unit=%s",
+ uint8( vdmode ) == 0 ? "pixels" : ( uint8( vdmode ) == 1 ? "centimeters": "inches" ) );
+ }
+// else if( EbmlId( *l ) == KaxVideoAspectRatio::ClassInfos.GlobalId )
+// {
+// KaxVideoAspectRatio &ratio = *(KaxVideoAspectRatio*)l;
+
+// msg_Dbg( &sys.demuxer, " | | | + Track Video Aspect Ratio Type=%u", uint8( ratio ) );
+// }
+// else if( EbmlId( *l ) == KaxVideoGamma::ClassInfos.GlobalId )
+// {
+// KaxVideoGamma &gamma = *(KaxVideoGamma*)l;
+
+// msg_Dbg( &sys.demuxer, " | | | + gamma=%f", float( gamma ) );
+// }
+ else
+ {
+ msg_Dbg( &sys.demuxer, "| | | | + Unknown (%s)", typeid(*l).name() );
+ }
+ }
+ if( i_display_height && i_display_width )
+ tk->fmt.video.i_aspect = VOUT_ASPECT_FACTOR * i_display_width / i_display_height;
+ if( i_crop_left || i_crop_right || i_crop_top || i_crop_bottom )
+ {
+ tk->fmt.video.i_visible_width = tk->fmt.video.i_width;
+ tk->fmt.video.i_visible_height = tk->fmt.video.i_height;
+ tk->fmt.video.i_x_offset = i_crop_left;
+ tk->fmt.video.i_y_offset = i_crop_top;
+ tk->fmt.video.i_visible_width -= i_crop_left + i_crop_right;
+ tk->fmt.video.i_visible_height -= i_crop_top + i_crop_bottom;
+ }
+ /* FIXME: i_display_* allows you to not only set DAR, but also a zoom factor.
+ we do not support this atm */
+ }
+ else if( MKV_IS_ID( l, KaxTrackAudio ) )
+ {
+ EbmlMaster *tka = static_cast<EbmlMaster*>(l);
+ unsigned int j;
+
+ msg_Dbg( &sys.demuxer, "| | | + Track Audio" );
+
+ for( j = 0; j < tka->ListSize(); j++ )
+ {
+ EbmlElement *l = (*tka)[j];
+
+ if( MKV_IS_ID( l, KaxAudioSamplingFreq ) )
+ {
+ KaxAudioSamplingFreq &afreq = *(KaxAudioSamplingFreq*)l;
+
+ tk->i_original_rate = tk->fmt.audio.i_rate = (int)float( afreq );
+ msg_Dbg( &sys.demuxer, "| | | | + afreq=%d", tk->fmt.audio.i_rate );
+ }
+ else if( MKV_IS_ID( l, KaxAudioOutputSamplingFreq ) )
+ {
+ KaxAudioOutputSamplingFreq &afreq = *(KaxAudioOutputSamplingFreq*)l;
+
+ tk->fmt.audio.i_rate = (int)float( afreq );
+ msg_Dbg( &sys.demuxer, "| | | | + aoutfreq=%d", tk->fmt.audio.i_rate );
+ }
+ else if( MKV_IS_ID( l, KaxAudioChannels ) )
+ {
+ KaxAudioChannels &achan = *(KaxAudioChannels*)l;
+
+ tk->fmt.audio.i_channels = uint8( achan );
+ msg_Dbg( &sys.demuxer, "| | | | + achan=%u", uint8( achan ) );
+ }
+ else if( MKV_IS_ID( l, KaxAudioBitDepth ) )
+ {
+ KaxAudioBitDepth &abits = *(KaxAudioBitDepth*)l;
+
+ tk->fmt.audio.i_bitspersample = uint8( abits );
+ msg_Dbg( &sys.demuxer, "| | | | + abits=%u", uint8( abits ) );
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, "| | | | + Unknown (%s)", typeid(*l).name() );
+ }
+ }
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, "| | | + Unknown (%s)",
+ typeid(*l).name() );
+ }
+ }
+
+ if ( bSupported )
+ {
+ tracks.push_back( tk );
+ }
+ else
+ {
+ msg_Err( &sys.demuxer, "Track Entry %d not supported", tk->i_number );
+ delete tk;
+ }
+}
+
+/*****************************************************************************
+ * ParseTracks:
+ *****************************************************************************/
+void matroska_segment_c::ParseTracks( KaxTracks *tracks )
+{
+ EbmlElement *el;
+ unsigned int i;
+ int i_upper_level = 0;
+
+ msg_Dbg( &sys.demuxer, "| + Tracks" );
+
+ /* Master elements */
+ tracks->Read( es, tracks->Generic().Context, i_upper_level, el, true );
+
+ for( i = 0; i < tracks->ListSize(); i++ )
+ {
+ EbmlElement *l = (*tracks)[i];
+
+ if( MKV_IS_ID( l, KaxTrackEntry ) )
+ {
+ ParseTrackEntry( static_cast<KaxTrackEntry *>(l) );
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid(*l).name() );
+ }
+ }
+}
+
+/*****************************************************************************
+ * ParseInfo:
+ *****************************************************************************/
+void matroska_segment_c::ParseInfo( KaxInfo *info )
+{
+ EbmlElement *el;
+ EbmlMaster *m;
+ size_t i, j;
+ int i_upper_level = 0;
+
+ msg_Dbg( &sys.demuxer, "| + Information" );
+
+ /* Master elements */
+ m = static_cast<EbmlMaster *>(info);
+ m->Read( es, info->Generic().Context, i_upper_level, el, true );
+
+ for( i = 0; i < m->ListSize(); i++ )
+ {
+ EbmlElement *l = (*m)[i];
+
+ if( MKV_IS_ID( l, KaxSegmentUID ) )
+ {
+ if ( p_segment_uid == NULL )
+ p_segment_uid = new KaxSegmentUID(*static_cast<KaxSegmentUID*>(l));
+
+ msg_Dbg( &sys.demuxer, "| | + UID=%d", *(uint32*)p_segment_uid->GetBuffer() );
+ }
+ else if( MKV_IS_ID( l, KaxPrevUID ) )
+ {
+ if ( p_prev_segment_uid == NULL )
+ p_prev_segment_uid = new KaxPrevUID(*static_cast<KaxPrevUID*>(l));
+
+ msg_Dbg( &sys.demuxer, "| | + PrevUID=%d", *(uint32*)p_prev_segment_uid->GetBuffer() );
+ }
+ else if( MKV_IS_ID( l, KaxNextUID ) )
+ {
+ if ( p_next_segment_uid == NULL )
+ p_next_segment_uid = new KaxNextUID(*static_cast<KaxNextUID*>(l));
+
+ msg_Dbg( &sys.demuxer, "| | + NextUID=%d", *(uint32*)p_next_segment_uid->GetBuffer() );
+ }
+ else if( MKV_IS_ID( l, KaxTimecodeScale ) )
+ {
+ KaxTimecodeScale &tcs = *(KaxTimecodeScale*)l;
+
+ i_timescale = uint64(tcs);
+
+ msg_Dbg( &sys.demuxer, "| | + TimecodeScale="I64Fd,
+ i_timescale );
+ }
+ else if( MKV_IS_ID( l, KaxDuration ) )
+ {
+ KaxDuration &dur = *(KaxDuration*)l;
+
+ i_duration = mtime_t( double( dur ) );
+
+ msg_Dbg( &sys.demuxer, "| | + Duration="I64Fd,
+ i_duration );
+ }
+ else if( MKV_IS_ID( l, KaxMuxingApp ) )
+ {
+ KaxMuxingApp &mapp = *(KaxMuxingApp*)l;
+
+ psz_muxing_application = ToUTF8( UTFstring( mapp ) );
+
+ msg_Dbg( &sys.demuxer, "| | + Muxing Application=%s",
+ psz_muxing_application );
+ }
+ else if( MKV_IS_ID( l, KaxWritingApp ) )
+ {
+ KaxWritingApp &wapp = *(KaxWritingApp*)l;
+
+ psz_writing_application = ToUTF8( UTFstring( wapp ) );
+
+ msg_Dbg( &sys.demuxer, "| | + Writing Application=%s",
+ psz_writing_application );
+ }
+ else if( MKV_IS_ID( l, KaxSegmentFilename ) )
+ {
+ KaxSegmentFilename &sfn = *(KaxSegmentFilename*)l;
+
+ psz_segment_filename = ToUTF8( UTFstring( sfn ) );
+
+ msg_Dbg( &sys.demuxer, "| | + Segment Filename=%s",
+ psz_segment_filename );
+ }
+ else if( MKV_IS_ID( l, KaxTitle ) )
+ {
+ KaxTitle &title = *(KaxTitle*)l;
+
+ psz_title = ToUTF8( UTFstring( title ) );
+
+ msg_Dbg( &sys.demuxer, "| | + Title=%s", psz_title );
+ }
+ else if( MKV_IS_ID( l, KaxSegmentFamily ) )
+ {
+ KaxSegmentFamily *uid = static_cast<KaxSegmentFamily*>(l);
+
+ families.push_back( new KaxSegmentFamily(*uid) );
+
+ msg_Dbg( &sys.demuxer, "| | + family=%d", *(uint32*)uid->GetBuffer() );
+ }
+#if defined( HAVE_GMTIME_R ) && !defined( __APPLE__ )
+ else if( MKV_IS_ID( l, KaxDateUTC ) )
+ {
+ KaxDateUTC &date = *(KaxDateUTC*)l;
+ time_t i_date;
+ struct tm tmres;
+ char buffer[256];
+
+ i_date = date.GetEpochDate();
+ memset( buffer, 0, 256 );
+ if( gmtime_r( &i_date, &tmres ) &&
+ asctime_r( &tmres, buffer ) )
+ {
+ buffer[strlen( buffer)-1]= '\0';
+ psz_date_utc = strdup( buffer );
+ msg_Dbg( &sys.demuxer, "| | + Date=%s", psz_date_utc );
+ }
+ }
+#endif
+#if LIBMATROSKA_VERSION >= 0x000704
+ else if( MKV_IS_ID( l, KaxChapterTranslate ) )
+ {
+ KaxChapterTranslate *p_trans = static_cast<KaxChapterTranslate*>( l );
+ chapter_translation_c *p_translate = new chapter_translation_c();
+
+ p_trans->Read( es, p_trans->Generic().Context, i_upper_level, el, true );
+ for( j = 0; j < p_trans->ListSize(); j++ )
+ {
+ EbmlElement *l = (*p_trans)[j];
+
+ if( MKV_IS_ID( l, KaxChapterTranslateEditionUID ) )
+ {
+ p_translate->editions.push_back( uint64( *static_cast<KaxChapterTranslateEditionUID*>( l ) ) );
+ }
+ else if( MKV_IS_ID( l, KaxChapterTranslateCodec ) )
+ {
+ p_translate->codec_id = uint32( *static_cast<KaxChapterTranslateCodec*>( l ) );
+ }
+ else if( MKV_IS_ID( l, KaxChapterTranslateID ) )
+ {
+ p_translate->p_translated = new KaxChapterTranslateID( *static_cast<KaxChapterTranslateID*>( l ) );
+ }
+ }
+
+ translations.push_back( p_translate );
+ }
+#endif
+ else
+ {
+ msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid(*l).name() );
+ }
+ }
+
+ double f_dur = double(i_duration) * double(i_timescale) / 1000000.0;
+ i_duration = mtime_t(f_dur);
+}
+
+
+/*****************************************************************************
+ * ParseChapterAtom
+ *****************************************************************************/
+void matroska_segment_c::ParseChapterAtom( int i_level, KaxChapterAtom *ca, chapter_item_c & chapters )
+{
+ size_t i, j;
+
+ msg_Dbg( &sys.demuxer, "| | | + ChapterAtom (level=%d)", i_level );
+ for( i = 0; i < ca->ListSize(); i++ )
+ {
+ EbmlElement *l = (*ca)[i];
+
+ if( MKV_IS_ID( l, KaxChapterUID ) )
+ {
+ chapters.i_uid = uint64_t(*(KaxChapterUID*)l);
+ msg_Dbg( &sys.demuxer, "| | | | + ChapterUID: %lld", chapters.i_uid );
+ }
+ else if( MKV_IS_ID( l, KaxChapterFlagHidden ) )
+ {
+ KaxChapterFlagHidden &flag =*(KaxChapterFlagHidden*)l;
+ chapters.b_display_seekpoint = uint8( flag ) == 0;
+
+ msg_Dbg( &sys.demuxer, "| | | | + ChapterFlagHidden: %s", chapters.b_display_seekpoint ? "no":"yes" );
+ }
+ else if( MKV_IS_ID( l, KaxChapterTimeStart ) )
+ {
+ KaxChapterTimeStart &start =*(KaxChapterTimeStart*)l;
+ chapters.i_start_time = uint64( start ) / I64C(1000);
+
+ msg_Dbg( &sys.demuxer, "| | | | + ChapterTimeStart: %lld", chapters.i_start_time );
+ }
+ else if( MKV_IS_ID( l, KaxChapterTimeEnd ) )
+ {
+ KaxChapterTimeEnd &end =*(KaxChapterTimeEnd*)l;
+ chapters.i_end_time = uint64( end ) / I64C(1000);
+
+ msg_Dbg( &sys.demuxer, "| | | | + ChapterTimeEnd: %lld", chapters.i_end_time );
+ }
+ else if( MKV_IS_ID( l, KaxChapterDisplay ) )
+ {
+ EbmlMaster *cd = static_cast<EbmlMaster *>(l);
+
+ msg_Dbg( &sys.demuxer, "| | | | + ChapterDisplay" );
+ for( j = 0; j < cd->ListSize(); j++ )
+ {
+ EbmlElement *l= (*cd)[j];
+
+ if( MKV_IS_ID( l, KaxChapterString ) )
+ {
+ int k;
+
+ KaxChapterString &name =*(KaxChapterString*)l;
+ for (k = 0; k < i_level; k++)
+ chapters.psz_name += '+';
+ chapters.psz_name += ' ';
+ char *psz_tmp_utf8 = ToUTF8( UTFstring( name ) );
+ chapters.psz_name += psz_tmp_utf8;
+ chapters.b_user_display = true;
+
+ msg_Dbg( &sys.demuxer, "| | | | | + ChapterString '%s'", psz_tmp_utf8 );
+ free( psz_tmp_utf8 );
+ }
+ else if( MKV_IS_ID( l, KaxChapterLanguage ) )
+ {
+ KaxChapterLanguage &lang =*(KaxChapterLanguage*)l;
+ const char *psz = string( lang ).c_str();
+
+ msg_Dbg( &sys.demuxer, "| | | | | + ChapterLanguage '%s'", psz );
+ }
+ else if( MKV_IS_ID( l, KaxChapterCountry ) )
+ {
+ KaxChapterCountry &ct =*(KaxChapterCountry*)l;
+ const char *psz = string( ct ).c_str();
+
+ msg_Dbg( &sys.demuxer, "| | | | | + ChapterCountry '%s'", psz );
+ }
+ }
+ }
+ else if( MKV_IS_ID( l, KaxChapterProcess ) )
+ {
+ msg_Dbg( &sys.demuxer, "| | | | + ChapterProcess" );
+
+ KaxChapterProcess *cp = static_cast<KaxChapterProcess *>(l);
+ chapter_codec_cmds_c *p_ccodec = NULL;
+
+ for( j = 0; j < cp->ListSize(); j++ )
+ {
+ EbmlElement *k= (*cp)[j];
+
+ if( MKV_IS_ID( k, KaxChapterProcessCodecID ) )
+ {
+ KaxChapterProcessCodecID *p_codec_id = static_cast<KaxChapterProcessCodecID*>( k );
+ if ( uint32(*p_codec_id) == 0 )
+ p_ccodec = new matroska_script_codec_c( sys );
+ else if ( uint32(*p_codec_id) == 1 )
+ p_ccodec = new dvd_chapter_codec_c( sys );
+ break;
+ }
+ }
+
+ if ( p_ccodec != NULL )
+ {
+ for( j = 0; j < cp->ListSize(); j++ )
+ {
+ EbmlElement *k= (*cp)[j];
+
+ if( MKV_IS_ID( k, KaxChapterProcessPrivate ) )
+ {
+ KaxChapterProcessPrivate * p_private = static_cast<KaxChapterProcessPrivate*>( k );
+ p_ccodec->SetPrivate( *p_private );
+ }
+ else if( MKV_IS_ID( k, KaxChapterProcessCommand ) )
+ {
+ p_ccodec->AddCommand( *static_cast<KaxChapterProcessCommand*>( k ) );
+ }
+ }
+ chapters.codecs.push_back( p_ccodec );
+ }
+ }
+ else if( MKV_IS_ID( l, KaxChapterAtom ) )
+ {
+ chapter_item_c *new_sub_chapter = new chapter_item_c();
+ ParseChapterAtom( i_level+1, static_cast<KaxChapterAtom *>(l), *new_sub_chapter );
+ new_sub_chapter->psz_parent = &chapters;
+ chapters.sub_chapters.push_back( new_sub_chapter );
+ }
+ }
+}
+
+/*****************************************************************************
+ * ParseAttachments:
+ *****************************************************************************/
+void matroska_segment_c::ParseAttachments( KaxAttachments *attachments )
+{
+ EbmlElement *el;
+ int i_upper_level = 0;
+
+ attachments->Read( es, attachments->Generic().Context, i_upper_level, el, true );
+
+ KaxAttached *attachedFile = FindChild<KaxAttached>( *attachments );
+
+ while( attachedFile && ( attachedFile->GetSize() > 0 ) )
+ {
+ std::string psz_mime_type = GetChild<KaxMimeType>( *attachedFile );
+ KaxFileName &file_name = GetChild<KaxFileName>( *attachedFile );
+ KaxFileData &img_data = GetChild<KaxFileData>( *attachedFile );
+
+ attachment_c *new_attachment = new attachment_c();
+
+ if( new_attachment )
+ {
+ new_attachment->psz_file_name = ToUTF8( UTFstring( file_name ) );
+ new_attachment->psz_mime_type = psz_mime_type;
+ new_attachment->i_size = img_data.GetSize();
+ new_attachment->p_data = malloc( img_data.GetSize() );
+
+ if( new_attachment->p_data )
+ {
+ memcpy( new_attachment->p_data, img_data.GetBuffer(), img_data.GetSize() );
+ sys.stored_attachments.push_back( new_attachment );
+ }
+ else
+ {
+ delete new_attachment;
+ }
+ }
+
+ attachedFile = &GetNextChild<KaxAttached>( *attachments, *attachedFile );
+ }
+}
+
+/*****************************************************************************
+ * ParseChapters:
+ *****************************************************************************/
+void matroska_segment_c::ParseChapters( KaxChapters *chapters )
+{
+ EbmlElement *el;
+ size_t i;
+ int i_upper_level = 0;
+ mtime_t i_dur;
+
+ /* Master elements */
+ chapters->Read( es, chapters->Generic().Context, i_upper_level, el, true );
+
+ for( i = 0; i < chapters->ListSize(); i++ )
+ {
+ EbmlElement *l = (*chapters)[i];
+
+ if( MKV_IS_ID( l, KaxEditionEntry ) )
+ {
+ chapter_edition_c *p_edition = new chapter_edition_c();
+
+ EbmlMaster *E = static_cast<EbmlMaster *>(l );
+ size_t j;
+ msg_Dbg( &sys.demuxer, "| | + EditionEntry" );
+ for( j = 0; j < E->ListSize(); j++ )
+ {
+ EbmlElement *l = (*E)[j];
+
+ if( MKV_IS_ID( l, KaxChapterAtom ) )
+ {
+ chapter_item_c *new_sub_chapter = new chapter_item_c();
+ ParseChapterAtom( 0, static_cast<KaxChapterAtom *>(l), *new_sub_chapter );
+ p_edition->sub_chapters.push_back( new_sub_chapter );
+ }
+ else if( MKV_IS_ID( l, KaxEditionUID ) )
+ {
+ p_edition->i_uid = uint64(*static_cast<KaxEditionUID *>( l ));
+ }
+ else if( MKV_IS_ID( l, KaxEditionFlagOrdered ) )
+ {
+ p_edition->b_ordered = config_GetInt( &sys.demuxer, "mkv-use-ordered-chapters" ) ? (uint8(*static_cast<KaxEditionFlagOrdered *>( l )) != 0) : 0;
+ }
+ else if( MKV_IS_ID( l, KaxEditionFlagDefault ) )
+ {
+ if (uint8(*static_cast<KaxEditionFlagDefault *>( l )) != 0)
+ i_default_edition = stored_editions.size();
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, "| | | + Unknown (%s)", typeid(*l).name() );
+ }
+ }
+ stored_editions.push_back( p_edition );
+ }
+ else
+ {
+ msg_Dbg( &sys.demuxer, "| | + Unknown (%s)", typeid(*l).name() );
+ }
+ }
+
+ for( i = 0; i < stored_editions.size(); i++ )
+ {
+ stored_editions[i]->RefreshChapters( );
+ }
+
+ if ( stored_editions.size() != 0 && stored_editions[i_default_edition]->b_ordered )
+ {
+ /* update the duration of the segment according to the sum of all sub chapters */
+ i_dur = stored_editions[i_default_edition]->Duration() / I64C(1000);
+ if (i_dur > 0)
+ i_duration = i_dur;
+ }
+}
+
+void matroska_segment_c::ParseCluster( )
+{
+ EbmlElement *el;
+ EbmlMaster *m;
+ unsigned int i;
+ int i_upper_level = 0;
+
+ /* Master elements */
+ m = static_cast<EbmlMaster *>( cluster );
+ m->Read( es, cluster->Generic().Context, i_upper_level, el, true );
+
+ for( i = 0; i < m->ListSize(); i++ )
+ {
+ EbmlElement *l = (*m)[i];
+
+ if( MKV_IS_ID( l, KaxClusterTimecode ) )
+ {
+ KaxClusterTimecode &ctc = *(KaxClusterTimecode*)l;
+
+ cluster->InitTimecode( uint64( ctc ), i_timescale );
+ break;
+ }
+ }
+
+ i_start_time = cluster->GlobalTimecode() / 1000;
+}
+
+/*****************************************************************************
+ * InformationCreate:
+ *****************************************************************************/
+void matroska_segment_c::InformationCreate( )
+{
+ sys.meta = vlc_meta_New();
+
+ if( psz_title )
+ {
+ vlc_meta_SetTitle( sys.meta, psz_title );
+ }
+ if( psz_date_utc )
+ {
+ vlc_meta_SetDate( sys.meta, psz_date_utc );
+ }
+#if 0
+ if( psz_segment_filename )
+ {
+ fprintf( stderr, "***** WARNING: Unhandled meta - Use custom\n" );
+ }
+ if( psz_muxing_application )
+ {
+ fprintf( stderr, "***** WARNING: Unhandled meta - Use custom\n" );
+ }
+ if( psz_writing_application )
+ {
+ fprintf( stderr, "***** WARNING: Unhandled meta - Use custom\n" );
+ }
+
+ for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
+ {
+// mkv_track_t *tk = tracks[i_track];
+// vlc_meta_t *mtk = vlc_meta_New();
+ fprintf( stderr, "***** WARNING: Unhandled child meta\n");
+ }
+#endif
+
+ if( i_tags_position >= 0 )
+ {
+ vlc_bool_t b_seekable;
+
+ stream_Control( sys.demuxer.s, STREAM_CAN_FASTSEEK, &b_seekable );
+ if( b_seekable )
+ {
+ LoadTags( );
+ }
+ }
+}
+
+
+/*****************************************************************************
+ * Divers
+ *****************************************************************************/
+
+void matroska_segment_c::IndexAppendCluster( KaxCluster *cluster )
+{
+#define idx p_indexes[i_index]
+ idx.i_track = -1;
+ idx.i_block_number= -1;
+ idx.i_position = cluster->GetElementPosition();
+ idx.i_time = -1;
+ idx.b_key = VLC_TRUE;
+
+ i_index++;
+ if( i_index >= i_index_max )
+ {
+ i_index_max += 1024;
+ p_indexes = (mkv_index_t*)realloc( p_indexes, sizeof( mkv_index_t ) * i_index_max );
+ }
+#undef idx
+}
+
+void chapter_edition_c::RefreshChapters( )
+{
+ chapter_item_c::RefreshChapters( b_ordered, -1 );
+ b_display_seekpoint = false;
+}
+
+int64_t chapter_item_c::RefreshChapters( bool b_ordered, int64_t i_prev_user_time )
+{
+ int64_t i_user_time = i_prev_user_time;
+
+ // first the sub-chapters, and then ourself
+ std::vector<chapter_item_c*>::iterator index = sub_chapters.begin();
+ while ( index != sub_chapters.end() )
+ {
+ i_user_time = (*index)->RefreshChapters( b_ordered, i_user_time );
+ index++;
+ }
+
+ if ( b_ordered )
+ {
+ // the ordered chapters always start at zero
+ if ( i_prev_user_time == -1 )
+ {
+ if ( i_user_time == -1 )
+ i_user_time = 0;
+ i_prev_user_time = 0;
+ }
+
+ i_user_start_time = i_prev_user_time;
+ if ( i_end_time != -1 && i_user_time == i_prev_user_time )
+ {
+ i_user_end_time = i_user_start_time - i_start_time + i_end_time;
+ }
+ else
+ {
+ i_user_end_time = i_user_time;
+ }
+ }
+ else
+ {
+ if ( sub_chapters.begin() != sub_chapters.end() )
+ std::sort( sub_chapters.begin(), sub_chapters.end(), chapter_item_c::CompareTimecode );
+ i_user_start_time = i_start_time;
+ if ( i_end_time != -1 )
+ i_user_end_time = i_end_time;
+ else if ( i_user_time != -1 )
+ i_user_end_time = i_user_time;
+ else
+ i_user_end_time = i_user_start_time;
+ }
+
+ return i_user_end_time;
+}
+
+mtime_t chapter_edition_c::Duration() const
+{
+ mtime_t i_result = 0;
+
+ if ( sub_chapters.size() )
+ {
+ std::vector<chapter_item_c*>::const_iterator index = sub_chapters.end();
+ index--;
+ i_result = (*index)->i_user_end_time;
+ }
+
+ return i_result;
+}
+
+chapter_item_c * chapter_edition_c::FindTimecode( mtime_t i_timecode, const chapter_item_c * p_current )
+{
+ if ( !b_ordered )
+ p_current = NULL;
+ bool b_found_current = false;
+ return chapter_item_c::FindTimecode( i_timecode, p_current, b_found_current );
+}
+
+chapter_item_c *chapter_item_c::FindTimecode( mtime_t i_user_timecode, const chapter_item_c * p_current, bool & b_found )
+{
+ chapter_item_c *psz_result = NULL;
+
+ if ( p_current == this )
+ b_found = true;
+
+ if ( i_user_timecode >= i_user_start_time &&
+ ( i_user_timecode < i_user_end_time ||
+ ( i_user_start_time == i_user_end_time && i_user_timecode == i_user_end_time )))
+ {
+ std::vector<chapter_item_c*>::iterator index = sub_chapters.begin();
+ while ( index != sub_chapters.end() && ((p_current == NULL && psz_result == NULL) || (p_current != NULL && (!b_found || psz_result == NULL))))
+ {
+ psz_result = (*index)->FindTimecode( i_user_timecode, p_current, b_found );
+ index++;
+ }
+
+ if ( psz_result == NULL )
+ psz_result = this;
+ }
+
+ return psz_result;
+}
+
+bool chapter_item_c::ParentOf( const chapter_item_c & item ) const
+{
+ if ( &item == this )
+ return true;
+
+ std::vector<chapter_item_c*>::const_iterator index = sub_chapters.begin();
+ while ( index != sub_chapters.end() )
+ {
+ if ( (*index)->ParentOf( item ) )
+ return true;
+ index++;
+ }
+
+ return false;
+}
+
+void demux_sys_t::PreloadFamily( const matroska_segment_c & of_segment )
+{
+ for (size_t i=0; i<opened_segments.size(); i++)
+ {
+ opened_segments[i]->PreloadFamily( of_segment );
+ }
+}
+bool matroska_segment_c::PreloadFamily( const matroska_segment_c & of_segment )
+{
+ if ( b_preloaded )
+ return false;
+
+ for (size_t i=0; i<families.size(); i++)
+ {
+ for (size_t j=0; j<of_segment.families.size(); j++)
+ {
+ if ( *(families[i]) == *(of_segment.families[j]) )
+ return Preload( );
+ }
+ }
+
+ return false;
+}