[vlc-devel] [PATCH v2 18/18] audio_output: Add PPAPI plugin
Dennis Hamester
dhamester at jusst.de
Mon Mar 13 12:37:04 CET 2017
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 | 8 ++
modules/audio_output/ppapi.c | 261 +++++++++++++++++++++++++++++++++++++++
2 files changed, 269 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..7859de936e 100644
--- a/modules/audio_output/Makefile.am
+++ b/modules/audio_output/Makefile.am
@@ -12,6 +12,14 @@ 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_CFLAGS = $(AM_CFLAGS)
+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
More information about the vlc-devel
mailing list