[vlc-devel] [PATCH v3 19/19] audio_output: Add PPAPI plugin

Rémi Denis-Courmont remi at remlab.net
Tue Mar 21 11:37:05 CET 2017


On March 21, 2017 10:30:11 AM GMT+02:00, Thomas Guillem <thomas at gllm.fr> wrote:
>
>
>On Tue, Mar 21, 2017, at 09:18, Julian Scheel wrote:
>> On 21.03.2017 08:33, Thomas Guillem wrote:
>> >
>> >
>> > On Tue, Mar 21, 2017, at 07:27, Rémi Denis-Courmont wrote:
>> >> On March 20, 2017 6:57:36 PM GMT+02:00, Dennis Hamester
>> >> <dhamester at jusst.de> wrote:
>> >>> From: Julian Scheel <julian at jusst.de>
>> >>>
>> >>> Audio output using PPAPI to allow audio output when running as
>> >>> NativeClient.
>> >>>
>> >>> Signed-off-by: Julian Scheel <julian at jusst.de>
>> >>> ---
>> >>> modules/audio_output/Makefile.am |   7 ++
>> >>> modules/audio_output/ppapi.c     | 261
>> >>> +++++++++++++++++++++++++++++++++++++++
>> >>> 2 files changed, 268 insertions(+)
>> >>> create mode 100644 modules/audio_output/ppapi.c
>> >>>
>> >>> diff --git a/modules/audio_output/Makefile.am
>> >>> b/modules/audio_output/Makefile.am
>> >>> index 9006c257cb..744621e54c 100644
>> >>> --- a/modules/audio_output/Makefile.am
>> >>> +++ b/modules/audio_output/Makefile.am
>> >>> @@ -12,6 +12,13 @@ if HAVE_ANDROID
>> >>> aout_LTLIBRARIES += libandroid_audiotrack_plugin.la
>> >>> libopensles_android_plugin.la
>> >>> endif
>> >>>
>> >>> +libppapi_audio_plugin_la_SOURCES = audio_output/ppapi.c
>> >>> +libppapi_audio_plugin_la_LIBADD = $(LIBS_nacl)
>> >>> +
>> >>> +if HAVE_NACL
>> >>> +aout_LTLIBRARIES += libppapi_audio_plugin.la
>> >>> +endif
>> >>> +
>> >>> libadummy_plugin_la_SOURCES = audio_output/adummy.c
>> >>>
>> >>> libafile_plugin_la_SOURCES = audio_output/file.c
>> >>> diff --git a/modules/audio_output/ppapi.c
>> >>> b/modules/audio_output/ppapi.c
>> >>> new file mode 100644
>> >>> index 0000000000..16aa08cc98
>> >>> --- /dev/null
>> >>> +++ b/modules/audio_output/ppapi.c
>> >>> @@ -0,0 +1,261 @@
>> >>>
>+/*****************************************************************************
>> >>> + * ppapi.c: Audio output using PPAPI on NativeClient
>> >>> +
>> >>>
>*****************************************************************************
>> >>> + * Copyright © 2017 VLC authors and VideoLAN
>> >>> + *
>> >>> + * Authors: Julian Scheel <julian at jusst.de>
>> >>> + *
>> >>> + * This program is free software; you can redistribute it and/or
>> >>> modify it
>> >>> + * under the terms of the GNU Lesser General Public License as
>> >>> published by
>> >>> + * the Free Software Foundation; either version 2.1 of the
>License, or
>> >>> + * (at your option) any later version.
>> >>> + *
>> >>> + * This program is distributed in the hope that it will be
>useful,
>> >>> + * but WITHOUT ANY WARRANTY; without even the implied warranty
>of
>> >>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> >>> + * GNU Lesser General Public License for more details.
>> >>> + *
>> >>> + * You should have received a copy of the GNU Lesser General
>Public
>> >>> License
>> >>> + * along with this program; if not, write to the Free Software
>> >>> Foundation,
>> >>> + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301,
>USA.
>> >>> +
>> >>>
>*****************************************************************************/
>> >>> +#ifdef HAVE_CONFIG_H
>> >>> +# include "config.h"
>> >>> +#endif
>> >>> +
>> >>> +#include <vlc_common.h>
>> >>> +#include <vlc_atomic.h>
>> >>> +#include <vlc_plugin.h>
>> >>> +#include <vlc_aout.h>
>> >>> +#include <vlc_block_helper.h>
>> >>> +#include <vlc_plugin.h>
>> >>> +#include <vlc_threads.h>
>> >>> +
>> >>> +#include <ppapi/c/pp_instance.h>
>> >>> +#include <ppapi/c/ppb_audio_config.h>
>> >>> +#include <ppapi/c/ppb_audio.h>
>> >>> +#include <ppapi/c/ppb_core.h>
>> >>> +#include <ppapi/c/ppb.h>
>> >>> +
>> >>>
>+/*****************************************************************************
>> >>> + * Module descriptor
>> >>> +
>> >>>
>*****************************************************************************/
>> >>> +static int Open(vlc_object_t *);
>> >>> +static void Close(vlc_object_t *);
>> >>> +
>> >>> +vlc_module_begin()
>> >>> +    set_shortname("PPAPI aout")
>> >>> +    set_description(N_("PPAPI based audio output"))
>> >>> +    set_category(CAT_AUDIO)
>> >>> +    set_subcategory(SUBCAT_AUDIO_AOUT)
>> >>> +
>> >>> +    set_capability("audio output", 50)
>> >>> +    set_callbacks(Open, Close)
>> >>> +vlc_module_end()
>> >>> +
>> >>>
>+/*****************************************************************************
>> >>> + * Local prototypes.
>> >>> +
>> >>>
>*****************************************************************************/
>> >>> +struct aout_sys_t
>> >>> +{
>> >>> +    block_bytestream_t data;
>> >>> +
>> >>> +    atomic_bool flushing;
>> >>> +    vlc_cond_t flushed_signal;
>> >>> +    vlc_mutex_t mutex;
>> >>> +
>> >>> +    vlc_atomic_float latency;
>> >>> +    unsigned samplerate;
>> >>> +
>> >>> +    PP_Instance instance;
>> >>> +    PP_Resource config;
>> >>> +    PP_Resource context;
>> >>> +
>> >>> +    PPB_AudioConfig *audioconfig;
>> >>> +    PPB_Audio *audio;
>> >>> +    PPB_Core *core;
>> >>> +};
>> >>> +
>> >>>
>+/*****************************************************************************
>> >>> + * Implementation
>> >>> +
>> >>>
>*****************************************************************************/
>> >>> +static void ppapi_audio_callback(void *sample_buffer,
>> >>> +        uint32_t buffer_size_in_bytes, PP_TimeDelta latency,
>void*
>> >>> user_data)
>> >>> +{
>> >>> +    audio_output_t *aout = user_data;
>> >>> +    aout_sys_t *sys = aout->sys;
>> >>> +
>> >>> +    vlc_atomic_store_float(&sys->latency, latency);
>> >>> +
>> >>> +    if (block_GetBytes(&sys->data, sample_buffer,
>> >>> buffer_size_in_bytes) != VLC_SUCCESS) {
>> >>> +        if (atomic_load(&sys->flushing)) {
>> >>> +            block_BytestreamEmpty(&sys->data);
>> >>> +            vlc_mutex_lock(&sys->mutex);
>> >>> +            vlc_cond_signal(&sys->flushed_signal);
>> >>> +            vlc_mutex_unlock(&sys->mutex);
>> >>> +        } else {
>> >>> +            memset(sample_buffer, 0x00, buffer_size_in_bytes);
>> >>> +        }
>> >>> +    }
>> >>> +
>> >>> +    block_BytestreamFlush(&sys->data);
>> >>> +}
>> >>> +
>> >>> +static int Start(audio_output_t *aout, audio_sample_format_t
>*restrict
>> >>> fmt)
>> >>> +{
>> >>> +    aout_sys_t *sys = aout->sys;
>> >>> +
>> >>> +    sys->samplerate = fmt->i_rate;
>> >>> +
>> >>> +    /* Create audio config */
>> >>> +    uint32_t sample_frame_count =
>> >>> sys->audioconfig->RecommendSampleFrameCount(
>> >>> +            sys->instance, sys->samplerate, 512);
>> >>> +
>> >>> +    msg_Dbg(aout, "Using sample_frame_count of %u",
>> >>> sample_frame_count);
>> >>> +
>> >>> +    sys->config =
>sys->audioconfig->CreateStereo16Bit(sys->instance,
>> >>> +            sys->samplerate, sample_frame_count);
>> >>> +    if (unlikely(sys->config) == 0) {
>> >>> +        msg_Err(aout, "Could not create PPAPI audio config");
>> >>> +        goto error;
>> >>> +    }
>> >>> +
>> >>> +    /* Create audio context */
>> >>> +    sys->context = sys->audio->Create(sys->instance,
>sys->config,
>> >>> +            ppapi_audio_callback, aout);
>> >>> +    if (unlikely(sys->context) == 0) {
>> >>> +        msg_Err(aout, "Could not create PPAPI audio resource");
>> >>> +        goto error;
>> >>> +    }
>> >>> +
>> >>> +    /* Enforce stereo output S16N output */
>> >>> +    fmt->i_format = VLC_CODEC_S16N;
>> >>> +    fmt->i_original_channels = fmt->i_physical_channels =
>> >>> AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
>> >>> +
>> >>> +    sys->audio->StartPlayback(sys->context);
>> >>> +
>> >>> +    return VLC_SUCCESS;
>> >>> +
>> >>> +error:
>> >>> +    if (sys->config != 0)
>> >>> +        sys->core->ReleaseResource(sys->config);
>> >>> +
>> >>> +    return VLC_EGENERIC;
>> >>> +}
>> >>> +
>> >>> +static void Stop(audio_output_t *aout)
>> >>> +{
>> >>> +    aout_sys_t *sys = aout->sys;
>> >>> +
>> >>> +    if (unlikely(sys->context == 0))
>> >>> +        return;
>> >>> +
>> >>> +    if (sys->audio->StopPlayback(sys->context) != PP_TRUE)
>> >>> +        msg_Warn(aout, "Failed to stop playback");
>> >>> +
>> >>> +    sys->core->ReleaseResource(sys->context);
>> >>> +    sys->context = 0;
>> >>> +}
>> >>> +
>> >>> +static int TimeGet(audio_output_t *aout, mtime_t *delay)
>> >>> +{
>> >>> +    aout_sys_t *sys = aout->sys;
>> >>> +
>> >>> +    *delay = vlc_atomic_load_float(&sys->latency) * CLOCK_FREQ +
>> >>> +        (block_BytestreamRemaining(&sys->data) / 4) * CLOCK_FREQ
>/
>> >>> sys->samplerate;
>> >>> +
>> >>> +    return VLC_SUCCESS;
>> >>> +}
>> >>> +
>> >>> +static void Play(audio_output_t *aout, block_t *block)
>> >>> +{
>> >>> +    aout_sys_t *sys = aout->sys;
>> >>> +
>> >>> +    block_BytestreamPush(&sys->data, block);
>> >>> +}
>> >>> +
>> >>> +static void Flush(audio_output_t *aout, bool wait)
>> >>> +{
>> >>> +    aout_sys_t *sys = aout->sys;
>> >>> +
>> >>> +    if (wait) {
>> >>> +        atomic_store(&sys->flushing, true);
>> >>> +        vlc_mutex_lock(&sys->mutex);
>> >>> +        vlc_cond_wait(&sys->flushed_signal, &sys->mutex);
>> >>> +        vlc_mutex_unlock(&sys->mutex);
>> >>> +        atomic_store(&sys->flushing, false);
>> >>> +    } else {
>> >>> +        block_BytestreamEmpty(&sys->data);
>> >>> +    }
>> >>> +}
>> >>> +
>> >>> +static int Open(vlc_object_t *obj)
>> >>> +{
>> >>> +    audio_output_t *aout = (audio_output_t *)obj;
>> >>> +    aout_sys_t *sys;
>> >>> +
>> >>> +    sys = calloc(1, sizeof(*sys));
>> >>> +    if (unlikely(sys == NULL))
>> >>> +        return VLC_ENOMEM;
>> >>> +    aout->sys = sys;
>> >>> +
>> >>> +    PPB_GetInterface ppb_get_interface = var_InheritAddress(obj,
>> >>> "ppapi-ppb-get-interface");
>> >>> +    if (ppb_get_interface == NULL) {
>> >>> +        msg_Err(aout, "Variable ppapi-ppb-get-interface is not
>set");
>> >>> +        goto error;
>> >>> +    }
>> >>> +
>> >>> +    sys->instance = (int)var_InheritInteger(obj,
>"ppapi-instance");
>> >>> +    if (unlikely(sys->instance == 0)) {
>> >>> +        msg_Err(aout, "Variable ppapi-instance is not set");
>> >>> +        goto error;
>> >>> +    }
>> >>> +
>> >>> +    sys->core =
>(PPB_Core*)ppb_get_interface(PPB_CORE_INTERFACE);
>> >>> +    if (sys->core == NULL) {
>> >>> +        msg_Err(aout, "Failed to get PPB_CORE_INTERFACE");
>> >>> +        goto error;
>> >>> +    }
>> >>> +
>> >>> +    sys->audio =
>(PPB_Audio*)ppb_get_interface(PPB_AUDIO_INTERFACE);
>> >>> +    if (unlikely(sys->audio == NULL)) {
>> >>> +        msg_Err(aout, "Failed to get PPB_AUDIO_INTERFACE");
>> >>> +        goto error;
>> >>> +    }
>> >>> +
>> >>> +    sys->audioconfig =
>> >>> (PPB_AudioConfig*)ppb_get_interface(PPB_AUDIO_CONFIG_INTERFACE);
>> >>> +    if (unlikely(sys->audioconfig == NULL)) {
>> >>> +        msg_Err(aout, "Failed to get
>PPB_AUDIO_CONFIG_INTERFACE");
>> >>> +        goto error;
>> >>> +    }
>> >>> +
>> >>> +    block_BytestreamInit(&sys->data);
>> >>> +
>> >>> +    aout->start = Start;
>> >>> +    aout->stop = Stop;
>> >>> +    aout->time_get = TimeGet;
>> >>> +    aout->play = Play;
>> >>> +    aout->flush = Flush;
>> >>> +
>> >>> +    return VLC_SUCCESS;
>> >>> +
>> >>> +error:
>> >>> +    Close(obj);
>> >>> +    return VLC_EGENERIC;
>> >>> +}
>> >>> +
>> >>> +static void Close(vlc_object_t *obj)
>> >>> +{
>> >>> +    audio_output_t *aout = (audio_output_t *)obj;
>> >>> +    aout_sys_t *sys = aout->sys;
>> >>> +
>> >>> +    block_BytestreamRelease(&sys->data);
>> >>> +
>> >>> +    if (sys->context != 0)
>> >>> +        sys->core->ReleaseResource(sys->context);
>> >>> +
>> >>> +    if (sys->config != 0)
>> >>> +        sys->core->ReleaseResource(sys->config);
>> >>> +
>> >>> +    free(sys);
>> >>> +}
>> >>> --
>> >>> 2.12.0
>> >>>
>> >>> _______________________________________________
>> >>> vlc-devel mailing list
>> >>> To unsubscribe or modify your subscription options:
>> >>> https://mailman.videolan.org/listinfo/vlc-devel
>> >>
>> >> Nack, thread synchronizatio' is totally broken here.
>> >
>> > Indeed, sys->data block_* call should be locked with a mutex in
>Play()
>> > and ppapi_audio_callback(). Locking from the audio callback may
>cause a
>> > real-time issue. Maybe we should implement a lock free 1 producer 1
>> > consumer queue. Or we don't care for now and remove every atomic
>and
>> > protect everything with mutexes.
>> 
>> Right, I was somehow under the impression that block_Bytestream had 
>> internal locking implemented. But that's obviously wrong. Sorry for 
>> missing that.
>> To avoid making this patch series even bigger I'd prefer to change
>this 
>> to use simple mutex locking for now.
>> In a second step we could think about porting to a lockfree queue.
>Would 
>> this be ok for you guys?
>
>Fine with me. We would also need a lockfree queue for the Apple aout,
>so
>maybe it should be a core feature, but let's focus on that later (after
>3.0).
>
>> 
>> -Julian
>> 
>> >> --
>> >> Rémi Denis-Courmont
>> >> _______________________________________________
>> >> 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
>> >
>> 
>> _______________________________________________
>> 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

Hello,

To me, lock-free implies wait-free. And this is not wait-free, so I don't understand what you are suggesting.
-- 
Rémi Denis-Courmont


More information about the vlc-devel mailing list