[vlc-commits] [Git][videolan/vlc][master] 5 commits: clock: expose lock

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Sat Jul 10 19:14:27 UTC 2021



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
a2e2c056 by Romain Vimont at 2021-07-10T18:55:40+00:00
clock: expose lock

This is a first step to allow the caller to compute an arbitrary
deadline based on vlc_clock_ConvertToSystemLocked() then wait using
vlc_clock_Wait() without race condition.

- - - - -
6c2e92f9 by Romain Vimont at 2021-07-10T18:55:40+00:00
clock: remove ConvertArrayToSystem()

Now that clock lock is exposed, a wrapper function to apply several
conversions at once becomes unnecessary: the caller could execute
each conversion successively with lock held.

- - - - -
ecf0ac67 by Romain Vimont at 2021-07-10T18:55:40+00:00
clock: compute target deadline on caller-side

The function vlc_clock_Wait() was in charge of converting the stream
timestamp and handling a deadline provided by the caller.

Instead, just pass the deadline, expressed in system time. This will
allow the caller to compute arbitrary deadlines and to wake up the wait
on custom conditions.

- - - - -
7de5729f by Romain Vimont at 2021-07-10T18:55:40+00:00
clock: remove unused Abort()

- - - - -
8be3b627 by Romain Vimont at 2021-07-10T18:55:40+00:00
clock: add Wake()

Expose a function to wake up the wait condition. This will allow users
to loop on vlc_clock_Wait() under their own custom conditions.

- - - - -


4 changed files:

- src/clock/clock.c
- src/clock/clock.h
- src/video_output/video_output.c
- src/video_output/vout_subpictures.c


Changes:

=====================================
src/clock/clock.c
=====================================
@@ -57,7 +57,6 @@ struct vlc_clock_main_t
     clock_point_t first_pcr;
     vlc_tick_t output_dejitter; /* Delay used to absorb the output clock jitter */
     vlc_tick_t input_dejitter; /* Delay used to absorb the input jitter */
-    bool abort;
 };
 
 struct vlc_clock_t
@@ -346,28 +345,46 @@ static vlc_tick_t vlc_clock_slave_set_delay(vlc_clock_t *clock, vlc_tick_t delay
     return 0;
 }
 
-void vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_now, vlc_tick_t ts,
-                   double rate, vlc_tick_t max_duration)
+void vlc_clock_Lock(vlc_clock_t *clock)
 {
     vlc_clock_main_t *main_clock = clock->owner;
     vlc_mutex_lock(&main_clock->lock);
-    const vlc_tick_t max_deadline =
-        max_duration > 0 ? system_now + max_duration : VLC_TICK_MAX;
-    while (!main_clock->abort)
-    {
-        vlc_tick_t deadline;
-        if (main_clock->pause_date != VLC_TICK_INVALID)
-            deadline = VLC_TICK_MAX;
-        else
-            deadline = clock->to_system_locked(clock, system_now, ts, rate);
-        deadline = __MIN(deadline, max_deadline);
+}
 
-        if (vlc_cond_timedwait(&main_clock->cond, &main_clock->lock, deadline))
-            break;
-    }
+void vlc_clock_Unlock(vlc_clock_t *clock)
+{
+    vlc_clock_main_t *main_clock = clock->owner;
     vlc_mutex_unlock(&main_clock->lock);
 }
 
+static inline void AssertLocked(vlc_clock_t *clock)
+{
+    vlc_clock_main_t *main_clock = clock->owner;
+    vlc_mutex_assert(&main_clock->lock);
+}
+
+bool vlc_clock_IsPaused(vlc_clock_t *clock)
+{
+    AssertLocked(clock);
+
+    vlc_clock_main_t *main_clock = clock->owner;
+    return main_clock->pause_date != VLC_TICK_INVALID;
+}
+
+int vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t deadline)
+{
+    AssertLocked(clock);
+
+    vlc_clock_main_t *main_clock = clock->owner;
+    return vlc_cond_timedwait(&main_clock->cond, &main_clock->lock, deadline);
+}
+
+void vlc_clock_Wake(vlc_clock_t *clock)
+{
+    vlc_clock_main_t *main_clock = clock->owner;
+    vlc_cond_broadcast(&main_clock->cond);
+}
+
 vlc_clock_main_t *vlc_clock_main_New(struct vlc_logger *parent_logger)
 {
     vlc_clock_main_t *main_clock = malloc(sizeof(vlc_clock_main_t));
@@ -401,22 +418,12 @@ vlc_clock_main_t *vlc_clock_main_New(struct vlc_logger *parent_logger)
     main_clock->pause_date = VLC_TICK_INVALID;
     main_clock->input_dejitter = DEFAULT_PTS_DELAY;
     main_clock->output_dejitter = AOUT_MAX_PTS_ADVANCE * 2;
-    main_clock->abort = false;
 
     AvgInit(&main_clock->coeff_avg, 10);
 
     return main_clock;
 }
 
