[vlc-devel] [PATCH] MKV: rework the PCR to match what avformat does
Steve Lhomme
robUx4 at videolabs.io
Fri Mar 13 17:04:37 CET 2015
Fixes #13575
Fixes #11847 which had time display issues
Applies on top of [PATCH] MKV: split time values between container ones and VLC ones
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 | 49 ++++++++++++++++++++++++++---------------------
1 file changed, 27 insertions(+), 22 deletions(-)
diff --git a/modules/demux/mkv/mkv.cpp b/modules/demux/mkv/mkv.cpp
index 4824c23..f1cf718 100644
--- a/modules/demux/mkv/mkv.cpp
+++ b/modules/demux/mkv/mkv.cpp
@@ -332,7 +332,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
case DEMUX_GET_POSITION:
pf = (double*)va_arg( args, double * );
if ( p_sys->f_duration > 0.0 )
- *pf = (double)((p_sys->i_pts >= p_sys->i_start_pts ? p_sys->i_pts : p_sys->i_start_pts ) - VLC_TS_0) /
+ *pf = (double)((p_sys->i_pcr >= p_sys->i_start_pts ? p_sys->i_pcr : p_sys->i_start_pts ) - VLC_TS_0) /
(1000.0 * p_sys->f_duration);
return VLC_SUCCESS;
@@ -347,7 +347,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
case DEMUX_GET_TIME:
pi64 = (int64_t*)va_arg( args, int64_t * );
- *pi64 = p_sys->i_pts - VLC_TS_0;
+ *pi64 = p_sys->i_pcr - VLC_TS_0;
return VLC_SUCCESS;
case DEMUX_GET_TITLE_INFO:
@@ -693,18 +693,35 @@ msg_Dbg( p_demux, "block (track=%d) i_dts: %"PRId64" / i_pts: %"PRId64, tk->i_nu
(double) p_segment->i_timescale / ( 1000.0 * i_number_frames );
}
- /* FIXME remove when VLC_TS_INVALID work is done */
- if( i_frame == 0 || p_block->i_dts > VLC_TS_INVALID )
- p_block->i_dts += VLC_TS_0;
- 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
+ ts_time_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
+ ts_time_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 == VLC_TS_INVALID ) )
+ {
+ p_sys->i_pcr = i_ts_min;
+ es_out_Control( p_demux->out, ES_OUT_SET_PCR, 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 + tk->i_default_duration:
- VLC_TS_INVALID;
+ i_pts += tk->i_default_duration ? tk->i_default_duration : 1;
}
}
@@ -779,18 +796,6 @@ static int Demux( demux_t *p_demux)
p_sys->i_pts = (ts_time_t)block->GlobalTimecode() / INT64_C(1000);
p_sys->i_pts += p_sys->i_chapter_time + VLC_TS_0;
- 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, 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