[vlc-commits] [Git][videolan/vlc][master] 3 commits: clock: expose and require lock for vlc_clock_main_t

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Sun Mar 17 09:06:43 UTC 2024



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


Commits:
81a594b2 by Thomas Guillem at 2024-03-17T08:37:18+00:00
clock: expose and require lock for vlc_clock_main_t

All vlc_clock_main_t functions need to be called with this lock held.

This allows optimizations where 2 vlc_clock_main_t functions were called
in a row.

- - - - -
9af06586 by Thomas Guillem at 2024-03-17T08:37:18+00:00
aout: filters: clock_source is mutable

Even if the clock is only used for functions that are not modifying the
clock, it locks the clock->main_clock mutex.

This change is necessary as all vlc_clock_t will need to be called with
the lock held.

- - - - -
b61be68d by Thomas Guillem at 2024-03-17T08:37:18+00:00
clock: require the lock for all functions

Instead of wondering if a specific function need to be called locked or
not.

This allows few optimizations where 2 clock functions were called in a
row.

- - - - -


11 changed files:

- src/audio_output/aout_internal.h
- src/audio_output/dec.c
- src/audio_output/filters.c
- src/clock/clock.c
- src/clock/clock.h
- src/input/decoder.c
- src/input/es_out.c
- src/stream_output/stream_output.c
- src/video_output/video_output.c
- src/video_output/vout_subpictures.c
- test/src/clock/clock.c


Changes:

=====================================
src/audio_output/aout_internal.h
=====================================
@@ -203,7 +203,7 @@ static inline void aout_SetWavePhysicalChannels(audio_sample_format_t *fmt)
  * The clock, that is not mandatory, will be used to create a new slave clock
  * for the filter visualization plugins.
  */
-aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *, const vlc_clock_t *,
+aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *, vlc_clock_t *,
                                          const audio_sample_format_t *,
                                          const audio_sample_format_t *,
                                          const aout_filters_cfg_t *cfg) VLC_USED;


=====================================
src/audio_output/dec.c
=====================================
@@ -183,7 +183,9 @@ static void stream_Reset(vlc_aout_stream *stream)
         if (stream->filters)
             aout_FiltersFlush (stream->filters);
 
+        vlc_clock_Lock(stream->sync.clock);
         vlc_clock_Reset(stream->sync.clock);
+        vlc_clock_Unlock(stream->sync.clock);
         if (stream->filters)
             aout_FiltersResetClock(stream->filters);
 
@@ -195,7 +197,9 @@ static void stream_Reset(vlc_aout_stream *stream)
              * dejitter. This will allow the aout to update the master clock
              * sooner.
              */
+            vlc_clock_Lock(stream->sync.clock);
             vlc_clock_SetDelay(stream->sync.clock, 0);
+            vlc_clock_Unlock(stream->sync.clock);
             if (stream->filters)
                 aout_FiltersSetClockDelay(stream->filters, 0);
             stream->sync.request_delay = stream->sync.delay;
@@ -456,9 +460,11 @@ static void stream_Silence (vlc_aout_stream *stream, vlc_tick_t length, vlc_tick
     block->i_length = length;
 
     const vlc_tick_t system_now = vlc_tick_now();
+    vlc_clock_Lock(stream->sync.clock);
     const vlc_tick_t system_pts =
        vlc_clock_ConvertToSystem(stream->sync.clock, system_now, pts,
                                  stream->sync.rate);
+    vlc_clock_Unlock(stream->sync.clock);
     stream->timing.played_samples += block->i_nb_samples;
     aout->play(aout, block, system_pts);
 }
@@ -657,8 +663,10 @@ static void stream_Synchronize(vlc_aout_stream *stream, vlc_tick_t system_now,
             }
         }
 
+        vlc_clock_Lock(stream->sync.clock);
         drift = vlc_clock_Update(stream->sync.clock, system_now + delay,
                                  dec_pts, stream->sync.rate);
+        vlc_clock_Unlock(stream->sync.clock);
     }
 
     stream_HandleDrift(stream, drift, dec_pts);
@@ -699,9 +707,11 @@ void vlc_aout_stream_NotifyTiming(vlc_aout_stream *stream, vlc_tick_t system_ts,
 
     stream->timing.system_ts = system_ts;
     stream->timing.audio_ts = audio_ts;
+    vlc_clock_Lock(stream->sync.clock);
     stream->timing.last_drift =
         vlc_clock_Update(stream->sync.clock, system_ts,
                          audio_ts, stream->timing.rate);
+    vlc_clock_Unlock(stream->sync.clock);
     vlc_mutex_unlock(&stream->timing.lock);
 }
 
@@ -760,7 +770,9 @@ int vlc_aout_stream_Play(vlc_aout_stream *stream, block_t *block)
     if (stream->sync.request_delay != stream->sync.delay)
     {
         stream->sync.delay = stream->sync.request_delay;
+        vlc_clock_Lock(stream->sync.clock);
         vlc_tick_t delta = vlc_clock_SetDelay(stream->sync.clock, stream->sync.delay);
+        vlc_clock_Unlock(stream->sync.clock);
         if (stream->filters)
             aout_FiltersSetClockDelay(stream->filters, stream->sync.delay);
         if (delta > 0)
@@ -770,9 +782,11 @@ int vlc_aout_stream_Play(vlc_aout_stream *stream, block_t *block)
     /* Drift correction */
     vlc_tick_t system_now = vlc_tick_now();
 
+    vlc_clock_Lock(stream->sync.clock);
     vlc_tick_t play_date =
         vlc_clock_ConvertToSystem(stream->sync.clock, system_now, original_pts,
                                   stream->sync.rate);
+    vlc_clock_Unlock(stream->sync.clock);
     stream_Synchronize(stream, system_now, play_date, original_pts);
 
     vlc_audio_meter_Process(&owner->meter, block, play_date);
@@ -788,9 +802,11 @@ int vlc_aout_stream_Play(vlc_aout_stream *stream, block_t *block)
 
         /* Update the clock immediately with the new rate, instead of waiting
          * for a timing update that could come too late (after 1second). */
+        vlc_clock_Lock(stream->sync.clock);
         stream->timing.last_drift =
             vlc_clock_Update(stream->sync.clock, play_date, original_pts,
                              stream->sync.rate);
+        vlc_clock_Unlock(stream->sync.clock);
         vlc_mutex_unlock(&stream->timing.lock);
     }
 
@@ -861,10 +877,12 @@ void vlc_aout_stream_ChangePause(vlc_aout_stream *stream, bool paused, vlc_tick_
         if (aout->time_get == NULL && !paused
          && stream->timing.rate_audio_ts != VLC_TICK_INVALID)
         {
+            vlc_clock_Lock(stream->sync.clock);
             vlc_tick_t play_date =
                 vlc_clock_ConvertToSystem(stream->sync.clock, date,
                                           stream->timing.rate_audio_ts,
                                           stream->sync.rate);
+            vlc_clock_Unlock(stream->sync.clock);
             stream->timing.rate_system_ts = play_date;
         }
     }


=====================================
src/audio_output/filters.c
=====================================
@@ -370,7 +370,7 @@ struct aout_filters
         (either the scaletempo filter or a resampler) */
     struct aout_filter resampler; /**< The resampler */
     int resampling; /**< Current resampling (Hz) */
