[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, ¤t_pos ) )
+ if( priv->last_jump_pos != -1 )
+ current_pos = priv->last_jump_pos;
+ else if( demux_Control( p_demux, DEMUX_GET_POSITION, ¤t_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, ¤t_time ) )
+ if( priv->last_jump_time != VLC_TICK_INVALID )
+ current_time = priv->last_jump_time;
+ else if( demux_Control( p_demux, DEMUX_GET_TIME, ¤t_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