diff --git a/src/clock/clock.c b/src/clock/clock.c index 14c75eae52..33b124e589 100644 --- a/src/clock/clock.c +++ b/src/clock/clock.c @@ -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; } diff --git a/src/clock/clock.h b/src/clock/clock.h index bd48aadfe9..905efa8546 100644 --- a/src/clock/clock.h +++ b/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,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); diff --git a/src/input/es_out.c b/src/input/es_out.c index cf88b9eac6..1512bfc103 100644 --- a/src/input/es_out.c +++ b/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); } } @@ -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; } diff --git a/src/stream_output/stream_output.c b/src/stream_output/stream_output.c index e09f95580b..31a1786d98 100644 --- a/src/stream_output/stream_output.c +++ b/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 )