From a3bddd70fcffc98d82e1cff7fa82f8b2112e337e Mon Sep 17 00:00:00 2001 From: Thomas Guillem Date: Wed, 30 Nov 2022 10:15:20 +0100 Subject: [PATCH] input: propagate aout latency to the player And handle video delay directly from here. --- modules/audio_output/coreaudio_common.c | 6 ++++-- src/audio_output/aout_internal.h | 2 ++ src/audio_output/dec.c | 14 ++++++++++++++ src/input/decoder.c | 9 +++++++++ src/input/decoder.h | 2 ++ src/input/es_out.c | 20 ++++++++++++++++++++ src/input/input_internal.h | 3 +++ src/player/input.c | 20 ++++++++++++++++++++ 8 files changed, 74 insertions(+), 2 deletions(-) diff --git a/modules/audio_output/coreaudio_common.c b/modules/audio_output/coreaudio_common.c index f712699bb7..fca038b9f5 100644 --- a/modules/audio_output/coreaudio_common.c +++ b/modules/audio_output/coreaudio_common.c @@ -179,7 +179,7 @@ ca_Render(audio_output_t *p_aout, uint64_t host_time, { /* Write silence to reach the first play date */ vlc_tick_t silence_ticks = p_sys->first_play_date - end_ticks - - GetLatency(p_aout) + bytes_ticks; + + bytes_ticks; if (silence_ticks > 0) { tocopy = TicksToBytes(p_sys, silence_ticks); @@ -219,7 +219,9 @@ ca_Render(audio_output_t *p_aout, uint64_t host_time, { p_sys->timing_report_last_written_bytes = 0; vlc_tick_t pos_ticks = BytesToTicks(p_sys, p_sys->i_total_bytes); - aout_TimingReport(p_aout, end_ticks + GetLatency(p_aout), pos_ticks); + const vlc_tick_t latency_ticks = GetLatency(p_aout); + aout_LatencyReport(p_aout, latency_ticks); + aout_TimingReport(p_aout, end_ticks, pos_ticks); } else p_sys->timing_report_last_written_bytes += tocopy; diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h index 6234ff37cb..5db0e3ebf6 100644 --- a/src/audio_output/aout_internal.h +++ b/src/audio_output/aout_internal.h @@ -139,6 +139,8 @@ struct vlc_aout_stream_cfg struct vlc_clock_t *clock; const char *str_id; const audio_replay_gain_t *replay_gain; + void (*on_new_latency_cb)(vlc_tick_t tick, void *data); + void *cb_data; }; vlc_aout_stream *vlc_aout_stream_New(audio_output_t *p_aout, diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c index f057a9c99d..4fe94222a5 100644 --- a/src/audio_output/dec.c +++ b/src/audio_output/dec.c @@ -100,6 +100,9 @@ struct vlc_aout_stream atomic_uint buffers_lost; atomic_uint buffers_played; _Atomic vlc_tick_t latency; + vlc_tick_t last_latency; + void (*on_new_latency_cb)(vlc_tick_t tick, void *data); + void *cb_data; }; static inline aout_owner_t *aout_stream_owner(vlc_aout_stream *stream) @@ -167,6 +170,7 @@ static void stream_Discontinuity(vlc_aout_stream *stream) stream->timing.audio_ts = VLC_TICK_INVALID; vlc_mutex_unlock(&stream->timing.lock); stream->timing.played_samples = 0; + stream->last_latency = VLC_TICK_INVALID; } static void stream_Reset(vlc_aout_stream *stream) @@ -254,6 +258,9 @@ vlc_aout_stream * vlc_aout_stream_New(audio_output_t *p_aout, return NULL; stream->instance = aout_instance(p_aout); + stream->on_new_latency_cb = cfg->on_new_latency_cb; + stream->cb_data = cfg->cb_data; + stream->volume = NULL; if (!owner->bitexact) stream->volume = aout_volume_New (p_aout, cfg->replay_gain); @@ -671,6 +678,13 @@ static void stream_Synchronize(vlc_aout_stream *stream, vlc_tick_t system_now, void vlc_aout_stream_NotifyLatency(vlc_aout_stream *stream, vlc_tick_t latency) { + if (stream->last_latency == latency) + return; + stream->last_latency = latency; + + if (stream->on_new_latency_cb != NULL) + stream->on_new_latency_cb(latency, stream->cb_data); + atomic_store_explicit(&stream->latency, latency, memory_order_relaxed); } diff --git a/src/input/decoder.c b/src/input/decoder.c index b946d3e2d4..37f8646383 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -392,6 +392,13 @@ static bool aout_replaygain_changed( const audio_replay_gain_t *a, return false; } +static void +OnNewAudioLatency(vlc_tick_t latency, void *data) +{ + vlc_input_decoder_t *p_owner = data; + decoder_Notify(p_owner, on_new_audio_latency, latency); +} + static int ModuleThread_UpdateAudioFormat( decoder_t *p_dec ) { vlc_input_decoder_t *p_owner = dec_get_owner( p_dec ); @@ -455,6 +462,8 @@ static int ModuleThread_UpdateAudioFormat( decoder_t *p_dec ) .clock = p_owner->p_clock, .str_id = p_owner->psz_id, .replay_gain = &p_dec->fmt_out.audio_replay_gain, + .on_new_latency_cb = OnNewAudioLatency, + .cb_data = p_owner, }; p_astream = vlc_aout_stream_New( p_aout, &cfg ); if( p_astream == NULL ) diff --git a/src/input/decoder.h b/src/input/decoder.h index b17d513878..0538a56984 100644 --- a/src/input/decoder.h +++ b/src/input/decoder.h @@ -57,6 +57,8 @@ struct vlc_input_decoder_callbacks { void (*on_vout_frame_displayed)(vlc_input_decoder_t *decoder, vout_thread_t *vout, vlc_tick_t pts, void *userdata); + void (*on_new_audio_latency)(vlc_input_decoder_t *decoder, vlc_tick_t latency, + void *userdata); /* requests */ int (*get_attachments)(vlc_input_decoder_t *decoder, diff --git a/src/input/es_out.c b/src/input/es_out.c index 67ff19eef1..7331c374a9 100644 --- a/src/input/es_out.c +++ b/src/input/es_out.c @@ -535,6 +535,25 @@ decoder_on_new_audio_stats(vlc_input_decoder_t *decoder, unsigned decoded, unsig atomic_store_explicit(&stats->audio_latency, latency, memory_order_relaxed); } +static void +decoder_on_new_audio_latency(vlc_input_decoder_t *decoder, vlc_tick_t latency, + void *userdata) +{ + (void) decoder; + + es_out_id_t *id = userdata; + es_out_t *out = id->out; + es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out); + + if (p_sys->p_input == NULL) + return; + + input_SendEvent(p_sys->p_input, &(struct vlc_input_event) { + .type = INPUT_EVENT_AOUT_LATENCY, + .latency = latency, + }); +} + static int decoder_get_attachments(vlc_input_decoder_t *decoder, input_attachment_t ***ppp_attachment, @@ -601,6 +620,7 @@ static const struct vlc_input_decoder_callbacks decoder_cbs = { .on_new_video_sk_stats = decoder_on_new_video_sk_stats, .on_new_audio_stats = decoder_on_new_audio_stats, .on_new_decoder_stats = decoder_on_new_decoder_stats, + .on_new_audio_latency = decoder_on_new_audio_latency, .get_attachments = decoder_get_attachments, }; diff --git a/src/input/input_internal.h b/src/input/input_internal.h index b02b1e2eed..69b694c10b 100644 --- a/src/input/input_internal.h +++ b/src/input/input_internal.h @@ -153,6 +153,7 @@ typedef enum input_event_type_e INPUT_EVENT_BUFFER_CLEARED = 0x1000, INPUT_EVENT_VOUT_FRAME_DISPLAYED, INPUT_EVENT_VOUT_CAPTIONS_TO_DISPLAY, + INPUT_EVENT_AOUT_LATENCY, } input_event_type_e; #define VLC_INPUT_CAPABILITIES_SEEKABLE (1<<0) @@ -328,6 +329,8 @@ struct vlc_input_event float subs_fps; /* INPUT_EVENT_THUMBNAIL_READY */ picture_t *thumbnail; + /* INPUT_EVENT_AOUT_LATENCY */ + vlc_tick_t latency; }; }; diff --git a/src/player/input.c b/src/player/input.c index d96d535bec..d0561c9ba9 100644 --- a/src/player/input.c +++ b/src/player/input.c @@ -723,6 +723,23 @@ vlc_player_input_HandleVoutEvent(struct vlc_player_input *input, } } +static void +vlc_player_input_HandleAoutLatency(struct vlc_player_input *input, + vlc_tick_t latency) +{ + msg_Dbg(input->player, "adjusting video delay: %" PRId64, latency); + + enum es_format_category_e cats[] = { VIDEO_ES, SPU_ES }; + for (size_t i = 0; i < ARRAY_SIZE(cats); ++i) + { + enum es_format_category_e cat = cats[i]; + vlc_tick_t delay = input->cat_delays[cat] + latency; + + const input_control_param_t param = { .cat_delay = { cat, delay } }; + input_ControlPush(input->thread, INPUT_CONTROL_SET_CATEGORY_DELAY, ¶m); + } +} + static void input_thread_Events(input_thread_t *input_thread, const struct vlc_input_event *event, void *user_data) @@ -908,6 +925,9 @@ input_thread_Events(input_thread_t *input_thread, case INPUT_EVENT_VOUT_CAPTIONS_TO_DISPLAY: vlc_player_vout_SendEvent(player, on_captions_to_display, event->captions.vout, event->captions.p_cc, event->captions.i_cc); break; + case INPUT_EVENT_AOUT_LATENCY: + vlc_player_input_HandleAoutLatency(input, event->latency); + break; default: break; }