[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