-void vlc_clock_main_Abort(vlc_clock_main_t *main_clock)
-{
-    vlc_mutex_lock(&main_clock->lock);
-    main_clock->abort = true;
-    vlc_cond_broadcast(&main_clock->cond);
-
-    vlc_mutex_unlock(&main_clock->lock);
-}
-
 void vlc_clock_main_Reset(vlc_clock_main_t *main_clock)
 {
     vlc_mutex_lock(&main_clock->lock);
@@ -516,26 +523,11 @@ vlc_tick_t vlc_clock_SetDelay(vlc_clock_t *clock, vlc_tick_t delay)
     return clock->set_delay(clock, delay);
 }
 
-vlc_tick_t vlc_clock_ConvertToSystem(vlc_clock_t *clock, vlc_tick_t system_now,
-                                     vlc_tick_t ts, double rate)
-{
-    vlc_clock_main_t *main_clock = clock->owner;
-    vlc_mutex_lock(&main_clock->lock);
-    vlc_tick_t system = clock->to_system_locked(clock, system_now, ts, rate);
-    vlc_mutex_unlock(&main_clock->lock);
-    return system;
-}
-
-void vlc_clock_ConvertArrayToSystem(vlc_clock_t *clock, vlc_tick_t system_now,
-                                    vlc_tick_t *ts_array, size_t ts_count,
-                                    double rate)
+vlc_tick_t vlc_clock_ConvertToSystemLocked(vlc_clock_t *clock,
+                                           vlc_tick_t system_now, vlc_tick_t ts,
+                                           double rate)
 {
-    vlc_clock_main_t *main_clock = clock->owner;
-    vlc_mutex_lock(&main_clock->lock);
-    for (size_t i = 0; i < ts_count; ++i)
-        ts_array[i] = clock->to_system_locked(clock, system_now, ts_array[i],
-                                              rate);
-    vlc_mutex_unlock(&main_clock->lock);
+    return clock->to_system_locked(clock, system_now, ts, rate);
 }
 
 static void vlc_clock_set_master_callbacks(vlc_clock_t *clock)


=====================================
src/clock/clock.h
=====================================
@@ -65,11 +65,6 @@ vlc_clock_main_t *vlc_clock_main_New(struct vlc_logger *parent_logger);
  */
 void vlc_clock_main_Delete(vlc_clock_main_t *main_clock);
 
-/**
- * Abort all the pending vlc_clock_Wait
- */
-void vlc_clock_main_Abort(vlc_clock_main_t *main_clock);
-
 /**
  * Reset the vlc_clock_main_t
  */
@@ -174,23 +169,63 @@ void vlc_clock_Reset(vlc_clock_t *clock);
 vlc_tick_t vlc_clock_SetDelay(vlc_clock_t *clock, vlc_tick_t ts_delay);
 
 /**
- * Wait for a timestamp expressed in stream time
+ * Lock the clock mutex
  */
-void vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_now, vlc_tick_t ts,
-                   double rate, vlc_tick_t max_duration);
+void vlc_clock_Lock(vlc_clock_t *clock);
 
 /**
- * This function converts a timestamp from stream to system
- * @return the valid system time or VLC_TICK_MAX when the clock is paused
+ * Unlock the clock mutex
  */
-vlc_tick_t vlc_clock_ConvertToSystem(vlc_clock_t *clock, vlc_tick_t system_now,
-                                     vlc_tick_t ts, double rate);
+void vlc_clock_Unlock(vlc_clock_t *clock);
 
 /**
- * This functon converts an array of timestamp from stream to system
+ * Indicate if the clock is paused
+ *
+ * The clock mutex must be locked.
+ *
+ * @retval true if the clock is paused
+ * @retval false if the clock is not paused
+ */
+bool vlc_clock_IsPaused(vlc_clock_t *clock);
+
+/**
+ * Wait for a timestamp expressed in system time
+ *
+ * The wait will be interrupted (signaled) on clock state changes which could
+ * invalidate the computed deadline. In that case, the caller must recompute
+ * the new deadline and call it again.
+ *
+ * The clock mutex must be locked.
+ *
+ * @return 0 if the condition was signaled, an error code in case of timeout
  */
-void vlc_clock_ConvertArrayToSystem(vlc_clock_t *clock, vlc_tick_t system_now,
-                                    vlc_tick_t *ts_array, size_t ts_count,
-                                    double rate);
+int vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_deadline);
+
+/**
+ * Wake up any vlc_clock_Wait()
+ */
+void vlc_clock_Wake(vlc_clock_t *clock);
+
+/**
+ * This function converts a timestamp from stream to system
+ *
+ * The clock mutex must be locked.
+ *
+ * @return the valid system time or VLC_TICK_MAX when the clock is paused
+ */
+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;
+}
 
 #endif /*VLC_CLOCK_H*/


