[vlc-commits] [Git][videolan/vlc][master] 5 commits: player: timer: handle seek state

Steve Lhomme (@robUx4) gitlab at videolan.org
Fri Jan 19 10:11:30 UTC 2024



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
1ecb283c by Thomas Guillem at 2024-01-19T09:47:41+00:00
player: timer: handle seek state

Keep the last requested seek position/time, that will be used for
successive jumps. It will be more precise than using the demux
GET_TIME/GET_POSITION.

Send 'on_seek' callback with a valid point when starting a new seek.
This callback will be called with a NULL point once all seek requests
are processed.

UI have now the choice to update their time/position to the seeked
value. This will fix the UI not updated when the seek is long to
process.

Refs #27383
Refs #28482

- - - - -
293d8919 by Thomas Guillem at 2024-01-19T09:47:41+00:00
player: expose seeking from GetPos/GetTime

- - - - -
05c9c727 by Thomas Guillem at 2024-01-19T09:47:41+00:00
player: always seek the input_thread with absolute values

Don't use INPUT_CONTROL_JUMP_POSITION and INPUT_CONTROL_JUMP_TIME, that
use input times from the demuxer. Instead, add up the time from the
player timer, that use ts from the output clocks.

This fixes a possible gap with relatives seeks, depending on the input
source or output delay (aout).

For examples, seeking -3s was seeking -2s and seeking +3s was seeking
+4s before this commit. Now seeking back and forth with stay at the same
position.

Fixes #28482
Fixes #27383

- - - - -
396c8141 by Thomas Guillem at 2024-01-19T09:47:41+00:00
input: remove JUMP controls

The input_thread can now only seek with absolute values.

- - - - -
c20e4543 by Thomas Guillem at 2024-01-19T09:47:41+00:00
qt: implement timer.on_seek

Set the time and position to the requested seek point. Pause timers
while seeking.

- - - - -


13 changed files:

- include/vlc_demux.h
- include/vlc_player.h
- modules/demux/mpeg/ps.c
- modules/gui/qt/player/player_controller.cpp
- modules/gui/qt/player/player_controller_p.hpp
- modules/stream_out/chromecast/chromecast_demux.cpp
- src/input/input.c
- src/input/input_internal.h
- src/player/input.c
- src/player/osd.c
- src/player/player.c
- src/player/player.h
- src/player/timer.c


Changes:

=====================================
include/vlc_demux.h
=====================================
@@ -544,18 +544,8 @@ static inline bool demux_IsForced( demux_t *p_demux, const char *psz_name )
     return true;
 }
 
