From a2e2c056d9ce33f6354bea92025837e62f9026ec Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 8 Jul 2021 16:17:45 +0200 Subject: [PATCH] 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. --- src/clock/clock.c | 35 +++++++++++++++++++++++---------- src/clock/clock.h | 31 +++++++++++++++++++++++++++-- src/video_output/video_output.c | 2 ++ 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/clock/clock.c b/src/clock/clock.c index 0daf456d22..cd3b07f946 100644 --- a/src/clock/clock.c +++ b/src/clock/clock.c @@ -346,11 +346,30 @@ 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); +} + +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); +} + +void vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_now, vlc_tick_t ts, + double rate, vlc_tick_t max_duration) +{ + AssertLocked(clock); + + vlc_clock_main_t *main_clock = clock->owner; const vlc_tick_t max_deadline = max_duration > 0 ? system_now + max_duration : VLC_TICK_MAX; while (!main_clock->abort) @@ -365,7 +384,6 @@ void vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_now, vlc_tick_t ts, if (vlc_cond_timedwait(&main_clock->cond, &main_clock->lock, deadline)) break; } - vlc_mutex_unlock(&main_clock->lock); } vlc_clock_main_t *vlc_clock_main_New(struct vlc_logger *parent_logger) @@ -516,14 +534,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_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); - vlc_tick_t system = clock->to_system_locked(clock, system_now, ts, rate); - vlc_mutex_unlock(&main_clock->lock); - return system; + return clock->to_system_locked(clock, system_now, ts, rate); } void vlc_clock_ConvertArrayToSystem(vlc_clock_t *clock, vlc_tick_t system_now, diff --git a/src/clock/clock.h b/src/clock/clock.h index eff0114f0c..17a5189837 100644 --- a/src/clock/clock.h +++ b/src/clock/clock.h @@ -173,18 +173,45 @@ void vlc_clock_Reset(vlc_clock_t *clock); */ vlc_tick_t vlc_clock_SetDelay(vlc_clock_t *clock, vlc_tick_t ts_delay); +/** + * Lock the clock mutex + */ +void vlc_clock_Lock(vlc_clock_t *clock); + +/** + * Unlock the clock mutex + */ +void vlc_clock_Unlock(vlc_clock_t *clock); + /** * Wait for a timestamp expressed in stream time + * + * The clock mutex must be locked. */ void vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_now, vlc_tick_t ts, double rate, vlc_tick_t max_duration); /** * 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_ConvertToSystem(vlc_clock_t *clock, vlc_tick_t system_now, - vlc_tick_t ts, double rate); +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; +} /** * This functon converts an array of timestamp from stream to system diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index 5150894a09..494ba1ebf6 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -1330,8 +1330,10 @@ static int RenderPicture(vout_thread_sys_t *vout, bool render_now) { /* Wait to reach system_pts if the plugin doesn't handle * asynchronous display */ + vlc_clock_Lock(sys->clock); vlc_clock_Wait(sys->clock, system_now, pts, sys->rate, VOUT_REDISPLAY_DELAY); + vlc_clock_Unlock(sys->clock); /* Don't touch system_pts. Tell the clock that the pts was rendered * at the expected date */