[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