[vlc-devel] [RFC PATCH 4/7] player: add vlc_player_aout_AddLoudnessMeter()

Thomas Guillem thomas at gllm.fr
Fri Aug 14 15:18:04 CEST 2020


---
 include/vlc_player.h |  76 +++++++++++++++++++++++++++++++
 src/libvlccore.sym   |   2 +
 src/player/aout.c    | 103 +++++++++++++++++++++++++++++++++++++++++++
 src/player/player.c  |   3 ++
 src/player/player.h  |   9 ++++
 5 files changed, 193 insertions(+)

diff --git a/include/vlc_player.h b/include/vlc_player.h
index ac5991982df..ad4d39536d4 100644
--- a/include/vlc_player.h
+++ b/include/vlc_player.h
@@ -2199,6 +2199,50 @@ struct vlc_player_aout_cbs
         void *data);
 };
 
+/**
+ * Player aout loudness meter opaque structure.
+ *
+ * This opaque structure is returned by vlc_player_aout_AddLoudnessMeter() and
+ * can be used to remove the listener via
+ * vlc_player_aout_RemoveLoudnessMeter().
+ */
+typedef struct vlc_player_aout_loudness_meter_id vlc_player_aout_loudness_meter_id;
+
+/**
+ * Loudness meter mode
+ */
+enum vlc_player_aout_loudness_meter_mode
+{
+    /** Very low CPU usage, only the Momentary Loudness will be processed */
+    VLC_PLAYER_AOUT_LOUDNESS_METER_BEST_PERFS,
+    /** High CPU usage, Momentary Loudness, Short Term Loudness Integrated
+     * Loudness, Loudness Range and True Peak will be processed. */
+    VLC_PLAYER_AOUT_LOUDNESS_METER_FULL,
+};
+
+/**
+ * Player aout loudness meter callbacks
+ *
+ * Can be registered with vlc_player_aout_AddLoudnessMeter().
+ */
+struct vlc_player_aout_loudness_cbs
+{
+
+    /**
+     * Called when loudness measurements have changed
+     *
+     * Only sent when audio is playing, approximately every 400ms (but can be
+     * higher, depending on the input sample size).
+     *
+     * @param aout the main aout of the player
+     * @param meter last loudness measurements
+     * @param data opaque pointer set by vlc_player_aout_AddLoudnessMeter()
+     */
+    void (*on_loudness_changed)(audio_output_t *aout,
+                                const struct vlc_audio_loudness_meter *meter,
+                                void *data);
+};
+
 /**
  * Get the audio output
  *
@@ -2353,6 +2397,38 @@ vlc_player_aout_ToggleMute(vlc_player_t *player)
 VLC_API int
 vlc_player_aout_EnableFilter(vlc_player_t *player, const char *name, bool add);
 
+
+/**
+ * Add an aout loudness meter
+ *
+ * @note The player instance doesn't need to be locked for vlc_player_aout_*()
+ * functions.
+ * @note Every registered loudness meter need to be removed by the caller with
+ * vlc_player_aout_RemoveLoudnessMeter().
+ *
+ * @param player player instance
+ * @param cbs pointer to a vlc_player_aout_loudness_cbs structure, the
+ * structure must be valid during the lifetime of the player
+ * @param cbs_data opaque pointer used by the callbacks
+ * @return a valid meter id, or NULL in case of error ("audio-meter" plugin
+ * missing)
+ */
+VLC_API vlc_player_aout_loudness_meter_id *
+vlc_player_aout_AddLoudnessMeter(vlc_player_t *player,
+                                 enum vlc_player_aout_loudness_meter_mode,
+                                 const struct vlc_player_aout_loudness_cbs *cbs,
+                                 void *cbs_data);
+
+/**
+ * Remove an aout loudness meter
+ *
+ * @param player player instance
+ * @param meter_id meter id returned by vlc_player_aout_AddLoudnessMeter()
+ */
+VLC_API void
+vlc_player_aout_RemoveLoudnessMeter(vlc_player_t *player,
+                                    vlc_player_aout_loudness_meter_id *meter_id);
+
 /** @} vlc_player__aout */
 
 /**
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index ed43c17715c..cf1916fd92c 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -774,6 +774,7 @@ vlc_player_AddListener
 vlc_player_AddSmpteTimer
 vlc_player_AddTimer
 vlc_player_aout_AddListener
+vlc_player_aout_AddLoudnessMeter
 vlc_player_aout_EnableFilter
 vlc_player_aout_GetVolume
 vlc_player_aout_Hold
@@ -782,6 +783,7 @@ vlc_player_aout_IncrementVolume
 vlc_player_aout_IsMuted
 vlc_player_aout_Mute
 vlc_player_aout_RemoveListener
+vlc_player_aout_RemoveLoudnessMeter
 vlc_player_aout_SetVolume
 vlc_player_ChangeRate
 vlc_player_CondWait
diff --git a/src/player/aout.c b/src/player/aout.c
index 8674cc65359..f962b53329b 100644
--- a/src/player/aout.c
+++ b/src/player/aout.c
@@ -26,6 +26,7 @@
 
 #include <vlc_common.h>
 #include <vlc_decoder.h>
+#include <vlc_modules.h>
 #include "player.h"
 #include "input/resource.h"
 
@@ -46,6 +47,106 @@ vlc_player_aout_Hold(vlc_player_t *player)
     return input_resource_HoldAout(player->resource);
 }
 
+VLC_API vlc_player_aout_loudness_meter_id *
+vlc_player_aout_AddLoudnessMeter(vlc_player_t *player,
+                                 enum vlc_player_aout_loudness_meter_mode mode,
+                                 const struct vlc_player_aout_loudness_cbs *cbs,
+                                 void *cbs_data)
+{
+    assert(cbs && cbs->on_loudness_changed);
+
+    if (!module_exists("ebur128"))
+        return NULL;
+
+    vlc_player_aout_loudness_meter_id *meter_id = malloc(sizeof(*meter_id));
+    if (meter_id == NULL)
+        return NULL;
+
+    meter_id->cbs = cbs;
+    meter_id->cbs_data = cbs_data;
+    meter_id->mode = mode;
+
+    vlc_mutex_lock(&player->aout_listeners_lock);
+
+    bool has_meter_module = !vlc_list_is_empty(&player->aout_loudness_meters);
+
+    enum vlc_player_aout_loudness_meter_mode prev_mode =
+        VLC_PLAYER_AOUT_LOUDNESS_METER_BEST_PERFS;
+    if (has_meter_module)
+    {
+        vlc_player_aout_loudness_meter_id *other_meter_id;
+        vlc_list_foreach(other_meter_id, &player->aout_loudness_meters, node)
+        {
+            if (other_meter_id->mode > prev_mode)
+                prev_mode = other_meter_id->mode;
+        }
+    }
+
+    vlc_list_append(&meter_id->node, &player->aout_loudness_meters);
+
+    vlc_mutex_unlock(&player->aout_listeners_lock);
+
+    if (!has_meter_module || mode > prev_mode)
+    {
+        audio_output_t *aout = vlc_player_aout_Hold(player);
+        if (aout != NULL)
+        {
+            var_SetBool(player, "ebur128-fullmeter",
+                        mode == VLC_PLAYER_AOUT_LOUDNESS_METER_FULL);
+            var_SetString(aout, "audio-meter", "ebur128");
+            aout_Release(aout);
+        }
+    }
+
+    return meter_id;
+}
+
+void
+vlc_player_aout_RemoveLoudnessMeter(vlc_player_t *player,
+                                    vlc_player_aout_loudness_meter_id *meter_id)
+{
+    assert(meter_id);
+
+    vlc_mutex_lock(&player->aout_listeners_lock);
+    vlc_list_remove(&meter_id->node);
+
+    bool has_meter_module = !vlc_list_is_empty(&player->aout_loudness_meters);
+
+    vlc_mutex_unlock(&player->aout_listeners_lock);
+    free(meter_id);
+
+    if (!has_meter_module)
+    {
+        audio_output_t *aout = vlc_player_aout_Hold(player);
+        if (aout != NULL)
+        {
+            var_SetString(aout, "audio-meter", NULL);
+            aout_Release(aout);
+        }
+    }
+}
+
+static int
+vlc_player_AoutLoudnessCallback(vlc_object_t *this, const char *var,
+                                vlc_value_t oldval, vlc_value_t newval, void *data)
+{
+    vlc_player_t *player = data;
+
+    struct vlc_audio_loudness_meter *meter = newval.p_address;
+
+    vlc_mutex_lock(&player->aout_listeners_lock);
+    vlc_player_aout_loudness_meter_id *meter_id;
+    vlc_list_foreach(meter_id, &player->aout_loudness_meters, node)
+    {
+        meter_id->cbs->on_loudness_changed((audio_output_t *)this,
+                                            meter, meter_id->cbs_data);
+    }
+    vlc_mutex_unlock(&player->aout_listeners_lock);
+
+    (void) var; (void) oldval;
+    return VLC_SUCCESS;
+}
+
 vlc_player_aout_listener_id *
 vlc_player_aout_AddListener(vlc_player_t *player,
                             const struct vlc_player_aout_cbs *cbs,
@@ -202,6 +303,7 @@ vlc_player_aout_AddCallbacks(vlc_player_t *player)
     var_AddCallback(aout, "volume", vlc_player_AoutCallback, player);
     var_AddCallback(aout, "mute", vlc_player_AoutCallback, player);
     var_AddCallback(aout, "device", vlc_player_AoutCallback, player);
+    var_AddCallback(aout, "loudness-meter", vlc_player_AoutLoudnessCallback, player);
 
     aout_Release(aout);
 }
@@ -216,6 +318,7 @@ vlc_player_aout_DelCallbacks(vlc_player_t *player)
     var_DelCallback(aout, "volume", vlc_player_AoutCallback, player);
     var_DelCallback(aout, "mute", vlc_player_AoutCallback, player);
     var_DelCallback(aout, "device", vlc_player_AoutCallback, player);
+    var_DelCallback(aout, "loudness-meter", vlc_player_AoutLoudnessCallback, player);
 
     aout_Release(aout);
 }
diff --git a/src/player/player.c b/src/player/player.c
index fd072e414b5..e74c29e6d9c 100644
--- a/src/player/player.c
+++ b/src/player/player.c
@@ -1893,6 +1893,7 @@ vlc_player_Delete(vlc_player_t *player)
     assert(vlc_list_is_empty(&player->listeners));
     assert(vlc_list_is_empty(&player->vout_listeners));
     assert(vlc_list_is_empty(&player->aout_listeners));
+    assert(vlc_list_is_empty(&player->aout_loudness_meters));
 
     vlc_mutex_unlock(&player->lock);
 
@@ -1934,6 +1935,7 @@ vlc_player_New(vlc_object_t *parent, enum vlc_player_lock_type lock_type,
     vlc_list_init(&player->listeners);
     vlc_list_init(&player->vout_listeners);
     vlc_list_init(&player->aout_listeners);
+    vlc_list_init(&player->aout_loudness_meters);
     vlc_list_init(&player->destructor.inputs);
     vlc_list_init(&player->destructor.stopping_inputs);
     vlc_list_init(&player->destructor.joinable_inputs);
@@ -1973,6 +1975,7 @@ vlc_player_New(vlc_object_t *parent, enum vlc_player_lock_type lock_type,
     VAR_CREATE("audio-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
     VAR_CREATE("mute", VLC_VAR_BOOL);
     VAR_CREATE("corks", VLC_VAR_INTEGER);
+    VAR_CREATE("ebur128-fullmeter", VLC_VAR_BOOL);
 
     /* es_out variables */
     VAR_CREATE("sout", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
diff --git a/src/player/player.h b/src/player/player.h
index 87b9e430330..e4fafbab087 100644
--- a/src/player/player.h
+++ b/src/player/player.h
@@ -140,6 +140,14 @@ struct vlc_player_aout_listener_id
     struct vlc_list node;
 };
 
+struct vlc_player_aout_loudness_meter_id
+{
+    const struct vlc_player_aout_loudness_cbs *cbs;
+    void *cbs_data;
+    enum vlc_player_aout_loudness_meter_mode mode;
+    struct vlc_list node;
+};
+
 enum vlc_player_timer_source_type
 {
     VLC_PLAYER_TIMER_TYPE_BEST,
@@ -224,6 +232,7 @@ struct vlc_player_t
 
     struct vlc_list listeners;
     struct vlc_list aout_listeners;
+    struct vlc_list aout_loudness_meters;
     struct vlc_list vout_listeners;
 
     input_resource_t *resource;
-- 
2.28.0



More information about the vlc-devel mailing list