[vlc-commits] [Git][videolan/vlc][master] 3 commits: demux: forward live state to es_out/input_event

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Sat Jul 12 13:25:25 UTC 2025



Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
f7ee9b03 by Thomas Guillem at 2025-07-12T13:10:36+00:00
demux: forward live state to es_out/input_event

This will be used by the player timer.

- - - - -
f60d33c6 by Thomas Guillem at 2025-07-12T13:10:36+00:00
player: timer: handle live state

If live is true, then the length represents the seek range and the
position variable is the position within that seek range.

Don't interpolate position with length in that case.

The timer live variable could be used by UI to change sliders design
accordingly.

This will allow fixing the 3.0 regression where it was impossible to
seek within a seek range with live streams.

- - - - -
d3a2408a by Thomas Guillem at 2025-07-12T13:10:36+00:00
demux: adaptive: forward live property

Fixes incoherent slider and seek with adaptive live streams.

- - - - -


12 changed files:

- include/vlc_demux.h
- include/vlc_player.h
- modules/demux/adaptive/PlaylistManager.cpp
- src/input/es_out.c
- src/input/es_out.h
- src/input/es_out_timeshift.c
- src/input/event.h
- src/input/input.c
- src/input/input_internal.h
- src/player/input.c
- src/player/player.h
- src/player/timer.c


Changes:

=====================================
include/vlc_demux.h
=====================================
@@ -185,7 +185,14 @@ enum demux_query_e
 
     /* LENGTH/TIME in microsecond, 0 if unknown */
     DEMUX_GET_LENGTH,           /* arg1= vlc_tick_t *   res=    */
-    DEMUX_GET_TIME,             /* arg1= vlc_tick_t *   res=    */
+    /**
+     * Get time and live state
+     *
+     * Set arg2 to true if the stream is live. In that case DEMUX_GET_LENGTH
+     * will represent a seek range, and DEMUX_GET_POSITION the position within
+     * that seek range.
+     * arg1= vlc_tick_t *, arg2 bool * res= */
+    DEMUX_GET_TIME,
     DEMUX_SET_TIME,             /* arg1= vlc_tick_t arg2= bool b_precise   res=can fail    */
     /* Normal or original time, used mainly by the ts module */
     DEMUX_GET_NORMAL_TIME,      /* arg1= vlc_tick_t *   res= can fail, in that case VLC_TICK_0 will be used as NORMAL_TIME */


=====================================
include/vlc_player.h
=====================================
@@ -3339,6 +3339,9 @@ struct vlc_player_timer_point
     vlc_tick_t ts;
     /** Valid length >= VLC_TICK_0 or VLC_TICK_INVALID */
     vlc_tick_t length;
+    /** if true, length represents the seek range and position is the position
+     * within that seek_range */
+    bool live;
     /** System date of this record (always valid), this date can be in the
      * future or in the past. The special value of INT64_MAX mean that the
      * clock was paused when this point was updated. In that case,


=====================================
modules/demux/adaptive/PlaylistManager.cpp
=====================================
@@ -616,6 +616,7 @@ int PlaylistManager::doControl(int i_query, va_list args)
             if(cached.b_live && cached.playlistLength == 0)
                 return VLC_EGENERIC;
             *(va_arg (args, vlc_tick_t *)) = cached.playlistLength;
+            *(va_arg (args, bool *)) = cached.b_live;
             break;
         }
 


=====================================
src/input/es_out.c
=====================================
@@ -3928,6 +3928,7 @@ static int EsOutVaPrivControlLocked(es_out_sys_t *p_sys, input_source_t *source,
         vlc_tick_t i_time = va_arg( args, vlc_tick_t );
         vlc_tick_t i_normal_time = va_arg( args, vlc_tick_t );
         vlc_tick_t i_length = va_arg( args, vlc_tick_t );
+        bool b_live = va_arg( args, int );
 
         if (i_normal_time != VLC_TICK_INVALID)
             source->i_normal_time = i_normal_time;
@@ -3938,7 +3939,7 @@ static int EsOutVaPrivControlLocked(es_out_sys_t *p_sys, input_source_t *source,
         if (p_sys->b_buffering)
         {
             input_SendEventTimes(p_sys->p_input, 0.0, VLC_TICK_INVALID,
-                                 i_normal_time, i_length);
+                                 i_normal_time, i_length, b_live);
             return VLC_SUCCESS;
         }
 
@@ -3964,7 +3965,7 @@ static int EsOutVaPrivControlLocked(es_out_sys_t *p_sys, input_source_t *source,
             f_position = 0;
 
         input_SendEventTimes(p_sys->p_input, f_position, i_time,
-                             i_normal_time, i_length);
+                             i_normal_time, i_length, b_live);
         return VLC_SUCCESS;
     }
     case ES_OUT_PRIV_SET_JITTER:


=====================================
src/input/es_out.h
=====================================
@@ -86,7 +86,7 @@ enum es_out_query_private_e
     ES_OUT_PRIV_SET_FRAME_NEXT,                     /*                          res=can fail */
 
     /* Set position/time/length */
