Correctly display time and seek with high input caching.
authorLaurent Aimar <fenrir@videolan.org>
Sat, 29 Nov 2008 20:16:42 +0000 (21:16 +0100)
committerLaurent Aimar <fenrir@videolan.org>
Sun, 30 Nov 2008 15:51:45 +0000 (16:51 +0100)
src/input/es_out.c
src/input/input.c

index 0d6197c..c252da6 100644 (file)
@@ -793,8 +793,52 @@ static void EsOutFrameNext( es_out_t *out )
 
     p_sys->i_preroll_end = -1;
 }
+static mtime_t EsOutGetBuffering( es_out_t *out )
+{
+    es_out_sys_t *p_sys = out->p_sys;
+
+    if( !p_sys->p_pgrm )
+        return 0;
+
+    int i_ret;
+    mtime_t i_stream_start;
+    mtime_t i_system_start;
+    mtime_t i_stream_duration;
+    mtime_t i_system_duration;
+    i_ret = input_clock_GetState( p_sys->p_pgrm->p_clock,
+                                  &i_stream_start, &i_system_start,
+                                  &i_stream_duration, &i_system_duration );
+
+    if( i_ret )
+        return 0;
 
+    mtime_t i_delay;
 
+    if( p_sys->b_buffering && p_sys->i_buffering_extra_initial <= 0 )
+    {
+        i_delay = i_stream_duration;
+    }
+    else
+    {
+        mtime_t i_system_duration;
+        if( p_sys->b_paused )
+        {
+            i_system_duration = p_sys->i_pause_date  - i_system_start;
+            if( p_sys->i_buffering_extra_initial > 0 )
+                i_system_duration += p_sys->i_buffering_extra_system - p_sys->i_buffering_extra_initial;
+        }
+        else
+        {
+            i_system_duration = mdate() - i_system_start;
+        }
+
+        const mtime_t i_consumed = i_system_duration * INPUT_RATE_DEFAULT / p_sys->i_rate - i_stream_duration;
+        i_delay = p_sys->p_input->i_pts_delay - i_consumed;
+    }
+    if( i_delay < 0 )
+        return 0;
+    return i_delay;
+}
 
 static void EsOutESVarUpdateGeneric( es_out_t *out, int i_id, es_format_t *fmt, const char *psz_language,
                                      bool b_delete )
@@ -2313,7 +2357,18 @@ static int EsOutControlLocked( es_out_t *out, int i_query, va_list args )
             mtime_t i_time = (mtime_t)va_arg( args, mtime_t );
             mtime_t i_length = (mtime_t)va_arg( args, mtime_t );
 
-            /* TODO handle es_out buffering */
+            /* Fix for buffering delay */
+            const mtime_t i_delay = EsOutGetBuffering( out );
+
+            i_time -= i_delay;
+            if( i_time < 0 )
+                i_time = 0;
+
+            if( i_length > 0 )
+                f_position -= (double)i_delay / i_length;
+            if( f_position < 0 )
+                f_position = 0;
+
             input_SendEventTimes( p_sys->p_input, f_position, i_time, i_length );
             return VLC_SUCCESS;
         }
index 9e48c5c..ba75afa 100644 (file)
@@ -1580,19 +1580,13 @@ static bool Control( input_thread_t *p_input, int i_type,
                 msg_Err( p_input, "INPUT_CONTROL_SET_POSITION(_OFFSET) ignored while recording" );
                 break;
             }
-            if( i_type == INPUT_CONTROL_SET_POSITION )
-            {
-                f_pos = val.f_float;
-            }
-            else
-            {
-                /* Should not fail */
-                demux_Control( p_input->p->input.p_demux,
-                                DEMUX_GET_POSITION, &f_pos );
-                f_pos += val.f_float;
-            }
-            if( f_pos < 0.0 ) f_pos = 0.0;
-            if( f_pos > 1.0 ) f_pos = 1.0;
+            f_pos = val.f_float;
+            if( i_type != INPUT_CONTROL_SET_POSITION )
+                f_pos += var_GetFloat( p_input, "position" );
+            if( f_pos < 0.0 )
+                f_pos = 0.0;
+            else if( f_pos > 1.0 )
+                f_pos = 1.0;
             /* Reset the decoders states and clock sync (before calling the demuxer */
             es_out_SetTime( p_input->p->p_es_out, -1 );
             if( demux_Control( p_input->p->input.p_demux, DEMUX_SET_POSITION,
@@ -1624,18 +1618,12 @@ static bool Control( input_thread_t *p_input, int i_type,
                 break;
             }
 
-            if( i_type == INPUT_CONTROL_SET_TIME )
-            {
-                i_time = val.i_time;
-            }
-            else
-            {
-                /* Should not fail */
-                demux_Control( p_input->p->input.p_demux,
-                                DEMUX_GET_TIME, &i_time );
-                i_time += val.i_time;
-            }
-            if( i_time < 0 ) i_time = 0;
+            i_time = val.i_time;
+            if( i_type != INPUT_CONTROL_SET_TIME )
+                i_time += var_GetTime( p_input, "time" );
+
+            if( i_time < 0 )
+                i_time = 0;
 
             /* Reset the decoders states and clock sync (before calling the demuxer */
             es_out_SetTime( p_input->p->p_es_out, -1 );
@@ -1934,9 +1922,8 @@ static bool Control( input_thread_t *p_input, int i_type,
                 {
                     i_seekpoint = p_demux->info.i_seekpoint;
                     i_seekpoint_time = p_input->p->input.title[p_demux->info.i_title]->seekpoint[i_seekpoint]->i_time_offset;
-                    if( i_seekpoint_time >= 0 &&
-                         !demux_Control( p_demux,
-                                          DEMUX_GET_TIME, &i_input_time ) )
+                    i_input_time = var_GetTime( p_input, "time" );
+                    if( i_seekpoint_time >= 0 && i_input_time >= 0 )
                     {
                         if( i_input_time < i_seekpoint_time + 3000000 )
                             i_seekpoint--;
@@ -1970,9 +1957,8 @@ static bool Control( input_thread_t *p_input, int i_type,
                 {
                     i_seekpoint = p_access->info.i_seekpoint;
                     i_seekpoint_time = p_input->p->input.title[p_access->info.i_title]->seekpoint[i_seekpoint]->i_time_offset;
-                    if( i_seekpoint_time >= 0 &&
-                        demux_Control( p_demux,
-                                        DEMUX_GET_TIME, &i_input_time ) )
+                    i_input_time = var_GetTime( p_input, "time" );
+                    if( i_seekpoint_time >= 0 && i_input_time >= 0 )
                     {
                         if( i_input_time < i_seekpoint_time + 3000000 )
                             i_seekpoint--;