-    const vlc_clock_t *clock_source;
+    vlc_clock_t *clock_source;
 
     unsigned count; /**< Number of filters */
     struct aout_filter tab[AOUT_MAX_FILTERS]; /**< Configured user filters
@@ -406,7 +406,7 @@ static int VisualizationCallback (vlc_object_t *obj, const char *var,
 
 struct filter_owner_sys
 {
-    const vlc_clock_t *clock_source;
+    vlc_clock_t *clock_source;
     vlc_clock_t *clock;
     vout_thread_t *vout;
 };
@@ -418,7 +418,9 @@ vout_thread_t *aout_filter_GetVout(filter_t *filter, const video_format_t *fmt)
     assert(owner_sys->clock == NULL);
     assert(owner_sys->vout == NULL);
 
+    vlc_clock_Lock(owner_sys->clock_source);
     vlc_clock_t *clock = vlc_clock_CreateSlave(owner_sys->clock_source, AUDIO_ES);
+    vlc_clock_Unlock(owner_sys->clock_source);
     if (clock == NULL)
         return NULL;
 
@@ -542,7 +544,7 @@ static int AppendRemapFilter(vlc_object_t *obj, aout_filters_t *restrict filters
     return ret;
 }
 
-aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *obj, const vlc_clock_t *clock,
+aout_filters_t *aout_FiltersNewWithClock(vlc_object_t *obj, vlc_clock_t *clock,
                                          const audio_sample_format_t *restrict infmt,
                                          const audio_sample_format_t *restrict outfmt,
                                          const aout_filters_cfg_t *cfg)
@@ -700,7 +702,11 @@ static void aout_FiltersPipelineResetClock(const struct aout_filter *tab,
     {
         vlc_clock_t *clock = tab[i].clock;
         if (clock != NULL)
+        {
+            vlc_clock_Lock(clock);
             vlc_clock_Reset(clock);
+            vlc_clock_Unlock(clock);
+        }
     }
 }
 
@@ -717,7 +723,11 @@ static void aout_FiltersPipelineSetClockDelay(const struct aout_filter *tab,
     {
         vlc_clock_t *clock = tab[i].clock;
         if (clock != NULL)
+        {
+            vlc_clock_Lock(clock);
             vlc_clock_SetDelay(clock, delay);
+            vlc_clock_Unlock(clock);
+        }
     }
 }
 


=====================================
src/clock/clock.c
=====================================
@@ -80,8 +80,8 @@ struct vlc_clock_ops
                          unsigned frame_rate, unsigned frame_rate_base);
     void (*reset)(vlc_clock_t *clock);
     vlc_tick_t (*set_delay)(vlc_clock_t *clock, vlc_tick_t delay);
-    vlc_tick_t (*to_system_locked)(vlc_clock_t *clock, vlc_tick_t system_now,
-                                   vlc_tick_t ts, double rate);
+    vlc_tick_t (*to_system)(vlc_clock_t *clock, vlc_tick_t system_now,
+                            vlc_tick_t ts, double rate);
 };
 
 struct vlc_clock_t
@@ -103,6 +103,7 @@ vlc_clock_AddListener(vlc_clock_t *clock,
 {
     vlc_clock_main_t *main_clock = clock->owner;
     assert(cbs != NULL);
+    vlc_mutex_assert(&main_clock->lock);
 
     vlc_clock_listener_id *listener_id = malloc(sizeof(*listener_id));
     if (listener_id == NULL)
@@ -112,10 +113,7 @@ vlc_clock_AddListener(vlc_clock_t *clock,
     listener_id->cbs = cbs;
     listener_id->data = data;
 
-    vlc_mutex_lock(&main_clock->lock);
     bool success = vlc_vector_push(&main_clock->listeners, listener_id);
-    vlc_mutex_unlock(&main_clock->lock);
-
     if (!success)
     {
         free(listener_id);
@@ -128,8 +126,7 @@ void
 vlc_clock_RemoveListener(vlc_clock_t *clock, vlc_clock_listener_id *listener_id)
 {
     vlc_clock_main_t *main_clock = clock->owner;
-
-    vlc_mutex_lock(&main_clock->lock);
+    vlc_mutex_assert(&main_clock->lock);
 
     const vlc_clock_listener_id *it;
     vlc_vector_foreach(it, &main_clock->listeners)
@@ -137,8 +134,6 @@ vlc_clock_RemoveListener(vlc_clock_t *clock, vlc_clock_listener_id *listener_id)
         {
             vlc_vector_remove(&main_clock->listeners, vlc_vector_idx_it);
             free(listener_id);
-
-            vlc_mutex_unlock(&main_clock->lock);
             return;
         }
 
@@ -232,8 +227,6 @@ static vlc_tick_t vlc_clock_master_update(vlc_clock_t *clock,
     if (unlikely(ts == VLC_TICK_INVALID || system_now == VLC_TICK_INVALID))
         return VLC_TICK_INVALID;
 
-    vlc_mutex_lock(&main_clock->lock);
-
     /* If system_now is VLC_TICK_MAX, the update is forced, don't modify
      * anything but only notify the new clock point. */
     if (system_now != VLC_TICK_MAX)
@@ -312,8 +305,6 @@ static vlc_tick_t vlc_clock_master_update(vlc_clock_t *clock,
         vlc_cond_broadcast(&main_clock->cond);
     }
 
-    vlc_mutex_unlock(&main_clock->lock);
-
     /* Fix the reported ts if both master and slaves source are delayed. This
      * happens if we apply a positive delay to the master, and then lower it. */
     if (clock->delay > 0 && main_clock->delay < 0 && ts > -main_clock->delay)
@@ -329,7 +320,6 @@ static void vlc_clock_master_reset(vlc_clock_t *clock)
 {
     vlc_clock_main_t *main_clock = clock->owner;
 
-    vlc_mutex_lock(&main_clock->lock);
     if (main_clock->tracer != NULL && clock->track_str_id != NULL)
         vlc_tracer_TraceEvent(main_clock->tracer, "RENDER", clock->track_str_id,
                               "reset_user");
@@ -353,15 +343,12 @@ static void vlc_clock_master_reset(vlc_clock_t *clock)
         }
     }
 
