[vlc-devel] [PATCH] MKV: find the duration in the last Cluster when it's not in the Info header
Steve Lhomme
robux4 at gmail.com
Mon Feb 23 11:10:31 CET 2015
Here's the .patch file since you're having problems applying my patches.
On Mon, Feb 23, 2015 at 11:03 AM, Steve Lhomme <robux4 at gmail.com> wrote:
> Only on fast seeking sources
> Fixes #12724
>
> ---
> 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();
> };
>
>
> --
> 1.9.5.msysgit.0
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-MKV-find-the-duration-in-the-last-Cluster-when-it-s-.patch
Type: application/octet-stream
Size: 4780 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20150223/d8eee4ab/attachment.obj>
More information about the vlc-devel
mailing list