[vlc-devel] [PATCH] MKV: rework the PCR to match what avformat does

Steve Lhomme robUx4 at videolabs.io
Thu Mar 12 15:37:34 CET 2015


Fixes #13575
Fixes #11847 which had time display issues

The new PCR logic is borrowed from
http://git.videolan.org/?p=vlc.git;a=blob;f=modules/demux/avformat/demux.c;hb=HEAD#l776

The PCR is now set just before sending the packet es_out_Send() rather than
before treating the new read Block (ie the previous PCR value)

i_last_dts is now only valid for active tracks

the i_pts is not set to 0 in a lace as it disturbs seeking performance
---
 modules/demux/mkv/mkv.cpp | 46 ++++++++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/modules/demux/mkv/mkv.cpp b/modules/demux/mkv/mkv.cpp
index 7b8abb1..b32c594 100644
--- a/modules/demux/mkv/mkv.cpp
+++ b/modules/demux/mkv/mkv.cpp
@@ -520,7 +520,7 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
         {
             tk->b_inited = false;
             if( tk->fmt.i_cat == VIDEO_ES || tk->fmt.i_cat == AUDIO_ES )
-                tk->i_last_dts = i_pts;
+                tk->i_last_dts = VLC_TS_INVALID;
             return;
         }
     }
@@ -697,12 +697,38 @@ msg_Dbg( p_demux, "block (track=%d) i_dts: %"PRId64" / i_pts: %"PRId64, tk->i_nu
         if( !tk->b_dts_only && ( i_frame == 0 || p_block->i_pts > VLC_TS_INVALID ) )
             p_block->i_pts += VLC_TS_0;
 
+        // find the latest DTS for an active track
+        int64_t i_ts_max = INT64_MIN;
+        for( size_t i = 0; i < p_segment->tracks.size(); i++ )
+        {
+            mkv_track_t *tk = p_segment->tracks[i];
+            if( tk->i_last_dts > VLC_TS_INVALID )
+                i_ts_max = __MAX( i_ts_max, tk->i_last_dts );
+        }
+
+        // find the earliest DTS less than 10 clock ticks away from the latest DTS
+        int64_t i_ts_min = INT64_MAX;
+        for( size_t i = 0; i < p_segment->tracks.size(); i++ )
+        {
+            mkv_track_t *tk = p_segment->tracks[i];
+            if( tk->i_last_dts > VLC_TS_INVALID && tk->i_last_dts + 10 * CLOCK_FREQ >= i_ts_max )
+                i_ts_min = __MIN( i_ts_min, tk->i_last_dts );
+        }
+
+        // the PCR is the earliest active DTS if we found one
+        if( i_ts_min != INT64_MAX && i_ts_min > p_sys->i_pcr )
+        {
+            p_sys->i_pcr = i_ts_min;
+            es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + i_ts_min );
+        }
+
         es_out_Send( p_demux->out, tk->p_es, p_block );
 
         /* use time stamp only for first block */
-        i_pts = ( tk->i_default_duration )?
-                 i_pts + ( mtime_t )( tk->i_default_duration / 1000 ):
-                 VLC_TS_INVALID;
+        if ( tk->i_default_duration )
+            i_pts +=( mtime_t )( tk->i_default_duration / 1000 );
+        else
+            i_pts += 1;
     }
 }
 
@@ -776,18 +802,6 @@ static int Demux( demux_t *p_demux)
         else
             p_sys->i_pts = p_sys->i_chapter_time + ( (mtime_t)block->GlobalTimecode() / INT64_C(1000) );
 
-        mtime_t i_pcr = VLC_TS_INVALID;
-        for( size_t i = 0; i < p_segment->tracks.size(); i++)
-            if( p_segment->tracks[i]->i_last_dts > VLC_TS_INVALID &&
-                ( p_segment->tracks[i]->i_last_dts < i_pcr || i_pcr == VLC_TS_INVALID ))
-                i_pcr = p_segment->tracks[i]->i_last_dts;
-
-        if( i_pcr > p_sys->i_pcr + 300000 )
-        {
-            es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_pcr );
-            p_sys->i_pcr = i_pcr;
-        }
-
         if( p_sys->i_pts >= p_sys->i_start_pts  )
         {
             if ( p_vsegment->UpdateCurrentToChapter( *p_demux ) )
-- 
2.3.2




More information about the vlc-devel mailing list