[vlc-devel] commit: mkv: Implement a dumb parser for files with broken or missing Seek Cue tables. (Derk-Jan Hartman )

git version control git at videolan.org
Fri Aug 15 03:41:26 CEST 2008


vlc | branch: master | Derk-Jan Hartman <hartman at videolan.org> | Fri Aug 15 03:41:20 2008 +0200| [4d60c14f60350cce60b5aed414ddd1249f0b8ada] | committer: Derk-Jan Hartman 

mkv: Implement a dumb parser for files with broken or missing Seek Cue tables.

- This is REALLY slow.
- It is slow each time you Seek to somewhere that you have not been/played before.
- We ought to create a "Repair index" function instead, like for avi. (no time before release)

This close ticket #1687

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=4d60c14f60350cce60b5aed414ddd1249f0b8ada
---

 modules/demux/mkv.cpp |   93 +++++++++++++++++++++++++++---------------------
 1 files changed, 52 insertions(+), 41 deletions(-)

diff --git a/modules/demux/mkv.cpp b/modules/demux/mkv.cpp
index 300c392..e3da4a7 100644
--- a/modules/demux/mkv.cpp
+++ b/modules/demux/mkv.cpp
@@ -1172,7 +1172,7 @@ public:
     void LoadCues( KaxCues *cues );
     void LoadTags( KaxTags *tags );
     void InformationCreate( );
-    void Seek( mtime_t i_date, mtime_t i_time_offset );
+    void Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_global_position );
 #if LIBMATROSKA_VERSION >= 0x000800
     int BlockGet( KaxBlock * &, KaxSimpleBlock * &, int64_t *, int64_t *, int64_t *);
 #else
@@ -1206,7 +1206,7 @@ public:
     size_t AddSegment( matroska_segment_c *p_segment );
     void PreloadLinked( );
     mtime_t Duration( ) const;
-    void Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset, chapter_item_c *psz_chapter );
+    void Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset, chapter_item_c *psz_chapter, int64_t i_global_position );
 
     inline chapter_edition_c *Edition()
     {
@@ -3228,7 +3228,7 @@ bool virtual_segment_c::UpdateCurrentToChapter( demux_t & demux )
                 {
                     // only physically seek if necessary
                     if ( psz_current_chapter == NULL || (psz_current_chapter->i_end_time != psz_curr_chapter->i_start_time) )
-                        Seek( demux, sys.i_pts, 0, psz_curr_chapter );
+                        Seek( demux, sys.i_pts, 0, psz_curr_chapter, -1 );
                 }
             }
  
@@ -3449,6 +3449,7 @@ static void Seek( demux_t *p_demux, mtime_t i_date, double f_percent, chapter_it
     virtual_segment_c  *p_vsegment = p_sys->p_current_segment;
     matroska_segment_c *p_segment = p_vsegment->Segment();
     mtime_t            i_time_offset = 0;
+    int64_t            i_global_position = -1;
 
     int         i_index;
 
@@ -3475,13 +3476,13 @@ static void Seek( demux_t *p_demux, mtime_t i_date, double f_percent, chapter_it
         {
             int64_t i_pos = int64_t( f_percent * stream_Size( p_demux->s ) );
 
-            msg_Dbg( p_demux, "inacurate way of seeking" );
+            msg_Dbg( p_demux, "inaccurate way of seeking for pos:%"PRId64, i_pos );
             for( i_index = 0; i_index < p_segment->i_index; i_index++ )
             {
-                if( p_segment->p_indexes[i_index].i_position >= i_pos)
-                {
+                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 )
                     break;
-                }
             }
             if( i_index == p_segment->i_index )
             {
@@ -3490,37 +3491,15 @@ static void Seek( demux_t *p_demux, mtime_t i_date, double f_percent, chapter_it
 
             i_date = p_segment->p_indexes[i_index].i_time;
 
-#if 0
-            if( p_segment->p_indexes[i_index].i_position < i_pos )
+            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 ))
             {
-                EbmlElement *el;
-
-                msg_Warn( p_demux, "searching for cluster, could take some time" );
-
-                /* search a cluster */
-                while( ( el = p_sys->ep->Get() ) != NULL )
-                {
-                    if( MKV_IS_ID( el, KaxCluster ) )
-                    {
-                        KaxCluster *cluster = (KaxCluster*)el;
-
-                        /* add it to the index */
-                        p_segment->IndexAppendCluster( cluster );
-
-                        if( (int64_t)cluster->GetElementPosition() >= i_pos )
-                        {
-                            p_sys->cluster = cluster;
-                            p_sys->ep->Down();
-                            break;
-                        }
-                    }
-                }
+                msg_Dbg( p_demux, "no cues, seek request to global pos: %"PRId64, i_pos );
+                i_global_position = i_pos;
             }
-#endif
         }
     }
 