-    ES_OUT_PRIV_SET_TIMES,                          /* arg1=double f_position arg2=vlc_tick_t i_time arg3=vlc_tick_t i_normal_time arg4=vlc_tick_t i_length res=cannot fail */
+    ES_OUT_PRIV_SET_TIMES,                          /* arg1=double f_position arg2=vlc_tick_t i_time arg3=vlc_tick_t i_normal_time arg4=vlc_tick_t i_length arg5 int b_live res=cannot fail */
 
     /* Set jitter */
     ES_OUT_PRIV_SET_JITTER,                         /* arg1=vlc_tick_t i_pts_delay arg2= vlc_tick_t i_pts_jitter, arg2=int i_cr_average res=cannot fail */
@@ -271,10 +271,10 @@ es_out_SetFrameNext(struct vlc_input_es_out *out )
 static inline void
 es_out_SetTimes(struct vlc_input_es_out *out, double f_position,
                 vlc_tick_t i_time, vlc_tick_t i_normal_time,
-                vlc_tick_t i_length )
+                vlc_tick_t i_length, bool b_live  )
 {
     int i_ret = es_out_PrivControl(out, ES_OUT_PRIV_SET_TIMES, f_position, i_time,
-                                   i_normal_time, i_length);
+                                   i_normal_time, i_length, b_live);
     assert( !i_ret );
 }
 


=====================================
src/input/es_out_timeshift.c
=====================================
@@ -170,6 +170,7 @@ typedef struct attribute_packed
             vlc_tick_t i_time;
             vlc_tick_t i_normal_time;
             vlc_tick_t i_length;
+            vlc_tick_t b_live;
         } times;
     } u;
 } ts_cmd_privcontrol_t;
@@ -1863,11 +1864,13 @@ static int CmdInitPrivControl( ts_cmd_privcontrol_t *p_cmd, input_source_t *in,
         vlc_tick_t i_time = va_arg( args, vlc_tick_t );
         vlc_tick_t i_normal_time = va_arg( args, vlc_tick_t );
         vlc_tick_t i_length = va_arg( args, vlc_tick_t );
+        bool b_live = va_arg( args, int );
 
         p_cmd->u.times.f_position = f_position;
         p_cmd->u.times.i_time = i_time;
         p_cmd->u.times.i_normal_time = i_normal_time;
         p_cmd->u.times.i_length = i_length;
+        p_cmd->u.times.b_live = b_live;
         break;
     }
     case ES_OUT_PRIV_SET_EOS: /* no arg */
@@ -1897,7 +1900,8 @@ static int CmdExecutePrivControl(struct es_out_timeshift *p_sys, ts_cmd_privcont
                                       p_cmd->u.times.f_position,
                                       p_cmd->u.times.i_time,
                                       p_cmd->u.times.i_normal_time,
-                                      p_cmd->u.times.i_length );
+                                      p_cmd->u.times.i_length,
+                                      p_cmd->u.times.b_live );
     case ES_OUT_PRIV_SET_EOS: /* no arg */
         return es_out_in_PrivControl( p_sys->p_out, in, i_query );
     default: vlc_assert_unreachable();


