From 293360d2f3016d5400d2a0b74cedf934f05218e3 Mon Sep 17 00:00:00 2001 From: Alexandre Janniaux Date: Thu, 30 Mar 2023 18:59:10 +0200 Subject: [PATCH] stats: add overrun and underrun --- include/vlc/libvlc_media.h | 3 +++ include/vlc_input_item.h | 3 +++ lib/media.c | 2 ++ src/audio_output/aout_internal.h | 2 ++ src/audio_output/dec.c | 11 +++++++++++ src/input/decoder.c | 2 ++ src/input/decoder.h | 4 ++++ src/input/es_out.c | 26 ++++++++++++++++++++++++++ src/input/input_internal.h | 3 +++ src/input/stats.c | 4 ++++ 10 files changed, 60 insertions(+) diff --git a/include/vlc/libvlc_media.h b/include/vlc/libvlc_media.h index 47cdaecbd4..ae110545c5 100644 --- a/include/vlc/libvlc_media.h +++ b/include/vlc/libvlc_media.h @@ -135,6 +135,9 @@ typedef struct libvlc_media_stats_t uint64_t video_renderer_out_cnt; uint64_t audio_renderer_out_cnt; libvlc_time_t audio_latency; + + uint64_t audio_overrun; + uint64_t audio_underrun; } libvlc_media_stats_t; /** diff --git a/include/vlc_input_item.h b/include/vlc_input_item.h index 4e6968fc93..f2271a8e36 100644 --- a/include/vlc_input_item.h +++ b/include/vlc_input_item.h @@ -557,6 +557,9 @@ struct input_stats_t uintmax_t audio_renderer_out_cnt; vlc_tick_t audio_latency; + uintmax_t audio_underrun; + uintmax_t audio_overrun; + }; /** diff --git a/lib/media.c b/lib/media.c index 766ff70526..842ae812e6 100644 --- a/lib/media.c +++ b/lib/media.c @@ -762,6 +762,8 @@ bool libvlc_media_get_stats(libvlc_media_t *p_md, p_stats->video_renderer_out_cnt = p_itm_stats->video_renderer_out_cnt; p_stats->audio_renderer_out_cnt = p_itm_stats->audio_renderer_out_cnt; p_stats->audio_latency = p_itm_stats->audio_latency; + p_stats->audio_overrun = p_itm_stats->audio_overrun; + p_stats->audio_underrun = p_itm_stats->audio_underrun; vlc_mutex_unlock( &item->lock ); return true; diff --git a/src/audio_output/aout_internal.h b/src/audio_output/aout_internal.h index 1a8bf55c83..fb16640485 100644 --- a/src/audio_output/aout_internal.h +++ b/src/audio_output/aout_internal.h @@ -147,6 +147,8 @@ struct vlc_aout_stats { unsigned lost; unsigned played; + unsigned overrun; + unsigned underrun; vlc_tick_t latency; }; diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c index 86881364e7..01343a5068 100644 --- a/src/audio_output/dec.c +++ b/src/audio_output/dec.c @@ -99,6 +99,8 @@ struct vlc_aout_stream atomic_uint buffers_lost; atomic_uint buffers_played; + atomic_uint buffers_underrun; + atomic_uint buffers_overrun; _Atomic vlc_tick_t latency; vlc_tick_t last_latency; void (*on_new_latency_cb)(vlc_tick_t tick, void *data); @@ -285,6 +287,8 @@ vlc_aout_stream * vlc_aout_stream_New(audio_output_t *p_aout, atomic_init (&stream->buffers_lost, 0); atomic_init (&stream->buffers_played, 0); atomic_init (&stream->latency, 0); + atomic_init (&stream->buffers_overrun, 0); + atomic_init (&stream->buffers_underrun, 0); atomic_store_explicit(&owner->vp.update, true, memory_order_relaxed); atomic_init(&stream->drained, false); @@ -506,6 +510,8 @@ static void stream_HandleDrift(vlc_aout_stream *stream, vlc_tick_t drift, msg_Info(aout, "avstats: [RENDER][AUDIO][FLUSH] ts=%" PRId64 " drift=%" PRId64, vlc_tick_now(), drift); + + atomic_fetch_add_explicit(&stream->buffers_underrun, 1, memory_order_relaxed); if (!stream->sync.discontinuity) msg_Warn (aout, "playback way too late (%"PRId64"): " "flushing buffers", drift); @@ -530,6 +536,7 @@ static void stream_HandleDrift(vlc_aout_stream *stream, vlc_tick_t drift, msg_Info(aout, "avstats: [RENDER][AUDIO][SILENCE] ts=%" PRId64 " drift=%" PRId64, vlc_tick_now(), drift); + atomic_fetch_add_explicit(&stream->buffers_overrun, 1, memory_order_relaxed); msg_Warn (aout, "playback way too early (%"PRId64"): " "playing silence", drift); } @@ -860,6 +867,10 @@ void vlc_aout_stream_GetResetStats(vlc_aout_stream *stream, stats->played = atomic_exchange_explicit(&stream->buffers_played, 0, memory_order_relaxed); stats->latency = atomic_load_explicit(&stream->latency, memory_order_relaxed); + stats->underrun = atomic_exchange_explicit(&stream->buffers_underrun, 0, + memory_order_relaxed); + stats->overrun = atomic_exchange_explicit(&stream->buffers_overrun, 0, + memory_order_relaxed); } void vlc_aout_stream_ChangePause(vlc_aout_stream *stream, bool paused, vlc_tick_t date) diff --git a/src/input/decoder.c b/src/input/decoder.c index ef414590fe..a50e977753 100644 --- a/src/input/decoder.c +++ b/src/input/decoder.c @@ -1518,6 +1518,8 @@ static void ModuleThread_QueueAudio( decoder_t *p_dec, vlc_frame_t *p_aout_buf ) vlc_fifo_Unlock(p_owner->p_fifo); decoder_Notify(p_owner, on_new_audio_stats, 1, stats.lost, stats.played, stats.latency); + decoder_Notify(p_owner, on_new_audio_sk_stats, + stats.overrun, stats.underrun); } static void ModuleThread_PlaySpu( vlc_input_decoder_t *p_owner, subpicture_t *p_subpic ) diff --git a/src/input/decoder.h b/src/input/decoder.h index 32f3dc5840..422da02cb2 100644 --- a/src/input/decoder.h +++ b/src/input/decoder.h @@ -47,6 +47,10 @@ struct vlc_input_decoder_callbacks { void *userdata); void (*on_new_audio_stats)(vlc_input_decoder_t *decoder, unsigned decoded, unsigned lost, unsigned played, vlc_tick_t latency, void *userdata); + void (*on_new_audio_sk_stats)(vlc_input_decoder_t *decoder, + unsigned overrun, unsigned underrun, + void *userdata); + void (*on_new_decoder_stats)(vlc_input_decoder_t *decoder, enum es_format_category_e cat, uintmax_t cnt_in, uintmax_t cnt_out, diff --git a/src/input/es_out.c b/src/input/es_out.c index 349cd0697e..7fc8005717 100644 --- a/src/input/es_out.c +++ b/src/input/es_out.c @@ -535,6 +535,31 @@ 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_sk_stats(vlc_input_decoder_t *decoder, + unsigned overrun, unsigned underun, + 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) + return; + + struct input_stats *stats = input_priv(p_sys->p_input)->stats; + if (!stats) + return; + + atomic_fetch_add_explicit(&stats->audio_overrun, overrun, + memory_order_relaxed); + atomic_fetch_add_explicit(&stats->audio_underrun, underun, + memory_order_relaxed); +} + + static void decoder_on_new_audio_latency(vlc_input_decoder_t *decoder, vlc_tick_t latency, void *userdata) @@ -619,6 +644,7 @@ static const struct vlc_input_decoder_callbacks decoder_cbs = { .on_new_video_stats = decoder_on_new_video_stats, .on_new_video_sk_stats = decoder_on_new_video_sk_stats, .on_new_audio_stats = decoder_on_new_audio_stats, + .on_new_audio_sk_stats = decoder_on_new_audio_sk_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 1f94c71df9..743ea15054 100644 --- a/src/input/input_internal.h +++ b/src/input/input_internal.h @@ -783,6 +783,9 @@ struct input_stats { atomic_uintmax_t video_renderer_out_cnt; atomic_uintmax_t audio_renderer_out_cnt; _Atomic vlc_tick_t audio_latency; + + atomic_uintmax_t audio_overrun; + atomic_uintmax_t audio_underrun; }; struct input_stats *input_stats_Create(void); diff --git a/src/input/stats.c b/src/input/stats.c index 7c0fc9ecbf..c02d943f2e 100644 --- a/src/input/stats.c +++ b/src/input/stats.c @@ -80,6 +80,8 @@ struct input_stats *input_stats_Create(void) atomic_init(&stats->audio_renderer_out_cnt, 0); atomic_init(&stats->audio_latency, 0); + atomic_init(&stats->audio_overrun, 0); + atomic_init(&stats->audio_underrun, 0); return stats; } @@ -137,6 +139,8 @@ void input_stats_Compute(struct input_stats *stats, input_stats_t *st) st->audio_renderer_out_cnt = atomic_load_explicit(&stats->audio_renderer_out_cnt, memory_order_relaxed); st->audio_latency = atomic_load_explicit(&stats->audio_latency, memory_order_relaxed); + st->audio_overrun = atomic_load_explicit(&stats->audio_overrun, memory_order_relaxed); + st->audio_underrun = atomic_load_explicit(&stats->audio_underrun, memory_order_relaxed); } /** Update a counter element with new values