-    p_vsegment->Seek( *p_demux, i_date, i_time_offset, psz_chapter );
+    p_vsegment->Seek( *p_demux, i_date, i_time_offset, psz_chapter, i_global_position );
 }
 
 /*****************************************************************************
@@ -5542,7 +5521,7 @@ void demux_sys_t::JumpTo( virtual_segment_c & vsegment, chapter_item_c * p_chapt
         if ( !p_chapter->Enter( true ) )
         {
             // jump to the location in the found segment
-            vsegment.Seek( demuxer, p_chapter->i_user_start_time, -1, p_chapter );
+            vsegment.Seek( demuxer, p_chapter->i_user_start_time, -1, p_chapter, -1 );
         }
     }
  
@@ -5879,7 +5858,7 @@ void virtual_segment_c::AppendUID( const EbmlBinary * p_UID )
     linked_uids.push_back( *(KaxSegmentUID*)(p_UID) );
 }
 
-void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset )
+void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset, int64_t i_global_position )
 {
     KaxBlock    *block;
 #if LIBMATROSKA_VERSION >= 0x000800
@@ -5893,6 +5872,39 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset )
     int64_t     i_seek_position = i_start_pos;
     int64_t     i_seek_time = i_start_time;
 
+    if( i_global_position >= 0 )
+    {
+        /* Special case for seeking in files with no cues */
+        EbmlElement *el = NULL;
+        es.I_O().setFilePointer( i_start_pos, seek_beginning );
+        delete ep;
+        ep = new EbmlParser( &es, segment, &sys.demuxer );
+        cluster = NULL;
+
+        while( ( el = ep->Get() ) != NULL )
+        {
+            if( MKV_IS_ID( el, KaxCluster ) )
+            {
+                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() ) )
+                {
+                    IndexAppendCluster( cluster );
+                }
+                if( es.I_O().getFilePointer() >= i_global_position )
+                {
+                    ParseCluster();
+                    msg_Dbg( &sys.demuxer, "we found a cluster that is in the neighbourhood" );
+                    es_out_Control( sys.demuxer.out, ES_OUT_RESET_PCR );
+                    return;
+                }
+            }
+        }
+        msg_Err( &sys.demuxer, "This file has no cues, and we were unable to seek to the requested position by parsing." );
+        return;
+    }
+
     if ( i_index > 0 )
     {
         int i_idx = 0;
@@ -5939,7 +5951,6 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset )
         es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, tracks[i_track]->p_es, i_date );
     }
 
-
     while( i_track_skipping > 0 )
     {
 #if LIBMATROSKA_VERSION >= 0x000800
@@ -6015,7 +6026,7 @@ void matroska_segment_c::Seek( mtime_t i_date, mtime_t i_time_offset )
     }
 }
 
-void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset, chapter_item_c *psz_chapter )
+void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset, chapter_item_c *psz_chapter, int64_t i_global_position )
 {
     demux_sys_t *p_sys = demuxer.p_sys;
     size_t i;
@@ -6059,7 +6070,7 @@ void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_
         i_current_segment = i;
     }
 
-    linked_segments[i]->Seek( i_date, i_time_offset );
+    linked_segments[i]->Seek( i_date, i_time_offset, i_global_position );
 }
 
 void chapter_codec_cmds_c::AddCommand( const KaxChapterProcessCommand & command )
@@ -6604,7 +6615,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
             {
                 if ( !p_chapter->Enter( true ) )
                     // jump to the location in the found segment
-                    sys.p_current_segment->Seek( sys.demuxer, p_chapter->i_user_start_time, -1, p_chapter );
+                    sys.p_current_segment->Seek( sys.demuxer, p_chapter->i_user_start_time, -1, p_chapter, -1 );
 
                 f_result = true;
             }
@@ -6622,7 +6633,7 @@ bool dvd_command_interpretor_c::Interpret( const binary * p_command, size_t i_si
             {
                 if ( !p_chapter->Enter( true ) )
                     // jump to the location in the found segment
-                    sys.p_current_segment->Seek( sys.demuxer, p_chapter->i_user_start_time, -1, p_chapter );
+                    sys.p_current_segment->Seek( sys.demuxer, p_chapter->i_user_start_time, -1, p_chapter, -1 );
 
                 f_result = true;
             }
@@ -6854,7 +6865,7 @@ bool matroska_script_interpretor_c::Interpret( const binary * p_command, size_t
         else
         {
             if ( !p_chapter->EnterAndLeave( sys.p_current_segment->CurrentChapter() ) )
-                p_segment->Seek( sys.demuxer, p_chapter->i_user_start_time, -1, p_chapter );
+                p_segment->Seek( sys.demuxer, p_chapter->i_user_start_time, -1, p_chapter, -1 );
             b_result = true;
         }
     }




More information about the vlc-devel mailing list