[vlc-commits] MKV: Fix seeking without cues
Denis Charmet
git at videolan.org
Wed Dec 28 01:17:24 CET 2011
vlc | branch: master | Denis Charmet <typx at dinauz.org> | Mon Dec 26 19:29:31 2011 +0100| [771748b4275712ab21dcb8d4b13f92a23dc45a9d] | committer: Jean-Baptiste Kempf
MKV: Fix seeking without cues
the demux generates its own cues while reading and when seeking.
This should also avoid crashes when seeking without cues.
Closes #5085 and #5712
Signed-off-by: Jean-Baptiste Kempf <jb at videolan.org>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=771748b4275712ab21dcb8d4b13f92a23dc45a9d
---
modules/demux/mkv/matroska_segment.cpp | 43 ++++++++++++++++---------------
modules/demux/mkv/mkv.cpp | 30 +++++++++------------
2 files changed, 35 insertions(+), 38 deletions(-)
diff --git a/modules/demux/mkv/matroska_segment.cpp b/modules/demux/mkv/matroska_segment.cpp
index 2bef45e..0415d95 100644
--- a/modules/demux/mkv/matroska_segment.cpp
+++ b/modules/demux/mkv/matroska_segment.cpp
@@ -427,7 +427,7 @@ void matroska_segment_c::IndexAppendCluster( KaxCluster *cluster )
idx.i_track = -1;
idx.i_block_number= -1;
idx.i_position = cluster->GetElementPosition();
- idx.i_time = -1;
+ idx.i_time = cluster->GlobalTimecode()/ (mtime_t) 1000;
idx.b_key = true;
i_index++;
@@ -668,8 +668,9 @@ bool matroska_segment_c::LoadSeekHeadItem( const EbmlCallbacks & ClassInfos, int
struct spoint
{
- spoint(unsigned int tk): i_track(tk),i_date(0), i_seek_pos(0), i_cluster_pos(0),
- p_next(NULL){}
+ spoint(unsigned int tk, mtime_t date, int64_t pos, int64_t cpos):
+ i_track(tk),i_date(date), i_seek_pos(pos),
+ i_cluster_pos(cpos), p_next(NULL){}
unsigned int i_track;
mtime_t i_date;
int64_t i_seek_pos;
@@ -693,7 +694,13 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_
{
/* Special case for seeking in files with no cues */
EbmlElement *el = NULL;
- es.I_O().setFilePointer( i_start_pos, seek_beginning );
+
+ /* Start from the last known index instead of the beginning eachtime */
+ if( i_index == 0)
+ es.I_O().setFilePointer( i_start_pos, seek_beginning );
+ else
+ es.I_O().setFilePointer( p_indexes[ i_index - 1 ].i_position,
+ seek_beginning );
delete ep;
ep = new EbmlParser( &es, segment, &sys.demuxer );
cluster = NULL;
@@ -705,20 +712,16 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_
cluster = (KaxCluster *)el;
i_cluster_pos = cluster->GetElementPosition();
if( i_index == 0 ||
- ( i_index > 0 && p_indexes[i_index - 1].i_position < (int64_t)cluster->GetElementPosition() ) )
+ ( i_index > 0 &&
+ p_indexes[i_index - 1].i_position < (int64_t)cluster->GetElementPosition() ) )
{
+ ParseCluster();
IndexAppendCluster( cluster );
}
if( es.I_O().getFilePointer() >= (unsigned) i_global_position )
- {
- ParseCluster();
- msg_Dbg( &sys.demuxer, "we found a cluster that is in the neighbourhood" );
- return;
- }
+ break;
}
}
- msg_Err( &sys.demuxer, "This file has no cues, and we were unable to seek to the requested position by parsing." );
- return;
}
/* Don't try complex seek if we seek to 0 */
@@ -766,7 +769,7 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_
{
if( tracks[i_track]->fmt.i_cat == VIDEO_ES )
{
- spoint * seekpoint = new spoint(i_track);
+ spoint * seekpoint = new spoint(i_track, i_seek_time, i_seek_position, i_seek_position);
if( unlikely( !seekpoint ) )
{
for( spoint * sp = p_first; sp; )
@@ -813,7 +816,6 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_
i_pts = sys.i_chapter_time + simpleblock->GlobalTimecode() / (mtime_t) 1000;
else
i_pts = sys.i_chapter_time + block->GlobalTimecode() / (mtime_t) 1000;
-
if( i_track < tracks.size() )
{
if( tracks[i_track]->fmt.i_cat == VIDEO_ES && b_key_picture )
@@ -1436,13 +1438,6 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s
cluster = (KaxCluster*)el;
i_cluster_pos = cluster->GetElementPosition();
- /* add it to the index */
- if( i_index == 0 ||
- ( i_index > 0 && p_indexes[i_index - 1].i_position < (int64_t)cluster->GetElementPosition() ) )
- {
- IndexAppendCluster( cluster );
- }
-
// reset silent tracks
for (size_t i=0; i<tracks.size(); i++)
{
@@ -1468,6 +1463,12 @@ int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_s
ctc.ReadData( es.I_O(), SCOPE_ALL_DATA );
cluster->InitTimecode( uint64( ctc ), i_timescale );
+
+ /* add it to the index */
+ if( i_index == 0 ||
+ ( i_index > 0 &&
+ p_indexes[i_index - 1].i_position < (int64_t)cluster->GetElementPosition() ) )
+ IndexAppendCluster( cluster );
}
else if( MKV_IS_ID( el, KaxClusterSilentTracks ) )
{
diff --git a/modules/demux/mkv/mkv.cpp b/modules/demux/mkv/mkv.cpp
index 5f52656..ebbcafa 100644
--- a/modules/demux/mkv/mkv.cpp
+++ b/modules/demux/mkv/mkv.cpp
@@ -410,49 +410,45 @@ static void Seek( demux_t *p_demux, mtime_t i_date, double f_percent, virtual_ch
msg_Dbg( p_demux, "seek request to %"PRId64" (%f%%)", i_date, f_percent );
if( i_date < 0 && f_percent < 0 )
{
- msg_Warn( p_demux, "cannot seek nowhere !" );
+ msg_Warn( p_demux, "cannot seek nowhere!" );
return;
}
if( f_percent > 1.0 )
{
- msg_Warn( p_demux, "cannot seek so far !" );
+ msg_Warn( p_demux, "cannot seek so far!" );
+ return;
+ }
+ if( p_sys->f_duration < 0 )
+ {
+ msg_Warn( p_demux, "cannot seek without duration!");
return;
}
/* seek without index or without date */
if( f_percent >= 0 && (var_InheritBool( p_demux, "mkv-seek-percent" ) || !p_segment->b_cues || i_date < 0 ))
{
- if( p_sys->f_duration >= 0 && p_segment->b_cues )
- {
- i_date = int64_t( f_percent * p_sys->f_duration * 1000.0 );
- }
- else
+ i_date = int64_t( f_percent * p_sys->f_duration * 1000.0 );
+ if( !p_segment->b_cues )
{
int64_t i_pos = int64_t( f_percent * stream_Size( p_demux->s ) );
- msg_Dbg( p_demux, "inaccurate way of seeking for pos:%"PRId64, i_pos );
+ msg_Dbg( p_demux, "lengthy way of seeking for pos:%"PRId64, i_pos );
for( i_index = 0; i_index < p_segment->i_index; i_index++ )
{
- if( p_segment->b_cues && p_segment->p_indexes[i_index].i_position < i_pos )
- break;
- if( !p_segment->b_cues && p_segment->p_indexes[i_index].i_position >= i_pos && p_segment->p_indexes[i_index].i_time > 0 )
+ if( p_segment->p_indexes[i_index].i_position >= i_pos &&
+ p_segment->p_indexes[i_index].i_time > 0 )
break;
}
if( i_index == p_segment->i_index )
- {
i_index--;
- }
- i_date = p_segment->p_indexes[i_index].i_time;
-
- if( !p_segment->b_cues && ( p_segment->p_indexes[i_index].i_position < i_pos || p_segment->p_indexes[i_index].i_position - i_pos > 2000000 ))
+ if( p_segment->p_indexes[i_index].i_position < i_pos )
{
msg_Dbg( p_demux, "no cues, seek request to global pos: %"PRId64, i_pos );
i_global_position = i_pos;
}
}
}
-
p_vsegment->Seek( *p_demux, i_date, i_time_offset, p_chapter, i_global_position );
}
More information about the vlc-commits
mailing list