[vlc-devel] [PATCH 1/2] libvlc: add media_player metadata listener API
Thomas Guillem
thomas at gllm.fr
Mon Jan 18 16:32:14 UTC 2021
For now, it is only used for propagating loudness measurements.
---
include/vlc/libvlc_media_player.h | 133 ++++++++++++++++++++++++++++++
lib/libvlc.sym | 2 +
lib/media_player.c | 103 +++++++++++++++++++++++
3 files changed, 238 insertions(+)
diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
index 8dd85d16049..a0398883c88 100644
--- a/include/vlc/libvlc_media_player.h
+++ b/include/vlc/libvlc_media_player.h
@@ -2608,6 +2608,139 @@ LIBVLC_API int libvlc_media_player_set_role(libvlc_media_player_t *p_mi,
/** @} audio */
+/** \defgroup libvlc_media_player_metadata_cbs LibVLC media player metadata callbacks
+ * @{
+ */
+
+/**
+ * Media player metadata listener opaque structure.
+ *
+ * This opaque structure is returned by
+ * libvlc_media_player_add_metadata_listener() and can be used to remove the
+ * listener via libvlc_media_player_remove_metadata_listener().
+ */
+typedef struct libvlc_media_player_metadata_listener_id
+ libvlc_media_player_metadata_listener_id;
+
+/**
+ * Audio loudness measurement
+ */
+struct libvlc_audio_loudness
+{
+ /** Momentary loudness (last 400 ms), in LUFS */
+ double loudness_momentary;
+ /** Short term loudness (last 3seconds), in LUFS */
+ double loudness_shortterm;
+ /** Integrated loudness (global), in LUFS */
+ double loudness_integrated;
+ /** Loudness range, in LU */
+ double loudness_range;
+ /** True Peak, in dBTP */
+ double truepeak;
+};
+
+/**
+ * Player metadata option
+ */
+enum libvlc_media_player_metadata_option
+{
+ /**
+ * Ask for momentary loudness measurement
+ *
+ * Very low CPU usage.
+ * @see libvlc_media_player_metadata_cbs.on_momentary_loudness_changed
+ */
+ LIBVLC_MEDIA_PLAYER_METADATA_LOUDNESS_MOMENTARY,
+
+ /**
+ * Ask for all loudness measurements
+ *
+ * High CPU usage.
+ * @see libvlc_media_player_metadata_cbs.on_loudness_changed
+ */
+ LIBVLC_MEDIA_PLAYER_METADATA_LOUDNESS_FULL,
+};
+
+/**
+ * Player metadata callbacks
+ *
+ * Can be registered with libvlc_media_player_add_metadata_listener().
+ *
+ * @warning To avoid deadlocks, users should never call libvlc_media_player_t
+ * functions from these callbacks.
+ */
+union libvlc_media_player_metadata_cbs
+{
+ /**
+ * Called when the momentary loudness measurement have changed
+ *
+ * @see VLC_PLAYER_METADATA_LOUDNESS_MOMEMTARY
+ *
+ * Only sent when audio is playing, approximately every 400ms (but can be
+ * higher, depending on the input sample size).
+ *
+ * @param date Absolute date of the measurement. It is most likely in the
+ * future (0 to 2seconds) depending on the audio output buffer size. Use
+ * \ref libvlc_delay to get the relative delay until this date is reached.
+ * @param momentary_loudness Momentary loudness
+ * @param data opaque pointer set by
+ * libvlc_media_player_add_metadata_listener()
+ */
+ void (*on_momentary_loudness_changed)(libvlc_time_t date,
+ double momentary_loudness,
+ void *data);
+
+ /**
+ * Called when loudness measurements have changed
+ *
+ * @see VLC_PLAYER_METADATA_LOUDNESS_FULL
+ *
+ * Only sent when audio is playing, approximately every 400ms (but can be
+ * higher, depending on the input sample size).
+ *
+ * @param date Absolute date of the measurement. It is most likely in the
+ * future (0 to 2seconds) depending on the audio output buffer size. Use
+ * \ref libvlc_delay to get the relative delay until this date is reached.
+ * @param loudness loudness measurement
+ * @param data opaque pointer set by
+ * libvlc_media_player_add_metadata_listener()
+ */
+ void (*on_loudness_changed)(libvlc_time_t date,
+ const struct libvlc_audio_loudness *loudness,
+ void *data);
+};
+
+/**
+ * Add a metadata listener
+ *
+ * @note Every registered loudness meter need to be removed by the caller with
+ * libvlc_media_player_remove_metadata_listener().
+ *
+ * @param mp media player
+ * @param cbs pointer to a libvlc_media_player_metadata_cbs union, the
+ * structure must be valid during the lifetime of the player
+ * @param cbs_data opaque pointer used by the callbacks
+ * @return a valid listener id, or NULL in case of error (plugin missing)
+ */
+LIBVLC_API libvlc_media_player_metadata_listener_id *
+libvlc_media_player_add_metadata_listener(libvlc_media_player_t *mp,
+ enum libvlc_media_player_metadata_option option,
+ const union libvlc_media_player_metadata_cbs *cbs,
+ void *cbs_data);
+
+/**
+ * Remove a metadata listener
+ *
+ * @param mp media player
+ * @param id listener id returned by libvlc_media_player_add_metadata_listener()
+ */
+LIBVLC_API void
+libvlc_media_player_remove_metadata_listener(libvlc_media_player_t *mp,
+ libvlc_media_player_metadata_listener_id *id);
+
+
+/** @} libvlc_media_player_metadata_cbs */
+
/** @} media_player */
# ifdef __cplusplus
diff --git a/lib/libvlc.sym b/lib/libvlc.sym
index f30d67f3a9e..db476bda970 100644
--- a/lib/libvlc.sym
+++ b/lib/libvlc.sym
@@ -198,6 +198,8 @@ libvlc_media_player_select_program_id
libvlc_media_player_get_selected_program
libvlc_media_player_get_program_from_id
libvlc_media_player_get_programlist
+libvlc_media_player_add_metadata_listener
+libvlc_media_player_remove_metadata_listener
libvlc_media_release
libvlc_media_retain
libvlc_media_save_meta
diff --git a/lib/media_player.c b/lib/media_player.c
index 58dfbc39fb6..7ed306ece2b 100644
--- a/lib/media_player.c
+++ b/lib/media_player.c
@@ -2188,6 +2188,109 @@ int libvlc_media_player_get_role(libvlc_media_player_t *mp)
return ret;
}
+struct libvlc_media_player_metadata_listener_id
+{
+ vlc_player_metadata_listener_id *id;
+ union libvlc_media_player_metadata_cbs cbs;
+ void *cbs_data;
+};
+
+static void
+metadata_wrapper_on_momentary_loudness_changed(vlc_tick_t date,
+ double momentary_loudness,
+ void *data)
+{
+
+ libvlc_media_player_metadata_listener_id *wrapper = data;
+ wrapper->cbs.on_momentary_loudness_changed(date, momentary_loudness,
+ wrapper->cbs_data);
+}
+
+static void
+metadata_wrapper_on_loudness_changed(vlc_tick_t date,
+ const struct vlc_audio_loudness *vlc_loudness,
+ void *data)
+{
+
+ libvlc_media_player_metadata_listener_id *wrapper = data;
+
+ const struct libvlc_audio_loudness loudness = {
+ .loudness_momentary = vlc_loudness->loudness_momentary,
+ .loudness_shortterm = vlc_loudness->loudness_shortterm,
+ .loudness_integrated = vlc_loudness->loudness_integrated,
+ .loudness_range = vlc_loudness->loudness_range,
+ .truepeak = vlc_loudness->truepeak,
+ };
+ wrapper->cbs.on_loudness_changed(date, &loudness, wrapper->cbs_data);
+}
+
+libvlc_media_player_metadata_listener_id *
+libvlc_media_player_add_metadata_listener(libvlc_media_player_t *mp,
+ enum libvlc_media_player_metadata_option option,
+ const union libvlc_media_player_metadata_cbs *cbs,
+ void *cbs_data)
+{
+ vlc_player_t *player = mp->player;
+
+ libvlc_media_player_metadata_listener_id *wrapper = malloc(sizeof(*wrapper));
+ if (wrapper == NULL)
+ return NULL;
+
+ wrapper->cbs = *cbs;
+ wrapper->cbs_data = cbs_data;
+
+ enum vlc_player_metadata_option vlc_option;
+ union vlc_player_metadata_cbs *vlc_cbs;
+
+ switch (option)
+ {
+ case LIBVLC_MEDIA_PLAYER_METADATA_LOUDNESS_MOMENTARY:
+ {
+ vlc_option = VLC_PLAYER_METADATA_LOUDNESS_MOMENTARY;
+ static union vlc_player_metadata_cbs cbs_momentary_loudness = {
+ .on_momentary_loudness_changed = metadata_wrapper_on_momentary_loudness_changed,
+ };
+ vlc_cbs = &cbs_momentary_loudness;
+ break;
+ }
+ case LIBVLC_MEDIA_PLAYER_METADATA_LOUDNESS_FULL:
+ {
+ vlc_option = VLC_PLAYER_METADATA_LOUDNESS_FULL;
+ static union vlc_player_metadata_cbs cbs_loudness = {
+ .on_loudness_changed = metadata_wrapper_on_loudness_changed,
+ };
+ vlc_cbs = &cbs_loudness;
+ break;
+ }
+ default: vlc_assert_unreachable();
+ }
+
+ vlc_player_Lock(player);
+ vlc_player_metadata_listener_id *id =
+ vlc_player_AddMetadataListener(player, vlc_option, vlc_cbs, wrapper);
+ vlc_player_Unlock(player);
+
+ if (id != NULL)
+ wrapper->id = id;
+ else
+ free(wrapper);
+
+ return wrapper;
+}
+
+void
+libvlc_media_player_remove_metadata_listener(libvlc_media_player_t *mp,
+ libvlc_media_player_metadata_listener_id *wrapper)
+{
+ vlc_player_t *player = mp->player;
+
+ vlc_player_Lock(player);
+ vlc_player_RemoveMetadataListener(player, wrapper->id);
+ vlc_player_Unlock(player);
+ free(wrapper);
+}
+
+
#include <vlc_vout_display.h>
/* make sure surface structures from libvlc can be passed as such to vlc
--
2.29.2
More information about the vlc-devel
mailing list