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

Thomas Guillem thomas at gllm.fr
Tue Mar 21 08:33:55 CET 2017



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.


> -- 
> Rémi Denis-Courmont
> _______________________________________________
> 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