=====================================
src/video_output/video_output.c
=====================================
@@ -1328,10 +1328,29 @@ static int RenderPicture(vout_thread_sys_t *vout, bool render_now)
         }
         else if (vd->ops->display != NULL)
         {
+            vlc_tick_t max_deadline = system_now + VOUT_REDISPLAY_DELAY;
+
             /* Wait to reach system_pts if the plugin doesn't handle
              * asynchronous display */
-            vlc_clock_Wait(sys->clock, system_now, pts, sys->rate,
-                           VOUT_REDISPLAY_DELAY);
+            vlc_clock_Lock(sys->clock);
+
+            bool timed_out = false;
+            while (!timed_out) {
+                vlc_tick_t deadline;
+                if (vlc_clock_IsPaused(sys->clock))
+                    deadline = max_deadline;
+                else
+                {
+                    deadline = vlc_clock_ConvertToSystemLocked(sys->clock,
+                                                vlc_tick_now(), pts, sys->rate);
+                    if (deadline > max_deadline)
+                        deadline = max_deadline;
+                }
+
+                timed_out = vlc_clock_Wait(sys->clock, deadline);
+            };
+
+            vlc_clock_Unlock(sys->clock);
 
             /* Don't touch system_pts. Tell the clock that the pts was rendered
              * at the expected date */


=====================================
src/video_output/vout_subpictures.c
=====================================
@@ -596,37 +596,32 @@ static size_t spu_channel_UpdateDates(struct spu_channel *channel,
      * one shot */
     if (channel->entries.size == 0)
         return 0;
-    vlc_tick_t *date_array = vlc_alloc(channel->entries.size,
-                                       2 * sizeof(vlc_tick_t));
-    if (!date_array)
-        return 0;
 
+    if (!channel->clock)
+        goto end;
+
+    vlc_clock_Lock(channel->clock);
     for (size_t index = 0; index < channel->entries.size; index++)
     {
-        spu_render_entry_t *current = &channel->entries.data[index];
-        assert(current);
+        spu_render_entry_t *entry = &channel->entries.data[index];
+        assert(entry);
 
-        date_array[index * 2] = current->orgstart;
-        date_array[index * 2 + 1] = current->orgstop;
-    }
-
-    /* Convert all spu ts */
-    if (channel->clock)
-        vlc_clock_ConvertArrayToSystem(channel->clock, system_now, date_array,
-                                       channel->entries.size * 2, channel->rate);
+        vlc_tick_t ts;
 
-    /* Put back the converted ts into the output spu_render_entry_t struct */
-    for (size_t index = 0; index < channel->entries.size; index++)
-    {
-        spu_render_entry_t *render_entry = &channel->entries.data[index];
-        if(date_array[index * 2] != VLC_TICK_MAX) /* pause triggered before or during spu render */
+        ts = vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
+                                             entry->orgstart, channel->rate);
+        if (ts != VLC_TICK_MAX) /* pause triggered before or during spu render */
         {
-            render_entry->start = date_array[index * 2];
-            render_entry->stop = date_array[index * 2 + 1];
+            entry->start = ts;
+
+            entry->stop =
+                vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
+                                                entry->orgstop, channel->rate);
         }
     }
+    vlc_clock_Unlock(channel->clock);
 
-    free(date_array);
+end:
     return channel->entries.size;
 }
 
@@ -1870,11 +1865,15 @@ void spu_PutSubpicture(spu_t *spu, subpicture_t *subpic)
     if (channel->clock)
     {
         vlc_tick_t system_now = vlc_tick_now();
-        vlc_tick_t times[2] = { orgstart, orgstop };
-        vlc_clock_ConvertArrayToSystem(channel->clock, system_now,
-                                       times, 2, channel->rate);
-        subpic->i_start = times[0];
-        subpic->i_stop = times[1];
+
+        vlc_clock_Lock(channel->clock);
+        subpic->i_start =
+            vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
+                                            orgstart, channel->rate);
+        subpic->i_stop =
+            vlc_clock_ConvertToSystemLocked(channel->clock, system_now,
+                                            orgstop, channel->rate);
+        vlc_clock_Unlock(channel->clock);
     }
 
     if (spu_channel_Push(channel, subpic, orgstart, orgstop))



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/6208d519af83a7833d63dc819e9ef23cbc77777d...8be3b627143e5ba816edc6ecb6585d30a08afede

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/6208d519af83a7833d63dc819e9ef23cbc77777d...8be3b627143e5ba816edc6ecb6585d30a08afede
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list