-static inline int demux_SetPosition( demux_t *p_demux, double pos, bool precise,
-                                     bool absolute)
+static inline int demux_SetPosition( demux_t *p_demux, double pos, bool precise )
 {
-    if( !absolute )
-    {
-        double current_pos;
-        int ret = vlc_demux_GetPosition( p_demux, &current_pos );
-        if( ret != VLC_SUCCESS )
-            return ret;
-        pos += current_pos;
-    }
-
     if( pos < 0.f )
         pos = 0.f;
     else if( pos > 1.f )
@@ -563,18 +553,8 @@ static inline int demux_SetPosition( demux_t *p_demux, double pos, bool precise,
     return demux_Control( p_demux, DEMUX_SET_POSITION, pos, precise );
 }
 
-static inline int demux_SetTime( demux_t *p_demux, vlc_tick_t time, bool precise,
-                                 bool absolute )
+static inline int demux_SetTime( demux_t *p_demux, vlc_tick_t time, bool precise )
 {
-    if( !absolute )
-    {
-        vlc_tick_t current_time;
-        int ret = vlc_demux_GetTime( p_demux, &current_time );
-        if( ret != VLC_SUCCESS )
-            return ret;
-        time += current_time;
-    }
-
     if( time < 0 )
         time = 0;
     return demux_Control( p_demux, DEMUX_SET_TIME, time, precise );


=====================================
include/vlc_player.h
=====================================
@@ -3399,6 +3399,15 @@ struct vlc_player_timer_cbs
      * @param data opaque pointer set by vlc_player_AddTimer()
      */
     void (*on_discontinuity)(vlc_tick_t system_date, void *data);
+
+    /**
+     * Called when the player is seeking or finished seeking
+     *
+     * @param value point of the seek request or NULL when seeking is finished
+     * value.system_date = VLC_TICK_MAX in that case
+     * @param data opaque pointer set by vlc_player_AddTimer()
+     */
+    void (*on_seek)(const struct vlc_player_timer_point *value, void *data);
 };
 
 /**


=====================================
modules/demux/mpeg/ps.c
=====================================
@@ -804,7 +804,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             {
                 vlc_tick_t i_time = va_arg( args, vlc_tick_t );
                 i_time -= p_sys->tk[p_sys->i_time_track_index].i_first_pts;
-                return demux_SetPosition( p_demux, (double) i_time / p_sys->i_length, false, true );
+                return demux_SetPosition( p_demux, (double) i_time / p_sys->i_length, false );
             }
             break;
         }


=====================================
modules/gui/qt/player/player_controller.cpp
=====================================
@@ -904,6 +904,9 @@ static void on_player_timer_update(const struct vlc_player_timer_point *point,
                                    void *data)
 {
     PlayerControllerPrivate* that = static_cast<PlayerControllerPrivate*>(data);
+    if (that->seeking)
+        return;
+
     that->callAsync([that,point_copy = *point](){
         PlayerController* q = that->q_func();
 
@@ -974,6 +977,32 @@ static void on_player_timer_discontinuity(vlc_tick_t system_date, void *data)
     });
 }
 
+static void on_player_timer_seek(const struct vlc_player_timer_point *point,
+                                 void *data)
+{
+    PlayerControllerPrivate* that = static_cast<PlayerControllerPrivate*>(data);
+    if (point != NULL)
+    {
+        that->seeking = true;
+        that->callAsync([that,point_copy = *point](){
+            PlayerController* q = that->q_func();
+
+            that->m_player_time = point_copy;
+            if (that->m_player_time.position > 0)
+                that->m_position = that->m_player_time.position;
+            if (that->m_player_time.ts != VLC_TICK_INVALID)
+                that->m_time = that->m_player_time.ts - VLC_TICK_0;
+
+            q->updatePosition();
+            q->updateTime(VLC_TICK_INVALID, false);
+
+            that->m_position_timer.stop();
+            that->m_time_timer.stop();
+        });
+    }
+    else
+        that->seeking = false;
+}
 static void on_player_timer_smpte_update(const struct vlc_player_timer_smpte_timecode *tc,
                                          void *data)
 {
@@ -1049,6 +1078,7 @@ static const vlc_player_timer_cbs player_timer_cbs = []{
     struct vlc_player_timer_cbs cbs {};
     cbs.on_update = on_player_timer_update;
     cbs.on_discontinuity = on_player_timer_discontinuity;
+    cbs.on_seek = on_player_timer_seek;
     return cbs;
 }();
 
@@ -1734,7 +1764,8 @@ void PlayerController::updateTime(vlc_tick_t system_now, bool forceUpdate)
         d->m_remainingTime = VLC_TICK_INVALID;
     emit remainingTimeChanged(d->m_remainingTime);
 
-    if (d->m_player_time.system_date != VLC_TICK_MAX
+    if (system_now != VLC_TICK_INVALID
+     && d->m_player_time.system_date != VLC_TICK_MAX
      && (forceUpdate || !d->m_time_timer.isActive()))
     {
         // Tell the timer to wait until the next second is reached.


=====================================
modules/gui/qt/player/player_controller_p.hpp
=====================================
@@ -107,6 +107,7 @@ public:
     vlc_player_timer_id* m_player_timer = nullptr;
     vlc_player_timer_id* m_player_timer_smpte = nullptr;
     struct vlc_player_timer_point m_player_time;
+    bool seeking = false;
     QTimer m_position_timer;
     QTimer m_time_timer;
 


=====================================
modules/stream_out/chromecast/chromecast_demux.cpp
=====================================
@@ -221,7 +221,7 @@ struct demux_cc
                 ret = demux_Control( p_demux->s, DEMUX_SET_TIME, time, false );
 
             if( ret != VLC_SUCCESS && pos >= 0 )
-                demux_SetPosition( p_demux->s, pos, false, true );
+                demux_SetPosition( p_demux->s, pos, false );
         }
     }
 
@@ -346,7 +346,7 @@ struct demux_cc
         {
             double pos = va_arg( args, double );
             /* Force imprecise seek */
-            int ret = demux_SetPosition( p_demux->s, pos, false, true );
+            int ret = demux_SetPosition( p_demux->s, pos, false );
             if( ret != VLC_SUCCESS )
                 return ret;
 


=====================================
src/input/input.c
=====================================
@@ -1493,16 +1493,6 @@ static size_t ControlGetReducedIndexLocked( input_thread_t *p_input,
         {
             return sys->i_control - 1;
         }
-        else if ( i_ct == INPUT_CONTROL_JUMP_TIME )
-        {
-            c->param.time.i_val += prev_control->param.time.i_val;
-            return sys->i_control - 1;
-        }
-        else if ( i_ct == INPUT_CONTROL_JUMP_POSITION )
-        {
-            c->param.pos.f_val += prev_control->param.pos.f_val;
-            return sys->i_control - 1;
-        }
         else if ( i_ct == INPUT_CONTROL_UPDATE_VIEWPOINT )
         {
             c->param.viewpoint.yaw += prev_control->param.viewpoint.yaw;
@@ -1601,9 +1591,7 @@ static bool ControlIsSeekRequest( int i_type )
     switch( i_type )
     {
     case INPUT_CONTROL_SET_POSITION:
-    case INPUT_CONTROL_JUMP_POSITION:
     case INPUT_CONTROL_SET_TIME:
-    case INPUT_CONTROL_JUMP_TIME:
     case INPUT_CONTROL_SET_TITLE:
     case INPUT_CONTROL_SET_TITLE_NEXT:
     case INPUT_CONTROL_SET_TITLE_PREV:
@@ -1917,9 +1905,7 @@ static bool Control( input_thread_t *p_input,
     switch( i_type )
     {
         case INPUT_CONTROL_SET_POSITION:
-        case INPUT_CONTROL_JUMP_POSITION:
         {
-            const bool absolute = i_type == INPUT_CONTROL_SET_POSITION;
             if( priv->b_recording )
             {
                 msg_Err( p_input, "INPUT_CONTROL_SET_POSITION ignored while recording" );
@@ -1929,12 +1915,10 @@ static bool Control( input_thread_t *p_input,
             /* Reset the decoders states and clock sync (before calling the demuxer */
             es_out_Control( priv->p_es_out, ES_OUT_RESET_PCR );
             if( demux_SetPosition( priv->master->p_demux, param.pos.f_val,
-                                   !param.pos.b_fast_seek, absolute ) )
+                                   !param.pos.b_fast_seek ) )
             {
                 msg_Err( p_input, "INPUT_CONTROL_SET_POSITION "
-                         "%s%2.1f%% failed",
-                         absolute ? "@" : param.pos.f_val >= 0 ? "+" : "",
-                         param.pos.f_val * 100.f );
+                         "%2.1f%% failed", param.pos.f_val * 100.f );
             }
             else
             {
@@ -1948,9 +1932,7 @@ static bool Control( input_thread_t *p_input,
         }
 
         case INPUT_CONTROL_SET_TIME:
-        case INPUT_CONTROL_JUMP_TIME:
         {
-            const bool absolute = i_type == INPUT_CONTROL_SET_TIME;
             int i_ret;
 
             if( priv->b_recording )
@@ -1963,7 +1945,7 @@ static bool Control( input_thread_t *p_input,
             es_out_Control( priv->p_es_out, ES_OUT_RESET_PCR );
 
             i_ret = demux_SetTime( priv->master->p_demux, param.time.i_val,
-                                   !param.time.b_fast_seek, absolute );
+                                   !param.time.b_fast_seek );
             if( i_ret )
             {
                 vlc_tick_t i_length = InputSourceGetLength( priv->master, priv->p_item );
@@ -1972,16 +1954,13 @@ static bool Control( input_thread_t *p_input,
                 {
                     double f_pos = (double)param.time.i_val / (double)i_length;
                     i_ret = demux_SetPosition( priv->master->p_demux, f_pos,
-                                               !param.time.b_fast_seek,
-                                               absolute );
+                                               !param.time.b_fast_seek );
                 }
             }
             if( i_ret )
             {
-                msg_Warn( p_input, "INPUT_CONTROL_SET_TIME %s%"PRId64
-                         " failed or not possible",
-                         absolute ? "@" : param.time.i_val >= 0 ? "+" : "",
-                         param.time.i_val );
+                msg_Warn( p_input, "INPUT_CONTROL_SET_TIME @%"PRId64
+                         " failed or not possible", param.time.i_val );
             }
             else
             {


=====================================
src/input/input_internal.h
=====================================
@@ -557,10 +557,8 @@ enum input_control_e
     INPUT_CONTROL_SET_RATE,
 
     INPUT_CONTROL_SET_POSITION,
-    INPUT_CONTROL_JUMP_POSITION,
 
     INPUT_CONTROL_SET_TIME,
-    INPUT_CONTROL_JUMP_TIME,
 
     INPUT_CONTROL_SET_PROGRAM,
 


=====================================
src/player/input.c
=====================================
@@ -59,25 +59,27 @@ vlc_player_input_HandleAtoBLoop(struct vlc_player_input *input, vlc_tick_t time,
 }
 
 vlc_tick_t
-vlc_player_input_GetTime(struct vlc_player_input *input, vlc_tick_t system_now)
+vlc_player_input_GetTime(struct vlc_player_input *input, bool seeking,
+                         vlc_tick_t system_now)
 {
     vlc_player_t *player = input->player;
     vlc_tick_t ts;
 
     if (input == player->input
-     && vlc_player_GetTimerPoint(player, system_now, &ts, NULL) == 0)
+     && vlc_player_GetTimerPoint(player, seeking, system_now, &ts, NULL) == 0)
         return ts;
     return input->time;
 }
 
 double
-vlc_player_input_GetPos(struct vlc_player_input *input, vlc_tick_t system_now)
+vlc_player_input_GetPos(struct vlc_player_input *input, bool seeking,
+                        vlc_tick_t system_now)
 {
     vlc_player_t *player = input->player;
     double pos;
 
     if (input == player->input
-     && vlc_player_GetTimerPoint(player, system_now, NULL, &pos) == 0)
+     && vlc_player_GetTimerPoint(player, seeking, system_now, NULL, &pos) == 0)
         return pos;
     return input->position;
 }
@@ -89,8 +91,8 @@ vlc_player_input_UpdateTime(struct vlc_player_input *input)
     {
         vlc_tick_t now = vlc_tick_now();
         vlc_player_input_HandleAtoBLoop(input,
-                                        vlc_player_input_GetTime(input, now),
-                                        vlc_player_input_GetPos(input, now));
+                                        vlc_player_input_GetTime(input, false, now),
+                                        vlc_player_input_GetPos(input, false, now));
     }
 }
 
@@ -123,18 +125,24 @@ vlc_player_input_SeekByPos(struct vlc_player_input *input, double position,
     vlc_player_t *player = input->player;
     vlc_player_assert_seek_params(speed, whence);
 
-    const int type =
-        whence == VLC_PLAYER_WHENCE_ABSOLUTE ? INPUT_CONTROL_SET_POSITION
-                                             : INPUT_CONTROL_JUMP_POSITION;
-    int ret = input_ControlPush(input->thread, type,
+    if (whence != VLC_PLAYER_WHENCE_ABSOLUTE)
+        position += vlc_player_input_GetPos(input, true, vlc_tick_now());
+
+    if (position < 0)
+        position = 0;
+    else if (position > 1)
+        position = 1;
+
+    vlc_player_UpdateTimerSeekState(player, VLC_TICK_INVALID, position);
+
+    int ret = input_ControlPush(input->thread, INPUT_CONTROL_SET_POSITION,
         &(input_control_param_t) {
             .pos.f_val = position,
             .pos.b_fast_seek = speed == VLC_PLAYER_SEEK_FAST,
     });
 
     if (ret == VLC_SUCCESS)
-        vlc_player_osd_Position(player, input, VLC_TICK_INVALID, position,
-                                whence);
+        vlc_player_osd_Position(player, input, VLC_TICK_INVALID, position);
 }
 
 void
@@ -145,17 +153,22 @@ vlc_player_input_SeekByTime(struct vlc_player_input *input, vlc_tick_t time,
     vlc_player_t *player = input->player;
     vlc_player_assert_seek_params(speed, whence);
 
-    const int type =
-        whence == VLC_PLAYER_WHENCE_ABSOLUTE ? INPUT_CONTROL_SET_TIME
-                                             : INPUT_CONTROL_JUMP_TIME;
-    int ret = input_ControlPush(input->thread, type,
+    if (whence != VLC_PLAYER_WHENCE_ABSOLUTE)
+        time += vlc_player_input_GetTime(input, true, vlc_tick_now());
+
+    if (time < VLC_TICK_0)
+        time = VLC_TICK_0;
+
+    vlc_player_UpdateTimerSeekState(player, time, -1);
+
+    int ret = input_ControlPush(input->thread, INPUT_CONTROL_SET_TIME,
         &(input_control_param_t) {
             .time.i_val = time,
             .time.b_fast_seek = speed == VLC_PLAYER_SEEK_FAST,
     });
 
     if (ret == VLC_SUCCESS)
-        vlc_player_osd_Position(player, input, time, -1, whence);
+        vlc_player_osd_Position(player, input, time, -1);
 }
 
 void


=====================================
src/player/osd.c
=====================================
@@ -119,10 +119,8 @@ vlc_player_osd_Icon(vlc_player_t *player, short type)
 void
 vlc_player_osd_Position(vlc_player_t *player,
                         struct vlc_player_input *input, vlc_tick_t time,
-                        double position, enum vlc_player_whence whence)
+                        double position)
 {
-    vlc_tick_t now = vlc_tick_now();
-
     if (input->length != VLC_TICK_INVALID)
     {
         if (time == VLC_TICK_INVALID)
@@ -136,13 +134,6 @@ vlc_player_osd_Position(vlc_player_t *player,
 
     if (time != VLC_TICK_INVALID)
     {
-        if (whence == VLC_PLAYER_WHENCE_RELATIVE)
-        {
-            time += vlc_player_input_GetTime(input, now);
-            if (time < 0)
-                time = 0;
-        }
-
         char time_text[MSTRTIME_MAX_SIZE];
         vlc_tick_to_str(time_text, time);
         if (input->length != VLC_TICK_INVALID)
@@ -156,15 +147,7 @@ vlc_player_osd_Position(vlc_player_t *player,
     }
 
     if (vlc_player_vout_IsFullscreen(player))
-    {
-        if (whence == VLC_PLAYER_WHENCE_RELATIVE)
-        {
-            position += vlc_player_input_GetPos(input, now);
-            if (position < 0.f)
-                position = 0.f;
-        }
         vouts_osd_Slider(vouts, count, position * 100, OSD_HOR_SLIDER);
-    }
     vlc_player_osd_ReleaseAll(player, vouts, count);
 }
 


=====================================
src/player/player.c
=====================================
@@ -1378,7 +1378,7 @@ vlc_player_GetTime(vlc_player_t *player)
     if (!input)
         return VLC_TICK_INVALID;
 
-    return vlc_player_input_GetTime(input, vlc_tick_now());
+    return vlc_player_input_GetTime(input, false, vlc_tick_now());
 }
 
 double
@@ -1386,7 +1386,7 @@ vlc_player_GetPosition(vlc_player_t *player)
 {
     struct vlc_player_input *input = vlc_player_get_input_locked(player);
 
-    return input ? vlc_player_input_GetPos(input, vlc_tick_now()) : -1.f;
+    return input ? vlc_player_input_GetPos(input, false, vlc_tick_now()) : -1.f;
 }
 
 void
@@ -1398,9 +1398,8 @@ vlc_player_DisplayPosition(vlc_player_t *player)
 
     vlc_tick_t now = vlc_tick_now();
     vlc_player_osd_Position(player, input,
-                            vlc_player_input_GetTime(input, now),
-                            vlc_player_input_GetPos(input, now),
-                            VLC_PLAYER_WHENCE_ABSOLUTE);
+                            vlc_player_input_GetTime(input, false, now),
+                            vlc_player_input_GetPos(input, false, now));
 }
 
 void


=====================================
src/player/player.h
=====================================
@@ -215,13 +215,16 @@ struct vlc_player_timer
     vlc_mutex_t lock;
 
     enum vlc_player_timer_state state;
-    bool seeking;
 
     vlc_tick_t input_length;
     vlc_tick_t input_normal_time;
     vlc_tick_t last_ts;
     double input_position;
 
+    vlc_tick_t seek_ts;
+    double seek_position;
+    bool seeking;
+
     struct vlc_player_timer_source sources[VLC_PLAYER_TIMER_TYPE_COUNT];
 #define best_source sources[VLC_PLAYER_TIMER_TYPE_BEST]
 #define smpte_source sources[VLC_PLAYER_TIMER_TYPE_SMPTE]
@@ -437,10 +440,12 @@ vlc_player_input_GetSelectedTrackStringIds(struct vlc_player_input *input,
                                            enum es_format_category_e cat) VLC_MALLOC;
 
 vlc_tick_t
-vlc_player_input_GetTime(struct vlc_player_input *input, vlc_tick_t system_now);
+vlc_player_input_GetTime(struct vlc_player_input *input, bool seeking,
+                         vlc_tick_t system_now);
 
 double
-vlc_player_input_GetPos(struct vlc_player_input *input, vlc_tick_t system_now);
+vlc_player_input_GetPos(struct vlc_player_input *input, bool seeking,
+                        vlc_tick_t system_now);
 
 int
 vlc_player_input_Start(struct vlc_player_input *input);
@@ -482,6 +487,10 @@ vlc_player_UpdateTimerState(vlc_player_t *player, vlc_es_id_t *es_source,
                             enum vlc_player_timer_state state,
                             vlc_tick_t system_date);
 
+void
+vlc_player_UpdateTimerSeekState(vlc_player_t *player, vlc_tick_t time,
+                                double position);
+
 void
 vlc_player_UpdateTimer(vlc_player_t *player, vlc_es_id_t *es_source,
                        bool es_source_is_master,
@@ -493,7 +502,8 @@ void
 vlc_player_RemoveTimerSource(vlc_player_t *player, vlc_es_id_t *es_source);
 
 int
-vlc_player_GetTimerPoint(vlc_player_t *player, vlc_tick_t system_now,
+vlc_player_GetTimerPoint(vlc_player_t *player, bool seeking,
+                         vlc_tick_t system_now,
                          vlc_tick_t *out_ts, double *out_pos);
 
 /*
@@ -529,7 +539,7 @@ vlc_player_osd_Icon(vlc_player_t *player, short type);
 void
 vlc_player_osd_Position(vlc_player_t *player,
                         struct vlc_player_input *input, vlc_tick_t time,
-                        double position, enum vlc_player_whence whence);
+                        double position);
 void
 vlc_player_osd_Volume(vlc_player_t *player, bool mute_action);
 


=====================================
src/player/timer.c
=====================================
@@ -37,10 +37,28 @@ vlc_player_ResetTimer(vlc_player_t *player)
     player->timer.last_ts = VLC_TICK_INVALID;
     player->timer.input_position = 0;
     player->timer.smpte_source.smpte.last_framenum = ULONG_MAX;
+    player->timer.seek_ts = VLC_TICK_INVALID;
+    player->timer.seek_position = -1;
+    player->timer.seeking = false;
 
     vlc_mutex_unlock(&player->timer.lock);
 }
 
+static void
+vlc_player_SendTimerSeek(vlc_player_t *player,
+                         struct vlc_player_timer_source *source,
+                         const struct vlc_player_timer_point *point)
+{
+    (void) player;
+    vlc_player_timer_id *timer;
+
+    vlc_list_foreach(timer, &source->listeners, node)
+    {
+        if (timer->cbs->on_seek != NULL)
+            timer->cbs->on_seek(point, timer->data);
+    }
+}
+
 static void
 vlc_player_SendTimerSourceUpdates(vlc_player_t *player,
                                   struct vlc_player_timer_source *source,
@@ -194,8 +212,22 @@ vlc_player_UpdateTimerState(vlc_player_t *player, vlc_es_id_t *es_source,
                 if (source->es != es_source)
                     continue;
                 /* signal discontinuity only on best source */
-                if (source->point.system_date != VLC_TICK_INVALID)
-                    notify = bestsource->es == es_source;
+                if (bestsource->es == es_source)
+                {
+                    /* And only once */
+                    if (source->point.system_date != VLC_TICK_INVALID)
+                        notify = true;
+
+                    /* There can be several discontinuities on the same source
+                     * for one seek request, hence the need of the
+                     * 'timer.seeking' variable to notify only once the end of
+                     * the seek request. */
+                    if (player->timer.seeking)
+                    {
+                        player->timer.seeking = false;
+                        vlc_player_SendTimerSeek(player, bestsource, NULL);
+                    }
+                }
                 source->point.system_date = VLC_TICK_INVALID;
             }
             break;
@@ -228,6 +260,47 @@ vlc_player_UpdateTimerState(vlc_player_t *player, vlc_es_id_t *es_source,
     vlc_mutex_unlock(&player->timer.lock);
 }
 
+void
+vlc_player_UpdateTimerSeekState(vlc_player_t *player, vlc_tick_t time,
+                                double position)
+{
+    vlc_mutex_lock(&player->timer.lock);
+    struct vlc_player_timer_source *source = &player->timer.best_source;
+
+    if (time == VLC_TICK_INVALID)
+    {
+        assert(position >= 0);
+        if (source->point.length != VLC_TICK_INVALID)
+            player->timer.seek_ts = position * source->point.length;
+        else
+            player->timer.seek_ts = VLC_TICK_INVALID;
+    }
+    else
+        player->timer.seek_ts = time;
+
+    if (position < 0)
+    {
+        assert(time != VLC_TICK_INVALID);
+        if (source->point.length != VLC_TICK_INVALID)
+            player->timer.seek_position = time / (double) source->point.length;
+    }
+    else
+        player->timer.seek_position = position;
+
+    const struct vlc_player_timer_point point =
+    {
+        .position = player->timer.seek_position,
+        .rate = source->point.rate,
+        .ts = player->timer.seek_ts,
+        .length = source->point.length,
+        .system_date = VLC_TICK_MAX,
+    };
+
+    player->timer.seeking = true;
+    vlc_player_SendTimerSeek(player, source, &point);
+    vlc_mutex_unlock(&player->timer.lock);
+}
+
 static void
 vlc_player_UpdateTimerSource(vlc_player_t *player,
                              struct vlc_player_timer_source *source,
@@ -340,6 +413,17 @@ vlc_player_UpdateTimer(vlc_player_t *player, vlc_es_id_t *es_source,
             vlc_player_UpdateTimerSource(player, source, point->rate, point->ts,
                                          system_date);
 
+            /* It is possible to receive valid points while seeking. These
+             * points could be updated when the input thread didn't yet process
+             * the seek request. */
+            if (!player->timer.seeking)
+            {
+                /* Reset seek time/position now that we receive a valid point
+                 * and seek was processed */
+                player->timer.seek_ts = VLC_TICK_INVALID;
+                player->timer.seek_position = -1;
+            }
+
             if (!vlc_list_is_empty(&source->listeners))
                 vlc_player_SendTimerSourceUpdates(player, source, force_update,
                                                   &source->point);
@@ -384,6 +468,14 @@ void
 vlc_player_RemoveTimerSource(vlc_player_t *player, vlc_es_id_t *es_source)
 {
     vlc_mutex_lock(&player->timer.lock);
+
+    /* Unlikely case where the source ES is deleted while seeking */
+    if (player->timer.best_source.es == es_source && player->timer.seeking)
+    {
+        player->timer.seeking = false;
+        vlc_player_SendTimerSeek(player, &player->timer.best_source, NULL);
+    }
+
     for (size_t i = 0; i < VLC_PLAYER_TIMER_TYPE_COUNT; ++i)
     {
         struct vlc_player_timer_source *source = &player->timer.sources[i];
@@ -398,23 +490,41 @@ vlc_player_RemoveTimerSource(vlc_player_t *player, vlc_es_id_t *es_source)
 }
 
 int
-vlc_player_GetTimerPoint(vlc_player_t *player, vlc_tick_t system_now,
+vlc_player_GetTimerPoint(vlc_player_t *player, bool seeking,
+                         vlc_tick_t system_now,
                          vlc_tick_t *out_ts, double *out_pos)
 {
-    int ret;
+    int ret = VLC_EGENERIC;
     vlc_mutex_lock(&player->timer.lock);
-    if (player->timer.best_source.point.system_date == VLC_TICK_INVALID)
+    if (seeking
+     && (player->timer.seek_ts != VLC_TICK_INVALID || player->timer.seek_position >= 0.0f))
     {
-        vlc_mutex_unlock(&player->timer.lock);
-        return VLC_EGENERIC;
+        if (out_ts != NULL)
+        {
+            if (player->timer.seek_ts == VLC_TICK_INVALID)
+                goto end;
+            *out_ts = player->timer.seek_ts;
+        }
+        if (out_pos != NULL)
+        {
+            if (player->timer.seek_position < 0)
+                goto end;
+            *out_pos = player->timer.seek_position;
+        }
+        ret = VLC_SUCCESS;
+        goto end;
     }
 
+    if (player->timer.best_source.point.system_date == VLC_TICK_INVALID)
+        goto end;
+
     if (system_now != VLC_TICK_INVALID)
         ret = vlc_player_timer_point_Interpolate(&player->timer.best_source.point,
                                                  system_now, out_ts, out_pos);
     else
         ret = VLC_SUCCESS;
 
+end:
     vlc_mutex_unlock(&player->timer.lock);
     return ret;
 }



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4ea2f636707f67ccb6be74fb51da86b0cb120519...c20e45433545cc4974cffdbf9feda42aaefaa76a

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4ea2f636707f67ccb6be74fb51da86b0cb120519...c20e45433545cc4974cffdbf9feda42aaefaa76a
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list