[vlc-commits] MKV: find the duration in the last Cluster when it' s not in the Info header
Steve Lhomme
git at videolan.org
Mon Feb 23 11:24:09 CET 2015
vlc | branch: master | Steve Lhomme <robux4 at gmail.com> | Mon Feb 23 11:02:26 2015 +0100| [16b3d6a450bb5c471a11fbb3e28e40284180e589] | committer: Jean-Baptiste Kempf
MKV: find the duration in the last Cluster when it's not in the Info header
Only on fast seeking sources
Close #12724
Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=16b3d6a450bb5c471a11fbb3e28e40284180e589
---
modules/demux/mkv/matroska_segment.cpp | 104 ++++++++++++++++++++++++++++++++
modules/demux/mkv/matroska_segment.hpp | 1 +
2 files changed, 105 insertions(+)
diff --git a/modules/demux/mkv/matroska_segment.cpp b/modules/demux/mkv/matroska_segment.cpp
index 966d6aa..78d7f94 100644
--- a/modules/demux/mkv/matroska_segment.cpp
+++ b/modules/demux/mkv/matroska_segment.cpp
@@ -743,6 +743,8 @@ bool matroska_segment_c::Preload( )
b_preloaded = true;
+ EnsureDuration();
+
return true;
}
@@ -1163,6 +1165,108 @@ void matroska_segment_c::ComputeTrackPriority()
}
}
+void matroska_segment_c::EnsureDuration()
+{
+ if ( i_duration > 0 )
+ return;
+
+ i_duration = -1;
+
+ bool b_seekable;
+
+ stream_Control( sys.demuxer.s, STREAM_CAN_FASTSEEK, &b_seekable );
+ if ( !b_seekable )
+ {
+ msg_Warn( &sys.demuxer, "could not look for the segment duration" );
+ return;
+ }
+
+ uint64 i_current_position = es.I_O().getFilePointer();
+ uint64 i_last_cluster_pos = 0;
+
+ // find the last Cluster from the Cues
+ if ( b_cues && i_index > 0 && p_indexes != NULL)
+ {
+ i_last_cluster_pos = p_indexes[i_index-1].i_position;
+ }
+
+ // find the last Cluster manually
+ if ( !i_last_cluster_pos && cluster != NULL )
+ {
+ EbmlElement *el;
+ EbmlParser *ep;
+
+ es.I_O().setFilePointer( cluster->GetElementPosition(), seek_beginning );
+ ep = new EbmlParser( &es , segment, &sys.demuxer );
+
+ while( ( el = ep->Get() ) != NULL )
+ {
+ if ( MKV_IS_ID( el, KaxCluster ) )
+ {
+ i_last_cluster_pos = el->GetElementPosition();
+ }
+ }
+
+ delete ep;
+ }
+
+ // find the last timecode in the Cluster
+ if ( i_last_cluster_pos )
+ {
+ EbmlParser *ep;
+
+ es.I_O().setFilePointer( i_last_cluster_pos, seek_beginning );
+ ep = new EbmlParser( &es , segment, &sys.demuxer );
+
+ KaxCluster *p_last_cluster = (KaxCluster *) ep->Get();
+ ParseCluster( p_last_cluster, false, SCOPE_PARTIAL_DATA );
+
+ // use the last block + duration
+ uint64 i_last_timecode = p_last_cluster->GlobalTimecode();
+ for( unsigned int i = 0; i < p_last_cluster->ListSize(); i++ )
+ {
+ EbmlElement *l = (*p_last_cluster)[i];
+
+ if( MKV_IS_ID( l, KaxSimpleBlock ) )
+ {
+ KaxSimpleBlock *block = (KaxSimpleBlock*)l;
+ block->SetParent( *p_last_cluster );
+ i_last_timecode = max(i_last_timecode, block->GlobalTimecode());
+ }
+ else if( MKV_IS_ID( l, KaxBlockGroup ) )
+ {
+ KaxBlockGroup *group = (KaxBlockGroup*)l;
+ uint64 i_group_timecode = 0;
+ for( unsigned int j = 0; j < group->ListSize(); j++ )
+ {
+ EbmlElement *l = (*group)[j];
+
+ if( MKV_IS_ID( l, KaxBlock ) )
+ {
+ KaxBlock *block = (KaxBlock*)l;
+ block->SetParent( *p_last_cluster );
+ i_group_timecode += block->GlobalTimecode();
+ }
+ else if( MKV_IS_ID( l, KaxBlockDuration ) )
+ {
+ KaxBlockDuration & dur = *(KaxBlockDuration*)l;
+ i_group_timecode += uint64( dur );
+ }
+ }
+ i_last_timecode = max(i_last_timecode, i_group_timecode);
+ }
+ }
+
+ i_duration = ( i_last_timecode - cluster->GlobalTimecode() ) / (mtime_t)1000000;
+ msg_Dbg( &sys.demuxer, " extracted Duration=%" PRId64, i_duration );
+
+ delete ep;
+ }
+
+ // get back to the reading position we were at before looking for a duration
+ es.I_O().setFilePointer( i_current_position, seek_beginning );
+}
+
bool matroska_segment_c::Select( mtime_t i_start_time )
{
/* add all es */
diff --git a/modules/demux/mkv/matroska_segment.hpp b/modules/demux/mkv/matroska_segment.hpp
index 3ef8e37..e29d8dd 100644
--- a/modules/demux/mkv/matroska_segment.hpp
+++ b/modules/demux/mkv/matroska_segment.hpp
@@ -163,6 +163,7 @@ private:
void IndexAppendCluster( KaxCluster *cluster );
int32_t TrackInit( mkv_track_t * p_tk );
void ComputeTrackPriority();
+ void EnsureDuration();
};
More information about the vlc-commits
mailing list