[vlc-devel] [PATCH] Allow mpeg2-ts skip forward/backward
Steve Bennett
steveb at workware.net.au
Thu Apr 14 02:01:56 CEST 2011
Allow skip forward/backward and display total time for
mpeg2 transport streams (e.g. dvb-t).
The (possibly discontinous) embedded PCR is used to estimate the mux
rate and thus relate the current time index to the current file position.
See: https://trac.videolan.org/vlc/ticket/2985
Signed-off-by: Steve Bennett <steveb at workware.net.au>
---
modules/demux/ts.c | 80 +++++++++++++++++++++++++++++++++++++--------------
1 files changed, 58 insertions(+), 22 deletions(-)
diff --git a/modules/demux/ts.c b/modules/demux/ts.c
index 4c209f2..0ed5683 100644
--- a/modules/demux/ts.c
+++ b/modules/demux/ts.c
@@ -330,6 +330,11 @@ struct demux_sys_t
/* how many TS packet we read at once */
int i_ts_read;
+ /* guess mux rate */
+ mtime_t i_first_pcr;
+ int64_t i_first_streampos;
+ int i_mux_rate;
+
/* All pid */
ts_pid_t pid[8192];
@@ -1213,41 +1218,40 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return VLC_EGENERIC;
return VLC_SUCCESS;
-#if 0
case DEMUX_GET_TIME:
pi64 = (int64_t*)va_arg( args, int64_t * );
- if( p_sys->i_time < 0 )
+ i64 = stream_Size( p_demux->s );
+ if( i64 > 0 )
{
- *pi64 = 0;
- return VLC_EGENERIC;
+ /* Calculate time based on position and mux rate */
+ if (p_sys->i_mux_rate > 0)
+ {
+ *pi64 = INT64_C(1000000) * ( stream_Tell( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
+ return VLC_SUCCESS;
+ }
}
- *pi64 = p_sys->i_time;
- return VLC_SUCCESS;
+ else if( DVBEventInformation( p_demux, pi64, NULL ) == 0)
+ return VLC_SUCCESS;
+ *pi64 = 0;
+ return VLC_EGENERIC;
case DEMUX_GET_LENGTH:
pi64 = (int64_t*)va_arg( args, int64_t * );
- if( p_sys->i_mux_rate > 0 )
+ i64 = stream_Size( p_demux->s );
+ if( i64 > 0 )
{
- *pi64 = INT64_C(1000000) * ( stream_Size( p_demux->s ) / 50 ) /
- p_sys->i_mux_rate;
- return VLC_SUCCESS;
+ if( p_sys->i_mux_rate > 0 )
+ {
+ *pi64 = INT64_C(1000000) * ( stream_Size( p_demux->s ) / 50 ) / p_sys->i_mux_rate;
+ return VLC_SUCCESS;
+ }
}
+ else if( DVBEventInformation( p_demux, NULL, pi64 ) == 0)
+ return VLC_SUCCESS;
*pi64 = 0;
return VLC_EGENERIC;
-#else
- case DEMUX_GET_TIME:
- pi64 = (int64_t*)va_arg( args, int64_t * );
- if( DVBEventInformation( p_demux, pi64, NULL ) )
- *pi64 = 0;
- return VLC_SUCCESS;
- case DEMUX_GET_LENGTH:
- pi64 = (int64_t*)va_arg( args, int64_t * );
- if( DVBEventInformation( p_demux, NULL, pi64 ) )
- *pi64 = 0;
- return VLC_SUCCESS;
-#endif
case DEMUX_SET_GROUP:
{
vlc_list_t *p_list;
@@ -1858,6 +1862,38 @@ static void PCRHandle( demux_t *p_demux, ts_pid_t *pid, block_t *p_bk )
( (mtime_t)p[9] << 1 ) |
( (mtime_t)p[10] >> 7 );
+ if (p_sys->i_first_pcr == 0)
+ {
+ /* Save this pcr and stream position */
+ p_sys->i_first_pcr = i_pcr;
+ p_sys->i_first_streampos = stream_Tell( p_demux->s );
+ }
+ else if (p_sys->i_mux_rate <= 0)
+ {
+ if ((i_pcr - p_sys->i_first_pcr) * 100 / 9 >= 10000)
+ {
+ /* Have at least 10ms, so calculate (guess) the mux rate
+ * based on pcr and stream positions
+ */
+
+ /* Mux rate is in units of 50 bytes/s */
+ p_sys->i_mux_rate = (stream_Tell( p_demux->s ) - p_sys->i_first_streampos)
+ * 1000000 / 50 / ((i_pcr - p_sys->i_first_pcr) * 100 / 9);
+ msg_Dbg(p_demux, "Calculated mux rate=%d (50 bytes/sec) = %dbits/s",
+ p_sys->i_mux_rate, p_sys->i_mux_rate * 50 * 8);
+
+ /* If there is a disjunction or the pcr wraps,
+ * we may get a horribly wrong answer
+ */
+ if (p_sys->i_mux_rate < 5000 || p_sys->i_mux_rate > 50000)
+ {
+ msg_Warn( p_demux, "Unreasonable mux rate, retrying");
+ p_sys->i_first_pcr = 0;
+ p_sys->i_mux_rate = 0;
+ }
+ }
+ }
+
/* Search program and set the PCR */
for( int i = 0; i < p_sys->i_pmt; i++ )
{
--
1.5.5.3
More information about the vlc-devel
mailing list