]> git.sesse.net Git - vlc/commitdiff
Reuse the decoders when possible at segment change
authorDenis Charmet <typx@dinauz.org>
Tue, 1 Jan 2013 20:34:33 +0000 (21:34 +0100)
committerDenis Charmet <typx@dinauz.org>
Mon, 7 Jan 2013 21:08:12 +0000 (22:08 +0100)
Should fix #5906 in most cases

modules/demux/mkv/matroska_segment.cpp
modules/demux/mkv/matroska_segment.hpp
modules/demux/mkv/matroska_segment_parse.cpp
modules/demux/mkv/virtual_segment.cpp
modules/demux/mkv/virtual_segment.hpp

index ea0e9f7c93181a74164351a48e012a34b3e18d1c..73986a1fc43f6e36591f3ddbad3ab1706a2c3b07 100644 (file)
@@ -662,6 +662,8 @@ bool matroska_segment_c::Preload( )
             msg_Dbg( &sys.demuxer, "|   + Preload Unknown (%s)", typeid(*el).name() );
     }
 
+    ComputeTrackPriority();
+
     b_preloaded = true;
 
     return true;
@@ -1014,11 +1016,8 @@ int matroska_segment_c::BlockFindTrackIndex( size_t *pi_track,
     return VLC_SUCCESS;
 }
 
