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.
This commit is contained in:
Thomas Guillem 2024-03-15 14:50:04 +01:00 committed by Felix Paul Kühne
parent f1d0bb4f85
commit 81a594b206
4 changed files with 95 additions and 18 deletions

View File

@ -589,17 +589,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 +608,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 +654,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,6 +668,17 @@ 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)
{
@ -738,12 +749,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 +765,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 +791,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,6 +801,8 @@ 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.
@ -812,10 +825,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;
}

View File

@ -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,6 +187,8 @@ 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);

View File

@ -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);
}
}
@ -1304,8 +1309,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 +1339,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 +1517,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 +1526,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 +2284,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 +2303,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 +3943,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;
}

View File

@ -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 )