[vlc-commits] [Git][videolan/vlc][master] 7 commits: clock: continue to convert when paused

Steve Lhomme (@robUx4) gitlab at videolan.org
Fri Dec 15 09:12:56 UTC 2023



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
9a041d1c by Thomas Guillem at 2023-12-15T08:42:52+00:00
clock: continue to convert when paused

The paused state is already sent to all outputs, outputs might want to
convert timestamps while paused.

This is the case for the SPU output that need to select subpictures to
be displayed while paused. The SPU output still won't select the next
subpictures, since the vout will be paused and will always try to play
the same picture with the same converted TS.

Fixes #28429

- - - - -
75b861df by Thomas Guillem at 2023-12-15T08:42:52+00:00
aout: remove paused clock handling

It's not possible anymore and the output is already aware of the paused
state.

- - - - -
032cee86 by Thomas Guillem at 2023-12-15T08:42:52+00:00
vout: remove paused clock handling

It's not possible anymore and the output is already aware of the paused
state.

Refs #28429

- - - - -
8404c39e by Thomas Guillem at 2023-12-15T08:42:52+00:00
vout: spu: remove paused clock handling

It's not possible anymore and the output is already aware of the paused
state.

Refs #28429

- - - - -
1dabd6d9 by Thomas Guillem at 2023-12-15T08:42:52+00:00
test: clock: remove pointer check

master is always valid here.

- - - - -
0569e1cd by Thomas Guillem at 2023-12-15T08:42:52+00:00
test: clock: add new test type

- - - - -
1d20f89b by Thomas Guillem at 2023-12-15T08:42:52+00:00
test: clock: add pause scenarios

- - - - -


6 changed files:

- src/audio_output/dec.c
- src/clock/clock.c
- src/clock/clock.h
- src/video_output/video_output.c
- src/video_output/vout_subpictures.c
- test/src/clock/clock.c


Changes:

