vlc | branch: master | Filip Roséen <[email protected]> | Fri Nov 4 16:47:08 2016 +0100| [46e632dd060e6f3f70679af83f3d9efb7a1be733] | committer: Thomas Guillem
demux/mkv: abort EnsureDuration on non-finite elements matroska_segment_c::EnsureDuration is used to calculate the duration for a stream which does not include the value as metadata. Given that the function potentially will have to run through the entire file in order to get the last timecode, these changes make sure that we abort if an element does not have a finite size. If an element, on the way, does not have a finite size we cannot simply jump over it, but have to parse it's entire contents (which might be an expensive operation). And most often when an element does not have a finite size, the media is being streamed. We however have an exception to infinite clusters that are referenced by a Cue, in which case we will try to parse it (to allow content saved from a live stream where the Cues refers to every cluster to have a duration). Signed-off-by: Steve Lhomme <[email protected]> Signed-off-by: Thomas Guillem <[email protected]> > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=46e632dd060e6f3f70679af83f3d9efb7a1be733 --- modules/demux/mkv/matroska_segment.cpp | 62 +++++++++++++++------------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/modules/demux/mkv/matroska_segment.cpp b/modules/demux/mkv/matroska_segment.cpp index b2323d7..016748b 100644 --- a/modules/demux/mkv/matroska_segment.cpp +++ b/modules/demux/mkv/matroska_segment.cpp @@ -687,7 +687,7 @@ bool matroska_segment_c::Preload( ) b_preloaded = true; - if( cluster && cluster->IsFiniteSize() ) + if( cluster ) EnsureDuration(); return true; @@ -981,61 +981,53 @@ void matroska_segment_c::EnsureDuration() bool b_seekable; - vlc_stream_Control( sys.demuxer.s, STREAM_CAN_FASTSEEK, &b_seekable ); - if ( !b_seekable ) + if( vlc_stream_Control( sys.demuxer.s, STREAM_CAN_FASTSEEK, &b_seekable ) || + !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; + uint64 i_last_cluster_pos = cluster->GetElementPosition(); // find the last Cluster from the Cues + if ( b_cues && _seeker._cluster_positions.size() ) - { i_last_cluster_pos = *_seeker._cluster_positions.rbegin(); - } + else if( !cluster->IsFiniteSize() ) + return; - // find the last Cluster manually - if ( !i_last_cluster_pos && cluster != NULL ) - { - es.I_O().setFilePointer( cluster->GetElementPosition(), seek_beginning ); + es.I_O().setFilePointer( i_last_cluster_pos, seek_beginning ); + + EbmlParser eparser ( &es, segment, &sys.demuxer, var_InheritBool( + &sys.demuxer, "mkv-use-dummy" ) ); - EbmlElement* el; - EbmlParser ep( &es, segment, &sys.demuxer, - var_InheritBool( &sys.demuxer, "mkv-use-dummy" ) ); + // locate the definitely last cluster in the stream - while( ( el = ep.Get() ) != NULL ) + while( EbmlElement* el = eparser.Get() ) + { + if( !el->IsFiniteSize() && el->GetElementPosition() != i_last_cluster_pos ) { - if ( MKV_IS_ID( el, KaxCluster ) ) - { - i_last_cluster_pos = el->GetElementPosition(); - } + es.I_O().setFilePointer( i_current_position, seek_beginning ); + return; } + + if( MKV_IS_ID( el, KaxCluster ) ) + i_last_cluster_pos = el->GetElementPosition(); } // find the last timecode in the Cluster - if ( i_last_cluster_pos ) - { - es.I_O().setFilePointer( i_last_cluster_pos, seek_beginning ); - - EbmlParser eparser ( - &es , segment, &sys.demuxer, var_InheritBool( &sys.demuxer, "mkv-use-dummy" ) ); - KaxCluster *p_last_cluster = static_cast<KaxCluster*>( eparser.Get() ); - if( p_last_cluster == NULL ) - return; + eparser.Reset( &sys.demuxer ); + es.I_O().setFilePointer( i_last_cluster_pos, seek_beginning ); - if( !ParseCluster( p_last_cluster, false, SCOPE_PARTIAL_DATA ) ) - return; - - if( p_last_cluster->IsFiniteSize() == false ) - { - es.I_O().setFilePointer( i_current_position, seek_beginning ); - return; - } + EbmlElement* el = eparser.Get(); + MKV_CHECKED_PTR_DECL( p_last_cluster, KaxCluster, el ); + if( p_last_cluster && + 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++ ) _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
