[vlc-devel] [PATCH v3 19/19] audio_output: Add PPAPI plugin
Rémi Denis-Courmont
remi at remlab.net
Tue Mar 21 07:27:46 CET 2017
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.
--
Rémi Denis-Courmont
More information about the vlc-devel
mailing list