=====================================
src/input/event.h
=====================================
@@ -62,11 +62,12 @@ static inline void input_SendEventCapabilities(input_thread_t *p_input,
 static inline void input_SendEventTimes(input_thread_t *p_input,
                                         double f_position, vlc_tick_t i_time,
                                         vlc_tick_t i_normal_time,
-                                        vlc_tick_t i_length)
+                                        vlc_tick_t i_length,
+                                        bool b_live)
 {
     input_SendEvent(p_input, &(struct vlc_input_event) {
         .type = INPUT_EVENT_TIMES,
-        .times = { f_position, i_time, i_normal_time, i_length }
+        .times = { f_position, i_time, i_normal_time, i_length, b_live }
     });
 }
 


=====================================
src/input/input.c
=====================================
@@ -557,12 +557,23 @@ static int MainLoopTryRepeat( input_thread_t *p_input )
     return VLC_SUCCESS;
 }
 
-static vlc_tick_t InputSourceGetLength( input_source_t *source, input_item_t *item )
+static vlc_tick_t InputSourceGetLength( input_source_t *source, input_item_t *item,
+                                        bool *live )
 {
     vlc_tick_t length;
-    if( demux_Control( source->p_demux, DEMUX_GET_LENGTH, &length ) )
-        length = 0;
-    if( length == 0 && item != NULL )
+    bool ignored;
+    bool *liveptr;
+    if (live == NULL)
+        liveptr = &ignored;
+    else
+    {
+        liveptr = live;
+        *liveptr = false;
+    }
+
+    if( demux_Control( source->p_demux, DEMUX_GET_LENGTH, &length, liveptr ) )
+        length = VLC_TICK_INVALID;
+    if( length == VLC_TICK_INVALID && item != NULL )
         length = input_item_GetDuration( item );
 
     return length;
@@ -584,13 +595,15 @@ static void InputSourceStatistics(input_source_t *source, input_item_t *item,
     if( demux_Control( source->p_demux, DEMUX_GET_TIME, &i_time ) )
         i_time = VLC_TICK_INVALID;
 
-    i_length = InputSourceGetLength( source, item );
+    bool live;
+    i_length = InputSourceGetLength( source, item, &live );
 
     /* In case of failure (not implemented or in case of seek), use VLC_TICK_INVALID. */
     if (demux_Control( source->p_demux, DEMUX_GET_NORMAL_TIME, &i_normal_time ) != VLC_SUCCESS)
         i_normal_time = VLC_TICK_INVALID;
 
-    es_out_SetTimes( out, f_position, i_time, i_normal_time, i_length );
+    es_out_SetTimes( out, f_position, i_time, i_normal_time, i_length,
+                     live );
 }
 
 /**
@@ -1944,7 +1957,7 @@ 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->out, ES_OUT_RESET_PCR);
-            vlc_tick_t i_length = InputSourceGetLength(priv->master, priv->p_item);
+            vlc_tick_t i_length = InputSourceGetLength(priv->master, priv->p_item, NULL);
             double f_val;
             if( i_length > 0 )
             {
@@ -1990,7 +2003,7 @@ static bool Control( input_thread_t *p_input,
                                    !param.time.b_fast_seek );
             if( i_ret )
             {
-                vlc_tick_t i_length = InputSourceGetLength( priv->master, priv->p_item );
+                vlc_tick_t i_length = InputSourceGetLength( priv->master, priv->p_item, NULL );
                 /* Emulate it with a SET_POS */
                 if( i_length > 0 )
                 {


=====================================
src/input/input_internal.h
=====================================
@@ -173,6 +173,7 @@ struct vlc_input_event_times
     vlc_tick_t time;
     vlc_tick_t normal_time;
     vlc_tick_t length;
+    bool live;
 };
 
 struct vlc_input_event_output_clock


=====================================
src/player/input.c
=====================================
@@ -956,6 +956,12 @@ input_thread_Events(input_thread_t *input_thread,
                 changed = true;
             }
 
+            if (input->live != event->times.live)
+            {
+                input->live = event->times.live;
+                changed = true;
+            }
+
             if (input->normal_time != event->times.normal_time)
             {
                 input->normal_time = event->times.normal_time;
@@ -969,6 +975,7 @@ input_thread_Events(input_thread_t *input_thread,
                     .rate = input->rate,
                     .ts = input->time,
                     .length = input->length,
+                    .live = input->live,
                     .system_date = system_date,
                 };
                 vlc_player_UpdateTimer(player, NULL, false, &point,
@@ -1120,6 +1127,7 @@ vlc_player_input_New(vlc_player_t *player, input_item_t *item)
     input->rate = 1.f;
     input->capabilities = 0;
     input->length = input->time = VLC_TICK_INVALID;
+    input->live = false;
     input->normal_time = VLC_TICK_0;
     input->pause_date = VLC_TICK_INVALID;
     input->position = 0.f;


=====================================
src/player/player.h
=====================================
@@ -67,6 +67,7 @@ struct vlc_player_input
     float rate;
     int capabilities;
     vlc_tick_t length;
+    bool live;
 
     double position;
     vlc_tick_t time;
@@ -215,6 +216,7 @@ struct vlc_player_timer
 {
     vlc_mutex_t lock;
 
+    bool input_live;
     vlc_tick_t input_length;
     vlc_tick_t input_normal_time;
     vlc_tick_t last_ts;


=====================================
src/player/timer.c
=====================================
@@ -31,6 +31,7 @@ vlc_player_ResetTimer(vlc_player_t *player)
 {
     vlc_mutex_lock(&player->timer.lock);
 
+    player->timer.input_live = false;
     player->timer.input_length = VLC_TICK_INVALID;
     player->timer.input_normal_time = VLC_TICK_0;
     player->timer.last_ts = VLC_TICK_INVALID;
@@ -288,7 +289,7 @@ vlc_player_UpdateTimerSeekState(vlc_player_t *player, vlc_tick_t time,
     if (position < 0)
     {
         assert(time != VLC_TICK_INVALID);
-        if (source->point.length != VLC_TICK_INVALID)
+        if (source->point.length != VLC_TICK_INVALID && !source->point.live)
             player->timer.seek_position = time / (double) source->point.length;
     }
     else
@@ -300,6 +301,7 @@ vlc_player_UpdateTimerSeekState(vlc_player_t *player, vlc_tick_t time,
         .rate = source->point.rate,
         .ts = player->timer.seek_ts,
         .length = source->point.length,
+        .live = source->point.live,
         .system_date = VLC_TICK_MAX,
     };
 
@@ -319,6 +321,7 @@ vlc_player_UpdateTimerSource(vlc_player_t *player,
     source->point.rate = rate;
     source->point.ts = ts - player->timer.input_normal_time - player->timer.start_offset + VLC_TICK_0;
     source->point.length = player->timer.input_length;
+    source->point.live = player->timer.input_live;
 
     /* Put an invalid date for the first point in order to disable
      * interpolation (behave as paused), indeed, we should wait for one more
@@ -328,7 +331,7 @@ vlc_player_UpdateTimerSource(vlc_player_t *player,
     else
         source->point.system_date = system_date;
 
-    if (source->point.length != VLC_TICK_INVALID)
+    if (source->point.length != VLC_TICK_INVALID && !source->point.live)
         source->point.position = (ts - player->timer.input_normal_time - player->timer.start_offset)
                                / (double) source->point.length;
     else
@@ -460,6 +463,11 @@ vlc_player_UpdateTimer(vlc_player_t *player, vlc_es_id_t *es_source,
             player->timer.last_ts = VLC_TICK_INVALID;
             force_update = true;
         }
+        if (player->timer.input_live != point->live)
+        {
+            player->timer.input_live = point->live;
+            force_update = true;
+        }
         if (start_offset > 0)
             player->timer.start_offset = start_offset;
         /* Will likely be overridden by non input source */
@@ -644,7 +652,7 @@ vlc_player_timer_point_Interpolate(const struct vlc_player_timer_point *point,
         if (unlikely(ts < VLC_TICK_0))
             return VLC_EGENERIC;
     }
-    if (point->length != VLC_TICK_INVALID)
+    if (point->length != VLC_TICK_INVALID && !point->live)
     {
         pos += drift / (double) point->length;
         if (unlikely(pos < 0.f))



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4b63d1a94426057116056acaf0faf87712ac6b44...d3a2408afa6763d5098c8c77e1de74b95b03b61e

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4b63d1a94426057116056acaf0faf87712ac6b44...d3a2408afa6763d5098c8c77e1de74b95b03b61e
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