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

Jean-Baptiste Kempf jb at videolan.org
Sat Aug 15 13:12:54 CEST 2020


Why a specific function for loundness and not an extra metadata one?

On Fri, 14 Aug 2020, at 15:18, Thomas Guillem wrote:
> ---
>  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
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel

-- 
Jean-Baptiste Kempf -  President
+33 672 704 734


More information about the vlc-devel mailing list