-    vlc_mutex_unlock(&main_clock->lock);
-
     vlc_clock_on_update(clock, VLC_TICK_INVALID, VLC_TICK_INVALID, VLC_TICK_INVALID, 1.f, 0, 0);
 }
 
 static vlc_tick_t vlc_clock_master_set_delay(vlc_clock_t *clock, vlc_tick_t delay)
 {
     vlc_clock_main_t *main_clock = clock->owner;
-    vlc_mutex_lock(&main_clock->lock);
 
     vlc_tick_t delta = delay - clock->delay;
 
@@ -381,13 +368,12 @@ static vlc_tick_t vlc_clock_master_set_delay(vlc_clock_t *clock, vlc_tick_t dela
     assert(clock->delay >= 0);
 
     vlc_cond_broadcast(&main_clock->cond);
-    vlc_mutex_unlock(&main_clock->lock);
     return delta;
 }
 
 static vlc_tick_t
-vlc_clock_monotonic_to_system_locked(vlc_clock_t *clock, vlc_tick_t now,
-                                     vlc_tick_t ts, double rate)
+vlc_clock_monotonic_to_system(vlc_clock_t *clock, vlc_tick_t now,
+                              vlc_tick_t ts, double rate)
 {
     vlc_clock_main_t *main_clock = clock->owner;
 
@@ -421,9 +407,9 @@ vlc_clock_monotonic_to_system_locked(vlc_clock_t *clock, vlc_tick_t now,
         + main_clock->wait_sync_ref.system;
 }
 
-static vlc_tick_t vlc_clock_slave_to_system_locked(vlc_clock_t *clock,
-                                                   vlc_tick_t now,
-                                                   vlc_tick_t ts, double rate)
+static vlc_tick_t vlc_clock_slave_to_system(vlc_clock_t *clock,
+                                            vlc_tick_t now, vlc_tick_t ts,
+                                            double rate)
 {
     vlc_clock_main_t *main_clock = clock->owner;
 
@@ -432,15 +418,15 @@ static vlc_tick_t vlc_clock_slave_to_system_locked(vlc_clock_t *clock,
     {
         /* We don't have a master sync point, let's fallback to a monotonic ref
          * point */
-        system = vlc_clock_monotonic_to_system_locked(clock, now, ts, rate);
+        system = vlc_clock_monotonic_to_system(clock, now, ts, rate);
     }
 
     return system + (clock->delay - main_clock->delay) * rate;
 }
 
-static vlc_tick_t vlc_clock_master_to_system_locked(vlc_clock_t *clock,
-                                                    vlc_tick_t now,
-                                                    vlc_tick_t ts, double rate)
+static vlc_tick_t vlc_clock_master_to_system(vlc_clock_t *clock,
+                                             vlc_tick_t now, vlc_tick_t ts,
+                                             double rate)
 {
     vlc_clock_main_t *main_clock = clock->owner;
     vlc_tick_t system = main_stream_to_system(main_clock, ts);
@@ -448,7 +434,7 @@ static vlc_tick_t vlc_clock_master_to_system_locked(vlc_clock_t *clock,
     {
         /* We don't have a master sync point, let's fallback to a monotonic ref
          * point */
-        system = vlc_clock_monotonic_to_system_locked(clock, now, ts, rate);
+        system = vlc_clock_monotonic_to_system(clock, now, ts, rate);
     }
 
     return system;
@@ -460,8 +446,6 @@ static vlc_tick_t vlc_clock_slave_update(vlc_clock_t *clock,
                                          unsigned frame_rate,
                                          unsigned frame_rate_base)
 {
-    vlc_clock_main_t *main_clock = clock->owner;
-
     if (system_now == VLC_TICK_MAX)
     {
         /* If system_now is VLC_TICK_MAX, the update is forced, don't modify
@@ -471,11 +455,7 @@ static vlc_tick_t vlc_clock_slave_update(vlc_clock_t *clock,
         return VLC_TICK_MAX;
     }
 
-    vlc_mutex_lock(&main_clock->lock);
-
-    vlc_tick_t computed = clock->ops->to_system_locked(clock, system_now, ts, rate);
-
-    vlc_mutex_unlock(&main_clock->lock);
+    vlc_tick_t computed = clock->ops->to_system(clock, system_now, ts, rate);
 
     vlc_tick_t drift = computed - system_now;
     vlc_clock_on_update(clock, computed, ts, drift, rate,
@@ -486,13 +466,10 @@ static vlc_tick_t vlc_clock_slave_update(vlc_clock_t *clock,
 static void vlc_clock_slave_reset(vlc_clock_t *clock)
 {
     vlc_clock_main_t *main_clock = clock->owner;
-    vlc_mutex_lock(&main_clock->lock);
     main_clock->wait_sync_ref_priority = UINT_MAX;
     main_clock->wait_sync_ref =
         clock_point_Create(VLC_TICK_INVALID, VLC_TICK_INVALID);
 
-    vlc_mutex_unlock(&main_clock->lock);
-
     vlc_clock_on_update(clock, VLC_TICK_INVALID, VLC_TICK_INVALID,
                         VLC_TICK_INVALID, 1.0f, 0, 0);
 }
@@ -500,12 +477,10 @@ static void vlc_clock_slave_reset(vlc_clock_t *clock)
 static vlc_tick_t vlc_clock_slave_set_delay(vlc_clock_t *clock, vlc_tick_t delay)
 {
     vlc_clock_main_t *main_clock = clock->owner;
-    vlc_mutex_lock(&main_clock->lock);
 
     clock->delay = delay;
 
     vlc_cond_broadcast(&main_clock->cond);
-    vlc_mutex_unlock(&main_clock->lock);
     return 0;
 }
 
@@ -545,6 +520,8 @@ int vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t deadline)
 
 void vlc_clock_Wake(vlc_clock_t *clock)
 {
+    AssertLocked(clock);
+
     vlc_clock_main_t *main_clock = clock->owner;
     vlc_cond_broadcast(&main_clock->cond);
 }
@@ -589,17 +566,18 @@ vlc_clock_main_t *vlc_clock_main_New(struct vlc_logger *parent_logger, struct vl
 
 void vlc_clock_main_Reset(vlc_clock_main_t *main_clock)
 {
-    vlc_mutex_lock(&main_clock->lock);
+    vlc_mutex_assert(&main_clock->lock);
+
     vlc_clock_main_reset(main_clock);
     main_clock->first_pcr =
         clock_point_Create(VLC_TICK_INVALID, VLC_TICK_INVALID);
-    vlc_mutex_unlock(&main_clock->lock);
 }
 
 void vlc_clock_main_SetFirstPcr(vlc_clock_main_t *main_clock,
                                 vlc_tick_t system_now, vlc_tick_t ts)
 {
-    vlc_mutex_lock(&main_clock->lock);
+    vlc_mutex_assert(&main_clock->lock);
+
     if (main_clock->first_pcr.system == VLC_TICK_INVALID)
     {
         main_clock->first_pcr = clock_point_Create(system_now, ts);
@@ -607,29 +585,29 @@ void vlc_clock_main_SetFirstPcr(vlc_clock_main_t *main_clock,
         main_clock->wait_sync_ref =
             clock_point_Create(VLC_TICK_INVALID, VLC_TICK_INVALID);
     }
-    vlc_mutex_unlock(&main_clock->lock);
 }
 
 void vlc_clock_main_SetInputDejitter(vlc_clock_main_t *main_clock,
                                      vlc_tick_t delay)
 {
-    vlc_mutex_lock(&main_clock->lock);
+    vlc_mutex_assert(&main_clock->lock);
+
     main_clock->input_dejitter = delay;
-    vlc_mutex_unlock(&main_clock->lock);
 }
 
 void vlc_clock_main_SetDejitter(vlc_clock_main_t *main_clock,
                                 vlc_tick_t dejitter)
 {
-    vlc_mutex_lock(&main_clock->lock);
+    vlc_mutex_assert(&main_clock->lock);
+
     main_clock->output_dejitter = dejitter;
-    vlc_mutex_unlock(&main_clock->lock);
 }
 
 void vlc_clock_main_ChangePause(vlc_clock_main_t *main_clock, vlc_tick_t now,
                                 bool paused)
 {
-    vlc_mutex_lock(&main_clock->lock);
+    vlc_mutex_assert(&main_clock->lock);
+
     assert(paused == (main_clock->pause_date == VLC_TICK_INVALID));
 
     if (paused)
@@ -653,7 +631,6 @@ void vlc_clock_main_ChangePause(vlc_clock_main_t *main_clock, vlc_tick_t now,
         main_clock->pause_date = VLC_TICK_INVALID;
         vlc_cond_broadcast(&main_clock->cond);
     }
-    vlc_mutex_unlock(&main_clock->lock);
 }
 
 void vlc_clock_main_Delete(vlc_clock_main_t *main_clock)
@@ -668,9 +645,21 @@ void vlc_clock_main_Delete(vlc_clock_main_t *main_clock)
     free(main_clock);
 }
 
+void vlc_clock_main_Lock(vlc_clock_main_t *main_clock)
+{
+    vlc_mutex_lock(&main_clock->lock);
+}
+
+void vlc_clock_main_Unlock(vlc_clock_main_t *main_clock)
+{
+    vlc_mutex_assert(&main_clock->lock);
+    vlc_mutex_unlock(&main_clock->lock);
+}
+
 vlc_tick_t vlc_clock_Update(vlc_clock_t *clock, vlc_tick_t system_now,
                             vlc_tick_t ts, double rate)
 {
+    AssertLocked(clock);
     return clock->ops->update(clock, system_now, ts, rate, 0, 0);
 }
 
@@ -678,38 +667,42 @@ vlc_tick_t vlc_clock_UpdateVideo(vlc_clock_t *clock, vlc_tick_t system_now,
                                  vlc_tick_t ts, double rate,
                                  unsigned frame_rate, unsigned frame_rate_base)
 {
+    AssertLocked(clock);
     return clock->ops->update(clock, system_now, ts, rate, frame_rate, frame_rate_base);
 }
 
 void vlc_clock_Reset(vlc_clock_t *clock)
 {
+    AssertLocked(clock);
     clock->ops->reset(clock);
 }
 
 vlc_tick_t vlc_clock_SetDelay(vlc_clock_t *clock, vlc_tick_t delay)
 {
+    AssertLocked(clock);
     return clock->ops->set_delay(clock, delay);
 }
 
-vlc_tick_t vlc_clock_ConvertToSystemLocked(vlc_clock_t *clock,
-                                           vlc_tick_t system_now, vlc_tick_t ts,
-                                           double rate)
+vlc_tick_t vlc_clock_ConvertToSystem(vlc_clock_t *clock,
+                                     vlc_tick_t system_now, vlc_tick_t ts,
+                                     double rate)
 {
-    return clock->ops->to_system_locked(clock, system_now, ts, rate);
+    AssertLocked(clock);
+    return clock->ops->to_system(clock, system_now, ts, rate);
 }
 
 static const struct vlc_clock_ops master_ops = {
     .update = vlc_clock_master_update,
     .reset = vlc_clock_master_reset,
     .set_delay = vlc_clock_master_set_delay,
-    .to_system_locked = vlc_clock_master_to_system_locked,
+    .to_system = vlc_clock_master_to_system,
 };
 
 static const struct vlc_clock_ops slave_ops = {
     .update = vlc_clock_slave_update,
     .reset = vlc_clock_slave_reset,
     .set_delay = vlc_clock_slave_set_delay,
-    .to_system_locked = vlc_clock_slave_to_system_locked,
+    .to_system = vlc_clock_slave_to_system,
 };
 
 static vlc_clock_t *vlc_clock_main_Create(vlc_clock_main_t *main_clock,
@@ -738,12 +731,13 @@ vlc_clock_t *vlc_clock_main_CreateMaster(vlc_clock_main_t *main_clock,
                                          const struct vlc_clock_cbs *cbs,
                                          void *cbs_data)
 {
+    vlc_mutex_assert(&main_clock->lock);
+
     /* The master has always the 0 priority */
     vlc_clock_t *clock = vlc_clock_main_Create(main_clock, track_str_id, 0, cbs, cbs_data);
     if (!clock)
         return NULL;
 
-    vlc_mutex_lock(&main_clock->lock);
     assert(main_clock->master == NULL);
 
     if (main_clock->input_master == NULL)
@@ -753,19 +747,19 @@ vlc_clock_t *vlc_clock_main_CreateMaster(vlc_clock_main_t *main_clock,
 
     main_clock->master = clock;
     main_clock->rc++;
-    vlc_mutex_unlock(&main_clock->lock);
 
     return clock;
 }
 
 vlc_clock_t *vlc_clock_main_CreateInputMaster(vlc_clock_main_t *main_clock)
 {
+    vlc_mutex_assert(&main_clock->lock);
+
     /* The master has always the 0 priority */
     vlc_clock_t *clock = vlc_clock_main_Create(main_clock, "input", 0, NULL, NULL);
     if (!clock)
         return NULL;
 
-    vlc_mutex_lock(&main_clock->lock);
     assert(main_clock->input_master == NULL);
 
     /* Even if the master ES clock has already been created, it should not
@@ -779,7 +773,6 @@ vlc_clock_t *vlc_clock_main_CreateInputMaster(vlc_clock_main_t *main_clock)
     clock->ops = &master_ops;
     main_clock->input_master = clock;
     main_clock->rc++;
-    vlc_mutex_unlock(&main_clock->lock);
 
     return clock;
 }
@@ -790,10 +783,12 @@ vlc_clock_t *vlc_clock_main_CreateSlave(vlc_clock_main_t *main_clock,
                                         const struct vlc_clock_cbs *cbs,
                                         void *cbs_data)
 {
+    vlc_mutex_assert(&main_clock->lock);
+
     /* SPU outputs should have lower priority than VIDEO outputs since they
      * necessarily depend on a VIDEO output. This mean that a SPU reference
      * point will always be overridden by AUDIO or VIDEO outputs. Cf.
-     * vlc_clock_monotonic_to_system_locked */
+     * vlc_clock_monotonic_to_system */
     unsigned priority;
     switch (cat)
     {
@@ -812,10 +807,8 @@ vlc_clock_t *vlc_clock_main_CreateSlave(vlc_clock_main_t *main_clock,
     if (!clock)
         return NULL;
 
-    vlc_mutex_lock(&main_clock->lock);
     clock->ops = &slave_ops;
     main_clock->rc++;
-    vlc_mutex_unlock(&main_clock->lock);
 
     return clock;
 }


=====================================
src/clock/clock.h
=====================================
@@ -79,16 +79,48 @@ vlc_clock_main_t *vlc_clock_main_New(struct vlc_logger *parent_logger, struct vl
 
 /**
  * Destroy the clock main
+ *
+ * @param main_clock the unlocked main_clock
  */
 void vlc_clock_main_Delete(vlc_clock_main_t *main_clock);
 
+/**
+ * Lock the main_clock mutex
+ *
+ * All vlc_clock_main_t functions must be called with the lock held, except
+ * vlc_clock_main_Delete()
+ *
+ * @param main_clock the unlocked main_clock
+ */
+void vlc_clock_main_Lock(vlc_clock_main_t *main_clock);
+
+/**
+ * Unlock the main_clock mutex
+ *
+ * @param main_clock the locked main_clock
+ */
+void vlc_clock_main_Unlock(vlc_clock_main_t *main_clock);
+
 /**
  * Reset the vlc_clock_main_t
+ *
+ * @param main_clock the locked main_clock
  */
 void vlc_clock_main_Reset(vlc_clock_main_t *main_clock);
 
+/**
+ * Set the first PCR point
+ *
+ * @param main_clock the locked main_clock
+ */
 void vlc_clock_main_SetFirstPcr(vlc_clock_main_t *main_clock,
                                 vlc_tick_t system_now, vlc_tick_t ts);
+
+/**
+ * Set the input dejitter
+ *
+ * @param main_clock the locked main_clock
+ */
 void vlc_clock_main_SetInputDejitter(vlc_clock_main_t *main_clock,
                                      vlc_tick_t delay);
 
@@ -96,12 +128,16 @@ void vlc_clock_main_SetInputDejitter(vlc_clock_main_t *main_clock,
  * This function sets the dejitter delay to absorb the clock jitter
  *
  * Also used as the maximum delay before the synchro is considered to kick in.
+ *
+ * @param main_clock the locked main_clock
  */
 void vlc_clock_main_SetDejitter(vlc_clock_main_t *main_clock, vlc_tick_t dejitter);
 
 
 /**
  * This function allows changing the pause status.
+ *
+ * @param main_clock the locked main_clock
  */
 void vlc_clock_main_ChangePause(vlc_clock_main_t *clock, vlc_tick_t system_now,
                                 bool paused);
@@ -112,6 +148,8 @@ void vlc_clock_main_ChangePause(vlc_clock_main_t *clock, vlc_tick_t system_now,
  * @warning There can be only one master at a given time.
  *
  * You must use vlc_clock_Delete to free it.
+ *
+ * @param main_clock the locked main_clock
  */
 vlc_clock_t *vlc_clock_main_CreateMaster(vlc_clock_main_t *main_clock,
                                          const char *track_str_id,
@@ -127,6 +165,8 @@ vlc_clock_t *vlc_clock_main_CreateMaster(vlc_clock_main_t *main_clock,
  * @warning There can be only one input master at a given time.
  *
  * You must use vlc_clock_Delete to free it.
+ *
+ * @param main_clock the locked main_clock
  */
 vlc_clock_t *vlc_clock_main_CreateInputMaster(vlc_clock_main_t *main_clock);
 
@@ -134,6 +174,8 @@ vlc_clock_t *vlc_clock_main_CreateInputMaster(vlc_clock_main_t *main_clock);
  * This function creates a new slave vlc_clock_t interface
  *
  * You must use vlc_clock_Delete to free it.
+ *
+ * @param main_clock the locked main_clock
  */
 vlc_clock_t *vlc_clock_main_CreateSlave(vlc_clock_main_t *main_clock,
                                         const char *track_str_id,
@@ -145,19 +187,23 @@ vlc_clock_t *vlc_clock_main_CreateSlave(vlc_clock_main_t *main_clock,
  * This function creates a new slave vlc_clock_t interface
  *
  * You must use vlc_clock_Delete to free it.
+ *
+ * @param main_clock the locked main_clock
  */
 vlc_clock_t *vlc_clock_CreateSlave(const vlc_clock_t *clock,
                                    enum es_format_category_e cat);
 
 /**
  * This function free the resources allocated by vlc_clock*Create*()
+ *
+ * @param clock the unlocked clock used by the source
  */
 void vlc_clock_Delete(vlc_clock_t *clock);
 
 /**
  * This function will update the clock drift and returns the drift
  *
- * @param clock the clock setter to update
+ * @param clock the locked clock used by the source
  * @param system_now valid system time or VLC_TICK_MAX is the updated point is
  *        forced (when paused for example)
  * @param ts the timestamp in media time for the updated point
@@ -181,6 +227,8 @@ vlc_tick_t vlc_clock_UpdateVideo(vlc_clock_t *clock, vlc_tick_t system_now,
 
 /**
  * This function resets the clock drift
+ *
+ * @param clock the locked clock used by the source
  */
 void vlc_clock_Reset(vlc_clock_t *clock);
 
@@ -189,16 +237,22 @@ void vlc_clock_Reset(vlc_clock_t *clock);
  *
  * It returns the amount of time the clock owner need to wait in order to reach
  * the time introduced by the new positive delay.
+ *
+ * @param clock the locked clock used by the source
  */
 vlc_tick_t vlc_clock_SetDelay(vlc_clock_t *clock, vlc_tick_t ts_delay);
 
 /**
  * Lock the clock mutex
+ *
+ * @param clock the unlocked clock used by the source
  */
 void vlc_clock_Lock(vlc_clock_t *clock);
 
 /**
  * Unlock the clock mutex
+ *
+ * @param clock the locked clock used by the source
  */
 void vlc_clock_Unlock(vlc_clock_t *clock);
 
@@ -207,6 +261,7 @@ void vlc_clock_Unlock(vlc_clock_t *clock);
  *
  * The clock mutex must be locked.
  *
+ * @param clock the locked clock used by the source
  * @retval true if the clock is paused
  * @retval false if the clock is not paused
  */
@@ -219,8 +274,7 @@ bool vlc_clock_IsPaused(vlc_clock_t *clock);
  * invalidate the computed deadline. In that case, the caller must recompute
  * the new deadline and call it again.
  *
- * The clock mutex must be locked.
- *
+ * @param clock the locked clock used by the source
  * @return 0 if the condition was signaled, an error code in case of timeout
  */
 int vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_deadline);
@@ -228,14 +282,14 @@ int vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_deadline);
 /**
  * Wake up any vlc_clock_Wait()
  *
- * The clock mutex must be locked.
+ * @param clock the locked clock used by the source
  */
 void vlc_clock_Wake(vlc_clock_t *clock);
 
 /**
  * Add a listener for events
  *
- * @param clock the clock used by the source
+ * @param clock the locked clock used by the source
  * @param cbs valid pointer to register events
  * @param data opaque data used by cbs
  * @return a valid listener id, or NULL in case of allocation error
@@ -248,7 +302,7 @@ vlc_clock_AddListener(vlc_clock_t *clock,
 /**
  * Remove a event listener callback
  *
- * @param clock the clock used by the source
+ * @param clock the locked clock used by the source
  * @param listener_id listener id returned by vlc_clock_AddListener()
  */
 void
@@ -257,23 +311,11 @@ vlc_clock_RemoveListener(vlc_clock_t *clock, vlc_clock_listener_id *listener_id)
 /**
  * This function converts a timestamp from stream to system
  *
- * The clock mutex must be locked.
- *
+ * @param clock the locked clock used by the source
  * @return the valid system time
  */
-vlc_tick_t vlc_clock_ConvertToSystemLocked(vlc_clock_t *clock,
-                                           vlc_tick_t system_now, vlc_tick_t ts,
-                                           double rate);
-
-static inline vlc_tick_t
-vlc_clock_ConvertToSystem(vlc_clock_t *clock, vlc_tick_t system_now,
-                          vlc_tick_t ts, double rate)
-{
-    vlc_clock_Lock(clock);
-    vlc_tick_t system =
-        vlc_clock_ConvertToSystemLocked(clock, system_now, ts, rate);
-    vlc_clock_Unlock(clock);
-    return system;
-}
+vlc_tick_t vlc_clock_ConvertToSystem(vlc_clock_t *clock,
+                                     vlc_tick_t system_now, vlc_tick_t ts,
+                                     double rate);
 
 #endif /*CLOCK_H*/


=====================================
src/input/decoder.c
=====================================
@@ -989,7 +989,11 @@ static vlc_tick_t ModuleThread_GetDisplayDate( decoder_t *p_dec,
     if( !p_owner->p_clock || i_ts == VLC_TICK_INVALID )
         return i_ts;
 
-    return vlc_clock_ConvertToSystem( p_owner->p_clock, system_now, i_ts, rate );
+    vlc_clock_Lock( p_owner->p_clock );
+    vlc_tick_t conv_ts =
+        vlc_clock_ConvertToSystem( p_owner->p_clock, system_now, i_ts, rate );
+    vlc_clock_Unlock( p_owner->p_clock );
+    return conv_ts;
 }
 
 static float ModuleThread_GetDisplayRate( decoder_t *p_dec )


=====================================
src/input/es_out.c
=====================================
@@ -1038,6 +1038,7 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
 
     input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_input_clock, true, update );
 
+    vlc_clock_main_Lock(p_sys->p_pgrm->clocks.main);
     /* Resetting the main_clock here will drop all points that were sent during
      * the buffering step. Only points coming from the input_clock are dropped
      * here. Indeed, decoders should not send any output frames while buffering
@@ -1053,6 +1054,7 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
      * point for the sync point. */
     vlc_clock_main_SetFirstPcr(p_sys->p_pgrm->clocks.main, update,
                                i_stream_start);
+    vlc_clock_main_Unlock(p_sys->p_pgrm->clocks.main);
 
     foreach_es_then_es_slaves(p_es)
     {
@@ -1112,7 +1114,10 @@ static void EsOutProgramChangePause( es_out_t *out, bool b_paused, vlc_tick_t i_
     vlc_list_foreach(pgrm, &p_sys->programs, node)
     {
         input_clock_ChangePause(pgrm->p_input_clock, b_paused, i_date);
+
+        vlc_clock_main_Lock(pgrm->clocks.main);
         vlc_clock_main_ChangePause(pgrm->clocks.main, i_date, b_paused);
+        vlc_clock_main_Unlock(pgrm->clocks.main);
     }
 }
 
@@ -1256,14 +1261,20 @@ ClockListenerUpdate(void *opaque, vlc_tick_t ck_system,
                     vlc_tick_t ck_stream, double rate)
 {
     es_out_pgrm_t *pgrm = opaque;
-    return vlc_clock_Update(pgrm->clocks.input, ck_system, ck_stream, rate);
+    vlc_clock_Lock(pgrm->clocks.input);
+    vlc_tick_t drift =
+        vlc_clock_Update(pgrm->clocks.input, ck_system, ck_stream, rate);
+    vlc_clock_Unlock(pgrm->clocks.input);
+    return drift;
 }
 
 static void
 ClockListenerReset(void *opaque)
 {
     es_out_pgrm_t *pgrm = opaque;
+    vlc_clock_Lock(pgrm->clocks.input);
     vlc_clock_Reset(pgrm->clocks.input);
+    vlc_clock_Unlock(pgrm->clocks.input);
 }
 
 
@@ -1304,8 +1315,10 @@ static void EsOutProgramHandleClockSource( es_out_t *out, es_out_pgrm_t *p_pgrm
             /* Fall-through */
         case VLC_CLOCK_MASTER_INPUT:
         {
+            vlc_clock_main_Lock(p_sys->p_pgrm->clocks.main);
             p_pgrm->clocks.input =
                 vlc_clock_main_CreateInputMaster(p_pgrm->clocks.main);
+            vlc_clock_main_Unlock(p_sys->p_pgrm->clocks.main);
 
             if (p_pgrm->clocks.input == NULL)
                 break;
@@ -1332,8 +1345,10 @@ static void EsOutProgramHandleClockSource( es_out_t *out, es_out_pgrm_t *p_pgrm
 
     if (p_pgrm->active_clock_source != VLC_CLOCK_MASTER_INPUT)
     {
+        vlc_clock_main_Lock(p_pgrm->clocks.main);
         p_pgrm->clocks.input = vlc_clock_main_CreateSlave(
             p_pgrm->clocks.main, "pcr", UNKNOWN_ES, NULL, NULL);
+        vlc_clock_main_Unlock(p_pgrm->clocks.main);
 
         if (p_pgrm->clocks.input != NULL)
         {
@@ -1508,6 +1523,8 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, input_source_t *source, in
     const vlc_tick_t pts_delay = p_sys->i_pts_delay + p_sys->i_pts_jitter
                                + p_sys->i_tracks_pts_delay;
     input_clock_SetJitter( p_pgrm->p_input_clock, pts_delay, p_sys->i_cr_average );
+
+    vlc_clock_main_Lock(p_pgrm->clocks.main);
     vlc_clock_main_SetInputDejitter(p_pgrm->clocks.main, pts_delay );
 
     /* In case of low delay: don't use any output dejitter. This may result on
@@ -1515,6 +1532,7 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, input_source_t *source, in
      * than the visual quality if the user chose this option. */
     if (input_priv(p_input)->b_low_delay)
         vlc_clock_main_SetDejitter(p_pgrm->clocks.main, 0);
+    vlc_clock_main_Unlock(p_pgrm->clocks.main);
 
     /* Append it */
     vlc_list_append(&p_pgrm->node, &p_sys->programs);
@@ -2272,6 +2290,7 @@ static void EsOutCreateDecoder( es_out_t *out, es_out_id_t *p_es )
             vlc_assert_unreachable();
     }
 
+    vlc_clock_main_Lock(p_es->p_pgrm->clocks.main);
     if( p_es->fmt.i_cat != UNKNOWN_ES
      && p_es->fmt.i_cat == clock_source_cat
      && p_es->p_pgrm->p_master_es_clock == NULL )
@@ -2290,6 +2309,7 @@ static void EsOutCreateDecoder( es_out_t *out, es_out_id_t *p_es )
                                                    p_es->fmt.i_cat,
                                                    &clock_cbs, p_es);
     }
+    vlc_clock_main_Unlock(p_es->p_pgrm->clocks.main);
 
     if( !p_es->p_clock )
     {
@@ -3929,7 +3949,9 @@ static int EsOutVaPrivControlLocked( es_out_t *out, input_source_t *source,
         {
             input_clock_SetJitter(pgrm->p_input_clock,
                                   i_pts_delay, i_cr_average);
+            vlc_clock_main_Lock(pgrm->clocks.main);
             vlc_clock_main_SetInputDejitter(pgrm->clocks.main, i_pts_delay);
+            vlc_clock_main_Unlock(pgrm->clocks.main);
         }
         return VLC_SUCCESS;
     }


=====================================
src/stream_output/stream_output.c
=====================================
@@ -792,15 +792,21 @@ void sout_ClockMainDelete( vlc_clock_main_t *main_clock )
 
 void sout_ClockMainSetFirstPcr( vlc_clock_main_t *main_clock, vlc_tick_t pcr )
 {
+    vlc_clock_main_Lock( main_clock );
     vlc_clock_main_Reset( main_clock );
     vlc_clock_main_SetFirstPcr( main_clock, vlc_tick_now(), pcr );
+    vlc_clock_main_Unlock( main_clock );
 }
 
 vlc_clock_t *sout_ClockCreate( vlc_clock_main_t *main_clock,
                                const es_format_t *fmt )
 {
-    return vlc_clock_main_CreateSlave( main_clock, NULL, fmt->i_cat,
-                                       NULL, NULL );
+    vlc_clock_main_Lock( main_clock );
+    vlc_clock_t *clock =
+        vlc_clock_main_CreateSlave( main_clock, NULL, fmt->i_cat,
+                                    NULL, NULL );
+    vlc_clock_main_Unlock( main_clock );
+    return clock;
 }
 
 void sout_ClockDelete( vlc_clock_t *clock )


=====================================
src/video_output/video_output.c
=====================================
@@ -984,9 +984,11 @@ static picture_t *PreparePicture(vout_thread_sys_t *vout, bool reuse_decoded,
                 if (is_late_dropped && !decoded->b_force)
                 {
                     const vlc_tick_t system_now = vlc_tick_now();
+                    vlc_clock_Lock(sys->clock);
                     const vlc_tick_t system_pts =
                         vlc_clock_ConvertToSystem(sys->clock, system_now,
                                                   decoded->date, sys->rate);
+                    vlc_clock_Unlock(sys->clock);
 
                     if (IsPictureLate(vout, decoded, system_now, system_pts))
                     {
@@ -1145,9 +1147,11 @@ static int PrerenderPicture(vout_thread_sys_t *sys, picture_t *filtered,
         render_subtitle_date = sys->pause.date;
     else
     {
+        vlc_clock_Lock(sys->clock);
         render_subtitle_date = filtered->date <= VLC_TICK_0 ? system_now :
             vlc_clock_ConvertToSystem(sys->clock, system_now, filtered->date,
                                       sys->rate);
+        vlc_clock_Unlock(sys->clock);
     }
 
     /*
@@ -1313,8 +1317,10 @@ static int RenderPicture(vout_thread_sys_t *sys, bool render_now)
 
     vlc_tick_t system_now = vlc_tick_now();
     const vlc_tick_t pts = todisplay->date;
+    vlc_clock_Lock(sys->clock);
     vlc_tick_t system_pts = render_now ? system_now :
         vlc_clock_ConvertToSystem(sys->clock, system_now, pts, sys->rate);
+    vlc_clock_Unlock(sys->clock);
 
     const unsigned frame_rate = todisplay->format.i_frame_rate;
     const unsigned frame_rate_base = todisplay->format.i_frame_rate_base;
@@ -1357,8 +1363,9 @@ static int RenderPicture(vout_thread_sys_t *sys, bool render_now)
                     deadline = max_deadline;
                 else
                 {
-                    deadline = vlc_clock_ConvertToSystemLocked(sys->clock,
-                                                vlc_tick_now(), pts, sys->rate);
+                    deadline = vlc_clock_ConvertToSystem(sys->clock,
+                                                         vlc_tick_now(), pts,
+                                                         sys->rate);
                     if (deadline > max_deadline)
                         deadline = max_deadline;
                 }
@@ -1385,10 +1392,12 @@ static int RenderPicture(vout_thread_sys_t *sys, bool render_now)
 
     /* Display the direct buffer returned by vout_RenderPicture */
     vout_display_Display(vd, todisplay);
+    vlc_clock_Lock(sys->clock);
     vlc_tick_t drift = vlc_clock_UpdateVideo(sys->clock,
                                              vlc_tick_now(),
                                              pts, sys->rate,
                                              frame_rate, frame_rate_base);
+    vlc_clock_Unlock(sys->clock);
 
     vlc_queuedmutex_unlock(&sys->display_lock);
 
@@ -1461,9 +1470,11 @@ static bool UpdateCurrentPicture(vout_thread_sys_t *sys)
         return false;
 
     const vlc_tick_t system_now = vlc_tick_now();
+    vlc_clock_Lock(sys->clock);
     const vlc_tick_t system_swap_current =
         vlc_clock_ConvertToSystem(sys->clock, system_now,
                                   sys->displayed.current->date, sys->rate);
+    vlc_clock_Unlock(sys->clock);
 
     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;
@@ -1598,8 +1609,10 @@ static void vout_FlushUnlocked(vout_thread_sys_t *vout, bool below,
 
     if (sys->clock != NULL)
     {
+        vlc_clock_Lock(sys->clock);
         vlc_clock_Reset(sys->clock);
         vlc_clock_SetDelay(sys->clock, sys->delay);
+        vlc_clock_Unlock(sys->clock);
     }
 }
 
@@ -1636,7 +1649,9 @@ void vout_ChangeDelay(vout_thread_t *vout, vlc_tick_t delay)
     assert(sys->display);
 
     vout_control_Hold(&sys->control);
+    vlc_clock_Lock(sys->clock);
     vlc_clock_SetDelay(sys->clock, delay);
+    vlc_clock_Unlock(sys->clock);
     sys->delay = delay;
     vout_control_Release(&sys->control);
 }
@@ -1901,7 +1916,9 @@ static void vout_ReleaseDisplay(vout_thread_sys_t *vout)
 
     if (sys->clock_listener_id != NULL)
     {
+        vlc_clock_Lock(sys->clock);
         vlc_clock_RemoveListener(sys->clock, sys->clock_listener_id);
+        vlc_clock_Unlock(sys->clock);
         sys->clock_listener_id = NULL;
     }
 
@@ -2254,8 +2271,10 @@ int vout_Request(const vout_configuration_t *cfg, vlc_video_context *vctx, input
     static const struct vlc_clock_event_cbs clock_event_cbs = {
         .on_discontinuity = clock_event_OnDiscontinuity,
     };
+    vlc_clock_Lock(sys->clock);
     sys->clock_listener_id =
         vlc_clock_AddListener(sys->clock, &clock_event_cbs, vout);
+    vlc_clock_Unlock(sys->clock);
 
     sys->delay = 0;
 
@@ -2278,7 +2297,11 @@ error_thread:
 error_display:
     vout_DisableWindow(vout);
     if (sys->clock_listener_id != NULL)
+    {
+        vlc_clock_Lock(sys->clock);
         vlc_clock_RemoveListener(sys->clock, sys->clock_listener_id);
+        vlc_clock_Unlock(sys->clock);
+    }
     sys->clock_listener_id = NULL;
     vlc_mutex_lock(&sys->clock_lock);
     sys->clock = NULL;


=====================================
src/video_output/vout_subpictures.c
=====================================
@@ -696,12 +696,12 @@ static size_t spu_channel_UpdateDates(struct spu_channel *channel,
     {
         assert(entry);
 
-        entry->start = vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
-                                                       entry->orgstart, channel->rate);
+        entry->start = vlc_clock_ConvertToSystem(channel->clock, system_now,
+                                                 entry->orgstart, channel->rate);
 
         entry->stop =
-            vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
-                                            entry->orgstop, channel->rate);
+            vlc_clock_ConvertToSystem(channel->clock, system_now,
+                                      entry->orgstop, channel->rate);
     }
     vlc_clock_Unlock(channel->clock);
 
@@ -1857,7 +1857,9 @@ void spu_SetClockDelay(spu_t *spu, size_t channel_id, vlc_tick_t delay)
     vlc_mutex_lock(&sys->lock);
     struct spu_channel *channel = spu_GetChannel(spu, channel_id, NULL);
     assert(channel->clock);
+    vlc_clock_Lock(channel->clock);
     vlc_clock_SetDelay(channel->clock, delay);
+    vlc_clock_Unlock(channel->clock);
     channel->delay = delay;
     vlc_mutex_unlock(&sys->lock);
 }
@@ -1979,11 +1981,11 @@ void spu_PutSubpicture(spu_t *spu, subpicture_t *subpic)
 
         vlc_clock_Lock(channel->clock);
         subpic->i_start =
-            vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
-                                            orgstart, channel->rate);
+            vlc_clock_ConvertToSystem(channel->clock, system_now,
+                                      orgstart, channel->rate);
         subpic->i_stop =
-            vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
-                                            orgstop, channel->rate);
+            vlc_clock_ConvertToSystem(channel->clock, system_now,
+                                      orgstop, channel->rate);
         vlc_clock_Unlock(channel->clock);
 
         spu_channel_EarlyRemoveLate(sys, channel, system_now);
@@ -2187,8 +2189,10 @@ void spu_ClearChannel(spu_t *spu, size_t channel_id)
     spu_channel_Clean(sys, channel);
     if (channel->clock)
     {
+        vlc_clock_Lock(channel->clock);
         vlc_clock_Reset(channel->clock);
         vlc_clock_SetDelay(channel->clock, channel->delay);
+        vlc_clock_Unlock(channel->clock);
     }
     vlc_mutex_unlock(&sys->lock);
 }


=====================================
test/src/clock/clock.c
=====================================
@@ -315,6 +315,7 @@ static void play_scenario(libvlc_int_t *vlc, struct vlc_tracer *tracer,
     vlc_clock_main_t *mainclk = vlc_clock_main_New(logger, tracer);
     assert(mainclk != NULL);
 
+    vlc_clock_main_Lock(mainclk);
     vlc_clock_t *master = vlc_clock_main_CreateMaster(mainclk, scenario->name,
                                                       NULL, NULL);
     assert(master != NULL);
@@ -325,6 +326,7 @@ static void play_scenario(libvlc_int_t *vlc, struct vlc_tracer *tracer,
     vlc_clock_t *slave = vlc_clock_main_CreateSlave(mainclk, slave_name, VIDEO_ES,
                                                     NULL, NULL);
     assert(slave != NULL);
+    vlc_clock_main_Unlock(mainclk);
 
     const struct clock_ctx ctx = {
         .mainclk = mainclk,
@@ -365,10 +367,12 @@ static void play_scenario(libvlc_int_t *vlc, struct vlc_tracer *tracer,
         {
             while (video_system < expected_system + scenario->stream_increment)
             {
+                vlc_clock_Lock(ctx.slave);
                 vlc_tick_t play_date =
                     vlc_clock_ConvertToSystem(ctx.slave, video_system, video_ts,
                                               1.0f);
                 vlc_clock_Update(ctx.slave, play_date, video_ts, 1.0f);
+                vlc_clock_Unlock(ctx.slave);
                 video_system += video_increment;
                 video_ts += video_increment;
             }
@@ -454,8 +458,10 @@ static void normal_update(const struct clock_ctx *ctx, size_t index,
     (void) index;
     const struct clock_scenario *scenario = ctx->scenario;
 
+    vlc_clock_Lock(ctx->master);
     vlc_tick_t drift =
         vlc_clock_Update(ctx->master, *system, stream, 1.0f);
+    vlc_clock_Unlock(ctx->master);
     /* The master can't drift */
     assert(drift == VLC_TICK_INVALID);
 
@@ -524,9 +530,11 @@ static void normal_check(const struct clock_ctx *ctx, size_t update_count,
         }
     }
 
+    vlc_clock_Lock(ctx->slave);
     vlc_tick_t converted =
         vlc_clock_ConvertToSystem(ctx->slave, expected_system_end,
                                   stream_end, 1.0f);
+    vlc_clock_Unlock(ctx->slave);
     assert(converted == expected_system_end);
 }
 
@@ -543,8 +551,10 @@ static void lowprecision_update(const struct clock_ctx *ctx, size_t index,
     vlc_tick_t imprecision = rand() % VLC_TICK_FROM_MS(5);
     *system = base_system + imprecision;
 
+    vlc_clock_Lock(ctx->master);
     vlc_tick_t drift =
         vlc_clock_Update(ctx->master, *system, stream, 1.0f);
+    vlc_clock_Unlock(ctx->master);
     /* The master can't drift */
     assert(drift == VLC_TICK_INVALID);
 }
@@ -578,8 +588,10 @@ static void drift_update(const struct clock_ctx *ctx, size_t index,
     (void) index;
     const struct clock_scenario *scenario = ctx->scenario;
 
+    vlc_clock_Lock(ctx->master);
     vlc_tick_t drift =
         vlc_clock_Update(ctx->master, *system, stream, 1.0f);
+    vlc_clock_Unlock(ctx->master);
     /* The master can't drift */
     assert(drift == VLC_TICK_INVALID);
 
@@ -600,9 +612,11 @@ static void drift_check(const struct clock_ctx *ctx, size_t update_count,
 
     check_no_event_error(update_count);
 
+    vlc_clock_Lock(ctx->slave);
     vlc_tick_t converted =
         vlc_clock_ConvertToSystem(ctx->slave, expected_system_end,
                                   stream_end, 1.0f);
+    vlc_clock_Unlock(ctx->slave);
 
     assert(converted - expected_system_end == scenario->total_drift_duration);
 }
@@ -613,8 +627,10 @@ static void drift_sudden_update(const struct clock_ctx *ctx, size_t index,
     (void) index;
     const struct clock_scenario *scenario = ctx->scenario;
 
+    vlc_clock_Lock(ctx->slave);
     vlc_tick_t drift =
         vlc_clock_Update(ctx->master, *system, stream, 1.0f);
+    vlc_clock_Unlock(ctx->slave);
     /* The master can't drift */
     assert(drift == VLC_TICK_INVALID);
 
@@ -633,16 +649,26 @@ static void pause_common(const struct clock_ctx *ctx, vlc_clock_t *updater)
     const vlc_tick_t pause_duration = VLC_TICK_FROM_MS(20);
     vlc_tick_t system = system_start;
 
+    vlc_clock_Lock(updater);
     vlc_clock_Update(updater, system, 1, 1.0f);
+    vlc_clock_Unlock(updater);
 
     system += VLC_TICK_FROM_MS(10);
 
+    vlc_clock_main_Lock(ctx->mainclk);
     vlc_clock_main_ChangePause(ctx->mainclk, system, true);
+    vlc_clock_main_Unlock(ctx->mainclk);
+
     system += pause_duration;
+
+    vlc_clock_main_Lock(ctx->mainclk);
     vlc_clock_main_ChangePause(ctx->mainclk, system, false);
+    vlc_clock_main_Unlock(ctx->mainclk);
     system += 1;
 
+    vlc_clock_Lock(ctx->slave);
     vlc_tick_t converted = vlc_clock_ConvertToSystem(ctx->slave, system, 1, 1.0f);
+    vlc_clock_Unlock(ctx->slave);
     assert(converted == system_start + pause_duration);
 }
 
@@ -654,8 +680,10 @@ static void master_pause_run(const struct clock_ctx *ctx)
 static void monotonic_pause_run(const struct clock_ctx *ctx)
 {
     /* Don't add any delay for the first monotonic ref point  */
+    vlc_clock_main_Lock(ctx->mainclk);
     vlc_clock_main_SetInputDejitter(ctx->mainclk, 0);
     vlc_clock_main_SetDejitter(ctx->mainclk, 0);
+    vlc_clock_main_Unlock(ctx->mainclk);
 
     pause_common(ctx, ctx->slave);
 }
@@ -665,14 +693,20 @@ static void convert_paused_common(const struct clock_ctx *ctx, vlc_clock_t *upda
     const vlc_tick_t system_start = vlc_tick_now();
     vlc_tick_t system = system_start;
 
+    vlc_clock_Lock(updater);
     vlc_clock_Update(updater, system_start, 1, 1.0f);
+    vlc_clock_Unlock(updater);
 
     system += VLC_TICK_FROM_MS(10);
 
+    vlc_clock_main_Lock(ctx->mainclk);
     vlc_clock_main_ChangePause(ctx->mainclk, system, true);
+    vlc_clock_main_Unlock(ctx->mainclk);
     system += 1;
 
+    vlc_clock_Lock(ctx->slave);
     vlc_tick_t converted = vlc_clock_ConvertToSystem(ctx->slave, system, 1, 1.0f);
+    vlc_clock_Unlock(ctx->slave);
     assert(converted == system_start);
 }
 
@@ -684,8 +718,10 @@ static void master_convert_paused_run(const struct clock_ctx *ctx)
 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_Lock(ctx->mainclk);
     vlc_clock_main_SetInputDejitter(ctx->mainclk, 0);
     vlc_clock_main_SetDejitter(ctx->mainclk, 0);
+    vlc_clock_main_Unlock(ctx->mainclk);
 
     convert_paused_common(ctx, ctx->slave);
 }



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/f1d0bb4f85b6566648efb82a5d0561a6a594673b...b61be68d6aebb657d207c51114eeb6f6592cac73

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