[vlc-devel] [PATCH 7/7] input: make jumps more predictable

Thomas Guillem thomas at gllm.fr
Wed Oct 30 15:57:01 CET 2019


cf. ControlHandleLastJump() comment.

This commit also fixes unexpected jumps to 0, when a demux don't return a valid
time after a seek (this is the case for MKV). Nothing in the doc state that a
demux should return a valid time after a seek, but the time should be valid
after the first demux() call.
---
 src/input/input.c          | 59 ++++++++++++++++++++++++++++++++++++--
 src/input/input_internal.h |  4 +++
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/src/input/input.c b/src/input/input.c
index 3f6c5bbad0f..209a8b2fa68 100644
--- a/src/input/input.c
+++ b/src/input/input.c
@@ -78,6 +78,8 @@ static void             MainLoop( input_thread_t *p_input, bool b_interactive );
 static inline int ControlPop( input_thread_t *, int *, input_control_param_t *, vlc_tick_t i_deadline, bool b_postpone_seek );
 static void       ControlRelease( int i_type, const input_control_param_t *p_param );
 static bool       ControlIsSeekRequest( int i_type );
+static void       ControlHandleLastJump( input_thread_t *p_input, int i_type,
+                                         vlc_tick_t i_last_seek_mdate );
 static bool       Control( input_thread_t *, int, input_control_param_t );
 static void       ControlPause( input_thread_t *, vlc_tick_t );
 
@@ -306,6 +308,8 @@ static input_thread_t *Create( vlc_object_t *p_parent,
     priv->b_recording = false;
     priv->rate = 1.f;
     priv->normal_time = VLC_TICK_0;
+    priv->last_jump_time = VLC_TICK_INVALID;
+    priv->last_jump_pos = -1;
     TAB_INIT( priv->i_attachment, priv->attachment );
     priv->attachment_demux = NULL;
     priv->p_sout   = NULL;
@@ -763,6 +767,9 @@ static void MainLoop( input_thread_t *p_input, bool b_interactive )
 #ifndef NDEBUG
             msg_Dbg( p_input, "control type=%d", i_type );
 #endif
+
+            ControlHandleLastJump( p_input, i_type, i_last_seek_mdate );
+
             if( Control( p_input, i_type, param ) )
             {
                 if( ControlIsSeekRequest( i_type ) )
@@ -1540,6 +1547,44 @@ static inline int ControlPop( input_thread_t *p_input,
 
     return VLC_SUCCESS;
 }
+
+static void ControlHandleLastJump( input_thread_t *p_input, int i_type,
+                                   vlc_tick_t i_last_seek_mdate )
+{
+    input_thread_private_t *priv = input_priv(p_input);
+
+    /* Jump controls can come successively with or without a slight delay
+     * (depending on the interface/control). ControlGetReducedIndexLocked() is
+     * already gathering all jump controls of the control FIFO, but jump
+     * controls can also be sent after a previous jump is processed. In that
+     * case, we want to use the last input_thread_t time as a reference and not
+     * the demux one. This will allow to have more predictable final position,
+     * that won't depend on the jump control processing speed.
+     */
+
+    switch( i_type )
+    {
+        case INPUT_CONTROL_SET_PROGRAM:
+        case INPUT_CONTROL_SET_TITLE:
+        case INPUT_CONTROL_SET_TITLE_NEXT:
+        case INPUT_CONTROL_SET_TITLE_PREV:
+        case INPUT_CONTROL_SET_SEEKPOINT:
+        case INPUT_CONTROL_SET_SEEKPOINT_NEXT:
+        case INPUT_CONTROL_SET_SEEKPOINT_PREV:
+            /* These controls invalidate the last saved jump */
+            priv->last_jump_time = VLC_TICK_INVALID;
+            priv->last_jump_pos = -1;
+            break;
+        default:
+            /* Forget the last saved time/position after 50ms */
+            if( vlc_tick_now() - i_last_seek_mdate > VLC_TICK_FROM_MS(50) )
+            {
+                priv->last_jump_time = VLC_TICK_INVALID;
+                priv->last_jump_pos = -1;
+            }
+    }
+}
+
 static bool ControlIsSeekRequest( int i_type )
 {
     switch( i_type )
@@ -1751,7 +1796,9 @@ static int SetPosition( input_thread_t *p_input, double pos, bool fastseek,
     if( !absolute )
     {
         double current_pos;
-        if( demux_Control( p_demux, DEMUX_GET_POSITION, &current_pos ) )
+        if( priv->last_jump_pos != -1 )
+            current_pos = priv->last_jump_pos;
+        else if( demux_Control( p_demux, DEMUX_GET_POSITION, &current_pos ) )
             return VLC_EGENERIC;
         pos += current_pos;
     }
@@ -1764,6 +1811,9 @@ static int SetPosition( input_thread_t *p_input, double pos, bool fastseek,
     if( demux_Control( p_demux, DEMUX_SET_POSITION, pos, !fastseek ) )
         return VLC_EGENERIC;
 
+    priv->last_jump_time = VLC_TICK_INVALID;
+    priv->last_jump_pos = pos;
+
     PostSeek( p_input );
     return VLC_SUCCESS;
 }
@@ -1777,7 +1827,9 @@ static int SetTime( input_thread_t *p_input, vlc_tick_t time, bool fastseek,
     if( !absolute )
     {
         vlc_tick_t current_time;
-        if( demux_Control( p_demux, DEMUX_GET_TIME, &current_time ) )
+        if( priv->last_jump_time != VLC_TICK_INVALID )
+            current_time = priv->last_jump_time;
+        else if( demux_Control( p_demux, DEMUX_GET_TIME, &current_time ) )
             goto set_position_fallback;
         time += current_time;
     }
@@ -1787,6 +1839,9 @@ static int SetTime( input_thread_t *p_input, vlc_tick_t time, bool fastseek,
     if( demux_Control( p_demux, DEMUX_SET_TIME, time, !fastseek ) )
         goto set_position_fallback;
 
+    priv->last_jump_time = time;
+    priv->last_jump_pos = -1;
+
     PostSeek( p_input );
     return VLC_SUCCESS;
 
diff --git a/src/input/input_internal.h b/src/input/input_internal.h
index b990a23c66b..da644eb6e97 100644
--- a/src/input/input_internal.h
+++ b/src/input/input_internal.h
@@ -541,6 +541,10 @@ typedef struct input_thread_private_t
     float       rate;
     vlc_tick_t  normal_time;
 
+    /* cf. ControlHandleLastJump */
+    vlc_tick_t  last_jump_time;
+    double      last_jump_pos;
+
     /* Playtime configuration and state */
     vlc_tick_t  i_start;    /* :start-time,0 by default */
     vlc_tick_t  i_stop;     /* :stop-time, 0 if none */
-- 
2.20.1



More information about the vlc-devel mailing list