=====================================
src/audio_output/dec.c
=====================================
@@ -471,8 +471,8 @@ static void stream_HandleDrift(vlc_aout_stream *stream, vlc_tick_t drift,
 
     float rate = stream->sync.rate;
 
-    if (unlikely(drift == VLC_TICK_MAX) || owner->bitexact)
-        return; /* cf. VLC_TICK_MAX comment in vlc_aout_stream_Play() */
+    if (owner->bitexact)
+        return;
 
     struct vlc_tracer *tracer = aout_stream_tracer(stream);
     if (tracer != NULL)
@@ -773,14 +773,7 @@ int vlc_aout_stream_Play(vlc_aout_stream *stream, block_t *block)
     vlc_tick_t play_date =
         vlc_clock_ConvertToSystem(stream->sync.clock, system_now, original_pts,
                                   stream->sync.rate);
-    if (unlikely(play_date == VLC_TICK_MAX))
-    {
-        /* The clock is paused but not the output, play the audio anyway since
-         * we can't delay audio playback from here. */
-        play_date = system_now;
-    }
-    else
-        stream_Synchronize(stream, system_now, play_date, original_pts);
+    stream_Synchronize(stream, system_now, play_date, original_pts);
 
     vlc_audio_meter_Process(&owner->meter, block, play_date);
 


=====================================
src/clock/clock.c
=====================================
@@ -387,8 +387,6 @@ static vlc_tick_t vlc_clock_slave_to_system_locked(vlc_clock_t *clock,
                                                    vlc_tick_t ts, double rate)
 {
     vlc_clock_main_t *main_clock = clock->owner;
-    if (main_clock->pause_date != VLC_TICK_INVALID)
-        return VLC_TICK_MAX;
 
     vlc_tick_t system = main_stream_to_system(main_clock, ts);
     if (system == VLC_TICK_INVALID)


=====================================
src/clock/clock.h
=====================================
@@ -162,7 +162,7 @@ void vlc_clock_Delete(vlc_clock_t *clock);
  * @param rate the current playback speed
  *
  * @return a valid drift relative time, VLC_TICK_INVALID if there is no drift
- * (clock is master) or VLC_TICK_MAX if the clock is paused
+ * (clock is master)
  */
 vlc_tick_t vlc_clock_Update(vlc_clock_t *clock, vlc_tick_t system_now,
                             vlc_tick_t ts, double rate);
@@ -247,7 +247,7 @@ int vlc_clock_RegisterEvents(vlc_clock_t *clock,
  *
  * The clock mutex must be locked.
  *
- * @return the valid system time or VLC_TICK_MAX when the clock is paused
+ * @return the valid system time
  */
 vlc_tick_t vlc_clock_ConvertToSystemLocked(vlc_clock_t *clock,
                                            vlc_tick_t system_now, vlc_tick_t ts,


=====================================
src/video_output/video_output.c
=====================================
@@ -984,8 +984,7 @@ static picture_t *PreparePicture(vout_thread_sys_t *vout, bool reuse_decoded,
                         vlc_clock_ConvertToSystem(sys->clock, system_now,
                                                   decoded->date, sys->rate);
 
-                    if (system_pts != VLC_TICK_MAX &&
-                        IsPictureLate(vout, decoded, system_now, system_pts))
+                    if (IsPictureLate(vout, decoded, system_now, system_pts))
                     {
                         picture_Release(decoded);
                         vout_statistic_AddLost(&sys->statistic, 1);
@@ -1128,7 +1127,7 @@ static vlc_render_subpicture *RenderSPUs(vout_thread_sys_t *sys,
 }
 
 static int PrerenderPicture(vout_thread_sys_t *sys, picture_t *filtered,
-                            bool *render_now, picture_t **out_pic,
+                            picture_t **out_pic,
                             vlc_render_subpicture **out_subpic)
 {
     vout_display_t *vd = sys->display;
@@ -1145,15 +1144,6 @@ static int PrerenderPicture(vout_thread_sys_t *sys, picture_t *filtered,
         render_subtitle_date = filtered->date <= VLC_TICK_0 ? system_now :
             vlc_clock_ConvertToSystem(sys->clock, system_now, filtered->date,
                                       sys->rate);
-
-        /* The clock is paused, it's too late to fallback to the previous
-         * picture, display the current picture anyway and force the rendering
-         * to now. */
-        if (unlikely(render_subtitle_date == VLC_TICK_MAX))
-        {
-            render_subtitle_date = system_now;
-            *render_now = true;
-        }
     }
 
     /*
@@ -1310,7 +1300,7 @@ static int RenderPicture(vout_thread_sys_t *sys, bool render_now)
 
     picture_t *todisplay;
     vlc_render_subpicture *subpic;
-    int ret = PrerenderPicture(sys, filtered, &render_now, &todisplay, &subpic);
+    int ret = PrerenderPicture(sys, filtered, &todisplay, &subpic);
     if (ret != VLC_SUCCESS)
     {
         vlc_queuedmutex_unlock(&sys->display_lock);
@@ -1321,14 +1311,6 @@ static int RenderPicture(vout_thread_sys_t *sys, bool render_now)
     const vlc_tick_t pts = todisplay->date;
     vlc_tick_t system_pts = render_now ? system_now :
         vlc_clock_ConvertToSystem(sys->clock, system_now, pts, sys->rate);
-    if (unlikely(system_pts == VLC_TICK_MAX))
-    {
-        /* The clock is paused, it's too late to fallback to the previous
-         * picture, display the current picture anyway and force the rendering
-         * to now. */
-        system_pts = system_now;
-        render_now = true;
-    }
 
     const unsigned frame_rate = todisplay->format.i_frame_rate;
     const unsigned frame_rate_base = todisplay->format.i_frame_rate_base;
@@ -1477,9 +1459,6 @@ static bool UpdateCurrentPicture(vout_thread_sys_t *sys)
     const vlc_tick_t system_swap_current =
         vlc_clock_ConvertToSystem(sys->clock, system_now,
                                   sys->displayed.current->date, sys->rate);
-    if (unlikely(system_swap_current == VLC_TICK_MAX))
-        // the clock is paused but the vout thread is not ?
-        return false;
 
     const vlc_tick_t render_delay = vout_chrono_GetHigh(&sys->chrono.render) + VOUT_MWAIT_TOLERANCE;
     vlc_tick_t system_prepare_current = system_swap_current - render_delay;


=====================================
src/video_output/vout_subpictures.c
=====================================
@@ -647,31 +647,12 @@ static size_t spu_channel_UpdateDates(struct spu_channel *channel,
     {
         assert(entry);
 
-        vlc_tick_t ts;
+        entry->start = vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
+                                                       entry->orgstart, channel->rate);
 
-        ts = vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
-                                             entry->orgstart, channel->rate);
-        if (ts != VLC_TICK_MAX)
-        {
-            entry->start = ts;
-
-            entry->stop =
-                vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
-                                                entry->orgstop, channel->rate);
-        }
-        else
-        {
-            /* Pause triggered before or during spu render */
-
-            /* If currently rendered, display the current spu until the end of
-             * the pause. */
-            entry->stop = VLC_TICK_MAX;
-
-            /* Delay the start date only if not currently rendered. */
-            if (entry->start > system_now)
-                entry->start = VLC_TICK_MAX;
-
-        }
+        entry->stop =
+            vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
+                                            entry->orgstop, channel->rate);
     }
     vlc_clock_Unlock(channel->clock);
 
@@ -2023,8 +2004,7 @@ void spu_PutSubpicture(spu_t *spu, subpicture_t *subpic)
         subpicture_Delete(subpic);
         return;
     }
-    if (subpic->i_start != VLC_TICK_MAX) /* Don't prerender when paused */
-        spu_PrerenderEnqueue(sys, subpic);
+    spu_PrerenderEnqueue(sys, subpic);
     vlc_mutex_unlock(&sys->lock);
 }
 


=====================================
test/src/clock/clock.c
=====================================
@@ -47,18 +47,29 @@ struct clock_scenario
 {
     const char *name;
     const char *desc;
-    vlc_tick_t stream_start;
-    vlc_tick_t system_start; /* VLC_TICK_INVALID for vlc_tick_now() */
-    vlc_tick_t duration;
-    vlc_tick_t stream_increment; /* VLC_TICK_INVALID for manual increment */
-    unsigned video_fps;
-    vlc_tick_t total_drift_duration; /* VLC_TICK_INVALID for non-drift test */
-    double coeff_epsilon; /* Valid for lowprecision/burst checks */
-
-    void (*update)(const struct clock_ctx *ctx, size_t index,
-                   vlc_tick_t *system, vlc_tick_t stream);
-    void (*check)(const struct clock_ctx *ctx, size_t update_count,
-                  vlc_tick_t expected_system_end, vlc_tick_t stream_end);
+
+    enum {
+        CLOCK_SCENARIO_UPDATE,
+        CLOCK_SCENARIO_RUN,
+    } type;
+
+    union {
+        struct {
+            vlc_tick_t stream_start;
+            vlc_tick_t system_start; /* VLC_TICK_INVALID for vlc_tick_now() */
+            vlc_tick_t duration;
+            vlc_tick_t stream_increment; /* VLC_TICK_INVALID for manual increment */
+            unsigned video_fps;
+            vlc_tick_t total_drift_duration; /* VLC_TICK_INVALID for non-drift test */
+
+            double coeff_epsilon; /* Valid for lowprecision/burst checks */
+            void (*update)(const struct clock_ctx *ctx, size_t index,
+                           vlc_tick_t *system, vlc_tick_t stream);
+            void (*check)(const struct clock_ctx *ctx, size_t update_count,
+                          vlc_tick_t expected_system_end, vlc_tick_t stream_end);
+        };
+        void (*run)(const struct clock_ctx *ctx);
+    };
 };
 
 struct clock_ctx
@@ -296,7 +307,8 @@ static void play_scenario(libvlc_int_t *vlc, struct vlc_tracer *tracer,
 {
     fprintf(stderr, "[%s]: checking that %s\n", scenario->name, scenario->desc);
 
-    assert(scenario->update != NULL);
+    assert((scenario->type == CLOCK_SCENARIO_UPDATE && scenario->update != NULL)
+        || (scenario->type == CLOCK_SCENARIO_RUN && scenario->run != NULL));
 
     tracer_ctx_Reset(&tracer_ctx);
 
@@ -323,6 +335,12 @@ static void play_scenario(libvlc_int_t *vlc, struct vlc_tracer *tracer,
         .scenario = scenario,
     };
 
+    if (scenario->type == CLOCK_SCENARIO_RUN)
+    {
+        scenario->run(&ctx);
+        goto end;
+    }
+
     vlc_tick_t stream_end = scenario->stream_start + scenario->duration;
     vlc_tick_t stream = scenario->stream_start;
     if (scenario->system_start == VLC_TICK_INVALID)
@@ -369,8 +387,8 @@ static void play_scenario(libvlc_int_t *vlc, struct vlc_tracer *tracer,
         scenario->check(&ctx, index, expected_system, stream_end);
     }
 
-    if (master != NULL)
-        vlc_clock_Delete(master);
+end:
+    vlc_clock_Delete(master);
     vlc_clock_Delete(slave);
     free(slave_name);
     vlc_clock_main_Delete(mainclk);
@@ -611,6 +629,69 @@ static void drift_sudden_update(const struct clock_ctx *ctx, size_t index,
     }
 }
 
+static void pause_common(const struct clock_ctx *ctx, vlc_clock_t *updater)
+{
+    const vlc_tick_t system_start = vlc_tick_now();
+    const vlc_tick_t pause_duration = VLC_TICK_FROM_MS(20);
+    vlc_tick_t system = system_start;
+
+    vlc_clock_Update(updater, system, 1, 1.0f);
+
+    system += VLC_TICK_FROM_MS(10);
+
+    vlc_clock_main_ChangePause(ctx->mainclk, system, true);
+    system += pause_duration;
+    vlc_clock_main_ChangePause(ctx->mainclk, system, false);
+    system += 1;
+
+    vlc_tick_t converted = vlc_clock_ConvertToSystem(ctx->slave, system, 1, 1.0f);
+    assert(converted == system_start + pause_duration);
+}
+
+static void master_pause_run(const struct clock_ctx *ctx)
+{
+    pause_common(ctx, ctx->master);
+}
+
+static void monotonic_pause_run(const struct clock_ctx *ctx)
+{
+    /* Don't add any delay for the first monotonic ref point  */
+    vlc_clock_main_SetInputDejitter(ctx->mainclk, 0);
+    vlc_clock_main_SetDejitter(ctx->mainclk, 0);
+
+    pause_common(ctx, ctx->slave);
+}
+
+static void convert_paused_common(const struct clock_ctx *ctx, vlc_clock_t *updater)
+{
+    const vlc_tick_t system_start = vlc_tick_now();
+    vlc_tick_t system = system_start;
+
+    vlc_clock_Update(updater, system_start, 1, 1.0f);
+
+    system += VLC_TICK_FROM_MS(10);
+
+    vlc_clock_main_ChangePause(ctx->mainclk, system, true);
+    system += 1;
+
+    vlc_tick_t converted = vlc_clock_ConvertToSystem(ctx->slave, system, 1, 1.0f);
+    assert(converted == system_start);
+}
+
+static void master_convert_paused_run(const struct clock_ctx *ctx)
+{
+    convert_paused_common(ctx, ctx->master);
+}
+
+static void monotonic_convert_paused_run(const struct clock_ctx *ctx)
+{
+    /* Don't add any delay for the first monotonic ref point  */
+    vlc_clock_main_SetInputDejitter(ctx->mainclk, 0);
+    vlc_clock_main_SetDejitter(ctx->mainclk, 0);
+
+    convert_paused_common(ctx, ctx->slave);
+}
+
 #define VLC_TICK_24H VLC_TICK_FROM_SEC(24 * 60 * 60)
 #define VLC_TICK_2H VLC_TICK_FROM_SEC(2 * 60 * 60)
 #define DEFAULT_STREAM_INCREMENT VLC_TICK_FROM_MS(100)
@@ -626,6 +707,7 @@ static struct clock_scenario clock_scenarios[] = {
 {
     .name = "normal",
     .desc = "normal update has a coeff of 1.0f",
+    .type = CLOCK_SCENARIO_UPDATE,
     INIT_SYSTEM_STREAM_TIMING(VLC_TICK_2H, DEFAULT_STREAM_INCREMENT, 60),
     .update = normal_update,
     .check = normal_check,
@@ -633,6 +715,7 @@ static struct clock_scenario clock_scenarios[] = {
 {
     .name = "lowprecision",
     .desc = "low precision update has a coeff near 1.0f",
+    .type = CLOCK_SCENARIO_UPDATE,
     INIT_SYSTEM_STREAM_TIMING(VLC_TICK_2H, DEFAULT_STREAM_INCREMENT, 60),
     .coeff_epsilon = 0.005,
     .update = lowprecision_update,
@@ -641,6 +724,7 @@ static struct clock_scenario clock_scenarios[] = {
 {
     .name = "drift_72",
     .desc = "a drift of 72ms in 2h is handled",
+    .type = CLOCK_SCENARIO_UPDATE,
     INIT_SYSTEM_STREAM_TIMING(VLC_TICK_2H, DEFAULT_STREAM_INCREMENT, 60),
     .total_drift_duration = VLC_TICK_FROM_MS(72),
     .update = drift_update,
@@ -649,6 +733,7 @@ static struct clock_scenario clock_scenarios[] = {
 {
     .name = "drift_-72",
     .desc = "a drift of -72ms in 2h is handled",
+    .type = CLOCK_SCENARIO_UPDATE,
     INIT_SYSTEM_STREAM_TIMING(VLC_TICK_2H, DEFAULT_STREAM_INCREMENT, 60),
     .total_drift_duration = -VLC_TICK_FROM_MS(72),
     .update = drift_update,
@@ -657,6 +742,7 @@ static struct clock_scenario clock_scenarios[] = {
 {
     .name = "drift_864",
     .desc = "a drift of 864ms in 24h is handled",
+    .type = CLOCK_SCENARIO_UPDATE,
     INIT_SYSTEM_STREAM_TIMING(VLC_TICK_24H, DEFAULT_STREAM_INCREMENT, 0),
     .total_drift_duration = VLC_TICK_FROM_MS(864),
     .update = drift_update,
@@ -665,6 +751,7 @@ static struct clock_scenario clock_scenarios[] = {
 {
     .name = "drift_-864",
     .desc = "a drift of -864ms in 24h is handled",
+    .type = CLOCK_SCENARIO_UPDATE,
     INIT_SYSTEM_STREAM_TIMING(VLC_TICK_24H, DEFAULT_STREAM_INCREMENT, 0),
     .total_drift_duration = -VLC_TICK_FROM_MS(864),
     .update = drift_update,
@@ -673,11 +760,36 @@ static struct clock_scenario clock_scenarios[] = {
 {
     .name = "drift_sudden",
     .desc = "a sudden drift is handled",
+    .type = CLOCK_SCENARIO_UPDATE,
     INIT_SYSTEM_STREAM_TIMING(VLC_TICK_24H, DEFAULT_STREAM_INCREMENT, 0),
     .total_drift_duration = VLC_TICK_FROM_MS(864),
     .update = drift_sudden_update,
     .check = drift_check,
 },
+{
+    .name = "master_pause",
+    .desc = "pause + resume is delaying the next conversion",
+    .type = CLOCK_SCENARIO_RUN,
+    .run = master_pause_run,
+},
+{
+    .name = "monotonic_pause",
+    .desc = "pause + resume is delaying the next conversion",
+    .type = CLOCK_SCENARIO_RUN,
+    .run = monotonic_pause_run,
+},
+{
+    .name = "master_convert_paused",
+    .desc = "it is possible de convert ts while paused",
+    .type = CLOCK_SCENARIO_RUN,
+    .run = master_convert_paused_run,
+},
+{
+    .name = "monotonic_convert_paused",
+    .desc = "it is possible de convert ts while paused",
+    .type = CLOCK_SCENARIO_RUN,
+    .run = monotonic_convert_paused_run,
+},
 };
 
 int main(int argc, const char *argv[])



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/1326d6628be54bd6fa9cfe421f71c4048b98427a...1d20f89b0820cbd3957999c7242b739255b6cecc

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/1326d6628be54bd6fa9cfe421f71c4048b98427a...1d20f89b0820cbd3957999c7242b739255b6cecc
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