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

Steve Lhomme robux4 at ycbcr.xyz
Mon Aug 17 09:50:38 CEST 2020


On 2020-08-17 9:41, Thomas Guillem wrote:
> What is metadata in this context ? I don't follow you.

The loudness value for each audio block.

> The loudness meter plugin should only be enabled when there is a listener.

That's based on your design. You could enable the metadata generator and 
(a) viewer(s) at the same time.

> What I could do instead of this API:
> 
> vlc_player_EnableLoudnessMeter(mode);
> vlc_player_DisableLoudnessMeter(mode);

In this case the viewer is a callback. But that means blending the 
loudness in the video/display is not possible with this API, unless one 
manages the display and blending on their own.

> This will increment/decrement a refcount, the plugin will be loaded, unloaded, restarted (mode change) according to this count. Then the user use the classical vlc_player listener API to receive meter callbacks.
> 
> On Sat, Aug 15, 2020, at 13:12, Jean-Baptiste Kempf wrote:
>> 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
>> _______________________________________________
>> vlc-devel mailing list
>> To unsubscribe or modify your subscription options:
>> https://mailman.videolan.org/listinfo/vlc-devel
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
> 


More information about the vlc-devel mailing list