[vlc-commits] Improved time managment and seeking in our avformat wrapper.
Laurent Aimar
git at videolan.org
Wed Sep 21 00:59:06 CEST 2011
vlc | branch: master | Laurent Aimar <fenrir at videolan.org> | Mon Sep 19 23:03:14 2011 +0200| [2ee48753551670bf5a04be94e71226a5f8d09be9] | committer: Laurent Aimar
Improved time managment and seeking in our avformat wrapper.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2ee48753551670bf5a04be94e71226a5f8d09be9
---
modules/demux/avformat/demux.c | 118 ++++++++++++++++++++++++----------------
1 files changed, 72 insertions(+), 46 deletions(-)
diff --git a/modules/demux/avformat/demux.c b/modules/demux/avformat/demux.c
index 6b2c3ae..684dd85 100644
--- a/modules/demux/avformat/demux.c
+++ b/modules/demux/avformat/demux.c
@@ -71,9 +71,8 @@ struct demux_sys_t
int i_tk;
es_out_id_t **tk;
-
- int64_t i_pcr;
- int i_pcr_tk;
+ int64_t *tk_pcr;
+ int64_t i_pcr;
unsigned i_ssa_order;
@@ -95,6 +94,7 @@ static int64_t IOSeek( void *opaque, int64_t offset, int whence );
static block_t *BuildSsaFrame( const AVPacket *p_pkt, unsigned i_order );
static void UpdateSeekPoint( demux_t *p_demux, int64_t i_time );
+static void ResetTime( demux_t *p_demux, int64_t i_time );
/*****************************************************************************
* Open
@@ -190,8 +190,7 @@ int OpenDemux( vlc_object_t *p_this )
p_sys->fmt = fmt;
p_sys->i_tk = 0;
p_sys->tk = NULL;
- p_sys->i_pcr_tk = -1;
- p_sys->i_pcr = -1;
+ p_sys->tk_pcr = NULL;
p_sys->i_ssa_order = 0;
TAB_INIT( p_sys->i_attachments, p_sys->attachments);
p_sys->p_title = NULL;
@@ -465,6 +464,8 @@ int OpenDemux( vlc_object_t *p_this )
TAB_APPEND( p_sys->i_tk, p_sys->tk, es );
}
}
+ p_sys->tk_pcr = calloc( p_sys->i_tk, sizeof(*p_sys->tk_pcr) );
+
if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
i_start_time = p_sys->ic->start_time * 1000000 / AV_TIME_BASE;
@@ -496,6 +497,7 @@ int OpenDemux( vlc_object_t *p_this )
TAB_APPEND( p_sys->p_title->i_seekpoint, p_sys->p_title->seekpoint, s );
}
+ ResetTime( p_demux, 0 );
return VLC_SUCCESS;
}
@@ -508,6 +510,7 @@ void CloseDemux( vlc_object_t *p_this )
demux_sys_t *p_sys = p_demux->p_sys;
FREENULL( p_sys->tk );
+ free( p_sys->tk_pcr );
if( p_sys->ic ) av_close_input_stream( p_sys->ic );
@@ -598,19 +601,28 @@ static int Demux( demux_t *p_demux )
msg_Dbg( p_demux, "tk[%d] dts=%"PRId64" pts=%"PRId64,
pkt.stream_index, p_frame->i_dts, p_frame->i_pts );
#endif
+ if( p_frame->i_dts > VLC_TS_INVALID )
+ p_sys->tk_pcr[pkt.stream_index] = p_frame->i_dts;
- if( p_frame->i_dts > VLC_TS_INVALID &&
- ( pkt.stream_index == p_sys->i_pcr_tk || p_sys->i_pcr_tk < 0 ) )
- {
- p_sys->i_pcr_tk = pkt.stream_index;
- p_sys->i_pcr = p_frame->i_dts;
+ int64_t i_ts_max = INT64_MIN;
+ for( int i = 0; i < p_sys->i_tk; i++ )
+ i_ts_max = __MAX( i_ts_max, p_sys->tk_pcr[i] );
- es_out_Control( p_demux->out, ES_OUT_SET_PCR, (int64_t)p_sys->i_pcr );
+ int64_t i_ts_min = INT64_MAX;
+ for( int i = 0; i < p_sys->i_tk; i++ )
+ {
+ if( p_sys->tk_pcr[i] > VLC_TS_INVALID && p_sys->tk_pcr[i] + 10 * CLOCK_FREQ >= i_ts_max )
+ i_ts_min = __MIN( i_ts_min, p_sys->tk_pcr[i] );
+ }
+ if( i_ts_min >= p_sys->i_pcr )
+ {
+ p_sys->i_pcr = i_ts_min;
+ es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr );
+ UpdateSeekPoint( p_demux, p_sys->i_pcr );
}
es_out_Send( p_demux->out, p_sys->tk[pkt.stream_index], p_frame );
- UpdateSeekPoint( p_demux, p_sys->i_pcr);
av_free_packet( &pkt );
return 1;
}
@@ -637,6 +649,26 @@ static void UpdateSeekPoint( demux_t *p_demux, int64_t i_time )
}
}
+static void ResetTime( demux_t *p_demux, int64_t i_time )
+{
+ demux_sys_t *p_sys = p_demux->p_sys;
+
+ if( p_sys->ic->start_time == (int64_t)AV_NOPTS_VALUE || i_time < 0 )
+ i_time = VLC_TS_INVALID;
+ else if( i_time == 0 )
+ i_time = 1;
+
+ p_sys->i_pcr = i_time;
+ for( int i = 0; i < p_sys->i_tk; i++ )
+ p_sys->tk_pcr[i] = i_time;
+
+ if( i_time > VLC_TS_INVALID )
+ {
+ es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_time );
+ UpdateSeekPoint( p_demux, i_time );
+ }
+}
+
static block_t *BuildSsaFrame( const AVPacket *p_pkt, unsigned i_order )
{
if( p_pkt->size <= 0 )
@@ -677,6 +709,7 @@ static block_t *BuildSsaFrame( const AVPacket *p_pkt, unsigned i_order )
static int Control( demux_t *p_demux, int i_query, va_list args )
{
demux_sys_t *p_sys = p_demux->p_sys;
+ const int64_t i_start_time = p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE ? p_sys->ic->start_time : 0;
double f, *pf;
int64_t i64, *pi64;
@@ -700,31 +733,27 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
case DEMUX_SET_POSITION:
f = (double) va_arg( args, double );
- if( p_sys->i_pcr > 0 )
- {
- i64 = p_sys->ic->duration * f;
- if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
- i64 += p_sys->ic->start_time;
+ i64 = p_sys->ic->duration * f + i_start_time;
- msg_Warn( p_demux, "DEMUX_SET_POSITION: %"PRId64, i64 );
+ msg_Warn( p_demux, "DEMUX_SET_POSITION: %"PRId64, i64 );
- /* If we have a duration, we prefer to seek by time
- but if we don't, or if the seek fails, try BYTE seeking */
- if( p_sys->ic->duration == (int64_t)AV_NOPTS_VALUE ||
- (av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0) )
- {
- int64_t i_size = stream_Size( p_demux->s );
- i64 = (i_size * f);
+ /* If we have a duration, we prefer to seek by time
+ but if we don't, or if the seek fails, try BYTE seeking */
+ if( p_sys->ic->duration == (int64_t)AV_NOPTS_VALUE ||
+ (av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BACKWARD ) < 0) )
+ {
+ int64_t i_size = stream_Size( p_demux->s );
+ i64 = (i_size * f);
- msg_Warn( p_demux, "DEMUX_SET_BYTE_POSITION: %"PRId64, i64 );
- if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BYTE ) < 0 )
- return VLC_EGENERIC;
- }
- else
- {
- UpdateSeekPoint( p_demux, i64 );
- }
- p_sys->i_pcr = -1; /* Invalidate time display */
+ msg_Warn( p_demux, "DEMUX_SET_BYTE_POSITION: %"PRId64, i64 );
+ if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BYTE ) < 0 )
+ return VLC_EGENERIC;
+
+ ResetTime( p_demux, -1 );
+ }
+ else
+ {
+ ResetTime( p_demux, i64 - i_start_time );
}
return VLC_SUCCESS;
@@ -742,20 +771,19 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return VLC_SUCCESS;
case DEMUX_SET_TIME:
+ {
i64 = (int64_t)va_arg( args, int64_t );
- i64 = i64 *AV_TIME_BASE / 1000000;
- if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
- i64 += p_sys->ic->start_time;
+ i64 = i64 *AV_TIME_BASE / 1000000 + i_start_time;
msg_Warn( p_demux, "DEMUX_SET_TIME: %"PRId64, i64 );
- if( av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0 )
+ if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BACKWARD ) < 0 )
{
return VLC_EGENERIC;
}
- p_sys->i_pcr = -1; /* Invalidate time display */
- UpdateSeekPoint( p_demux, i64 );
+ ResetTime( p_demux, i64 - i_start_time );
return VLC_SUCCESS;
+ }
case DEMUX_HAS_UNSUPPORTED_META:
{
@@ -835,18 +863,16 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
if( !p_sys->p_title )
return VLC_EGENERIC;
- i64 = p_sys->p_title->seekpoint[i_seekpoint]->i_time_offset *AV_TIME_BASE / 1000000;
- if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
- i64 += p_sys->ic->start_time;
+ i64 = p_sys->p_title->seekpoint[i_seekpoint]->i_time_offset *
+ AV_TIME_BASE / 1000000 + i_start_time;
msg_Warn( p_demux, "DEMUX_SET_TIME: %"PRId64, i64 );
- if( av_seek_frame( p_sys->ic, -1, i64, 0 ) < 0 )
+ if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BACKWARD ) < 0 )
{
return VLC_EGENERIC;
}
- p_sys->i_pcr = -1; /* Invalidate time display */
- UpdateSeekPoint( p_demux, i64 );
+ ResetTime( p_demux, i64 - i_start_time );
return VLC_SUCCESS;
}
More information about the vlc-commits
mailing list