-bool matroska_segment_c::Select( mtime_t i_start_time )
+void matroska_segment_c::ComputeTrackPriority()
 {
-    /* add all es */
-    msg_Dbg( &sys.demuxer, "found %d es", (int)tracks.size() );
-
     bool b_has_default_video = false;
     bool b_has_default_audio = false;
     /* check for default */
@@ -1067,8 +1066,28 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
         /* Avoid multivideo tracks when unnecessary */
         if( p_tk->fmt.i_cat == VIDEO_ES )
             p_tk->fmt.i_priority--;
+    } 
+}
+
+bool matroska_segment_c::Select( mtime_t i_start_time )
+{
+    /* add all es */
+    msg_Dbg( &sys.demuxer, "found %d es", (int)tracks.size() );
+
+    for( size_t i_track = 0; i_track < tracks.size(); i_track++ )
+    {
+        mkv_track_t *p_tk = tracks[i_track];
+        es_format_t *p_fmt = &p_tk->fmt;
+
+        if( unlikely( p_fmt->i_cat == UNKNOWN_ES || !p_tk->psz_codec ) )
+        {
+            msg_Warn( &sys.demuxer, "invalid track[%d, n=%d]", (int)i_track, p_tk->i_number );
+            p_tk->p_es = NULL;
+            continue;
+        }
 
-        p_tk->p_es = es_out_Add( sys.demuxer.out, &p_tk->fmt );
+        if( !p_tk->p_es )
+            p_tk->p_es = es_out_Add( sys.demuxer.out, &p_tk->fmt );
 
         /* Turn on a subtitles track if it has been flagged as default -
          * but only do this if no subtitles track has already been engaged,
index a36a73efe6f705e11a9d47f932526140910bd0ad..afb37dbc9f274e53e438de3c15441d8466c0e6b2 100644 (file)
@@ -162,6 +162,7 @@ private:
     SimpleTag * ParseSimpleTags( KaxTagSimple *tag, int level = 50 );
     void IndexAppendCluster( KaxCluster *cluster );
     int32_t TrackInit( mkv_track_t * p_tk );
+    void ComputeTrackPriority();
 };
 
 
index ecdd129d1e74c002d4fd87d5fd0dbc4d2fc45879..697660d98fe3e7439222cfafb3af2785b587e350 100644 (file)
@@ -194,6 +194,7 @@ void matroska_segment_c::ParseTrackEntry( KaxTrackEntry *m )
     memset( tk, 0, sizeof( mkv_track_t ) );
 
     es_format_Init( &tk->fmt, UNKNOWN_ES, 0 );
+    tk->p_es = NULL;
     tk->fmt.psz_language       = strdup("English");
     tk->fmt.psz_description    = NULL;
 
index 0997e36be8b522c11c5e272c66808702243f676a..07cb9756d50eee5ea09c1ae6bc91244680aa3fee 100644 (file)
@@ -476,10 +476,7 @@ void virtual_segment_c::Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_
         }
 
         if( p_current_chapter->p_segment != p_chapter->p_segment )
-        {
-            p_chapter->p_segment->Select( i_date );
-            p_current_chapter->p_segment->UnSelect();
-        }
+            ChangeSegment( p_current_chapter->p_segment, p_chapter->p_segment, i_date );
         p_current_chapter = p_chapter;
 
         p_chapter->p_segment->Seek( i_date, i_time_offset, i_global_position );
@@ -613,3 +610,49 @@ void virtual_chapter_c::print()
         sub_chapters[i]->print();
 }
 #endif
+
+void virtual_segment_c::ChangeSegment( matroska_segment_c * p_old, matroska_segment_c * p_new, mtime_t i_start_time )
+{
+    size_t i, j;
+    for( i = 0; i < p_new->tracks.size(); i++)
+    {
+        mkv_track_t *p_tk = p_new->tracks[i];
+        es_format_t *p_nfmt = &p_tk->fmt;
+
+        /* Let's only do that for audio and video for now */
+        if( p_nfmt->i_cat == AUDIO_ES || p_nfmt->i_cat == VIDEO_ES )
+        {
+            
+            /* check for a similar elementary stream */
+            for( j = 0; j < p_old->tracks.size(); j++)
+            {
+                es_format_t * p_ofmt = &p_old->tracks[j]->fmt;
+
+                if( !p_old->tracks[j]->p_es )
+                    continue;
+
+                if( ( p_nfmt->i_cat == p_ofmt->i_cat ) &&
+                    ( p_nfmt->i_codec == p_ofmt->i_codec ) &&
+                    ( p_nfmt->i_priority == p_ofmt->i_priority ) &&
+                    ( p_nfmt->i_bitrate == p_ofmt->i_bitrate ) &&
+                    ( p_nfmt->i_extra == p_ofmt->i_extra ) &&
+                    ( (!p_nfmt->p_extra && !p_ofmt->p_extra) || 
+                      !memcmp( p_nfmt->p_extra, p_ofmt->p_extra, p_nfmt->i_extra ) ) &&
+                    !strcasecmp( p_nfmt->psz_language, p_ofmt->psz_language ) &&
+                    ( ( p_nfmt->i_cat == AUDIO_ES && 
+                        !memcmp( &p_nfmt->audio, &p_ofmt->audio, sizeof(audio_format_t) ) ) ||
+                      ( p_nfmt->i_cat == VIDEO_ES && 
+                        !memcmp( &p_nfmt->video, &p_ofmt->video, sizeof(video_format_t) ) ) ) )
+                {
+                    /* FIXME handle video palettes... */
+                    msg_Warn( &p_old->sys.demuxer, "Reusing decoder of old track %u for track %u", j, i);
+                    p_tk->p_es = p_old->tracks[j]->p_es;
+                    p_old->tracks[j]->p_es = NULL;
+                    break;
+                }
+            }
+        }
+    }
+    p_new->Select( i_start_time );
+    p_old->UnSelect();
+}
index c63e34a129049747f41db3ad32751fccd15b8173..c901e44e8996b3e825fc24ab7f929126a7ac5b08 100644 (file)
@@ -157,6 +157,8 @@ public:
     bool UpdateCurrentToChapter( demux_t & demux );
     void Seek( demux_t & demuxer, mtime_t i_date, mtime_t i_time_offset,
                virtual_chapter_c *p_chapter, int64_t i_global_position );
+private:
+    void ChangeSegment( matroska_segment_c * p_old, matroska_segment_c * p_new, mtime_t i_start_time );
 };
 
 #endif