vlc | branch: master | Denis Charmet <[email protected]> | 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 <[email protected]> > 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 ); } _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
