vlc | branch: master | Laurent Aimar <[email protected]> | 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; } _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
