[vlc-devel] [PATCH] sndio: Updated sndio backend which actually works.
Brad Smith
brad at comstyle.com
Thu Jun 21 02:05:24 CEST 2012
sndio: Updated sndio backend which actually works.
Provided by Alexandre Ratchov <alex at caoua.org>
---
NEWS | 2 +-
configure.ac | 7 +-
modules/LIST | 2 +-
modules/audio_output/sndio.c | 237 +++++++++++++++++++++++++++---------------
4 files changed, 156 insertions(+), 92 deletions(-)
diff --git a/NEWS b/NEWS
index ecde695..6bbf5d0 100644
--- a/NEWS
+++ b/NEWS
@@ -31,7 +31,7 @@ Demuxers:
Audio output:
* Windows Audio Session API audio output support
- * OpenBSD sndio audio output support
+ * sndio audio output support
Audio Filters:
* new remapping channel filter
diff --git a/configure.ac b/configure.ac
index 3b66640..804577d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3443,14 +3443,11 @@ AC_SUBST(OSS_LIBS)
AM_CONDITIONAL([HAVE_OSS], [test "${have_oss}" = "yes"])
dnl
-dnl OpenBSD sndio module
+dnl sndio module
dnl
AC_ARG_ENABLE([sndio],
[AS_HELP_STRING([--disable-sndio],
- [support the OpenBSD sndio (default auto)])],, [
- AS_IF([test "$SYS" = "opensd"], [
- enable_sndio="yes"
- ])
+ [support sndio (default auto)])
])
have_sndio="no"
AS_IF([test "$enable_sndio" != "no"], [
diff --git a/modules/LIST b/modules/LIST
index 85f93a4..53da889 100644
--- a/modules/LIST
+++ b/modules/LIST
@@ -298,7 +298,7 @@ $Id$
* simple_channel_mixer: channel mixer
* skins2: Skinnable interface, new generation
* smf: Standard MIDI file demuxer
- * sndio: OpenBSD sndio audio output
+ * sndio: sndio audio output
* spatializer: A spatializer audio filter
* speex: a speex audio decoder/packetizer using the libspeex library
* speex_resampler: audio resampler using the libspeexdsp library
diff --git a/modules/audio_output/sndio.c b/modules/audio_output/sndio.c
index 17fcaed..875cd4b 100644
--- a/modules/audio_output/sndio.c
+++ b/modules/audio_output/sndio.c
@@ -2,6 +2,7 @@
* sndio.c : sndio plugin for VLC
*****************************************************************************
* Copyright (C) 2012 Rémi Denis-Courmont
+ * Copyright (C) 2012 Alexandre Ratchov
*
* 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
@@ -27,6 +28,7 @@
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_aout.h>
+#include <vlc_aout_intf.h>
#include <sndio.h>
@@ -35,7 +37,7 @@ static void Close (vlc_object_t *);
vlc_module_begin ()
set_shortname ("sndio")
- set_description (N_("OpenBSD sndio audio output"))
+ set_description (N_("sndio audio output"))
set_category (CAT_AUDIO)
set_subcategory (SUBCAT_AUDIO_AOUT)
set_capability ("audio output", 120)
@@ -44,150 +46,215 @@ vlc_module_end ()
static void Play (audio_output_t *, block_t *);
static void Pause (audio_output_t *, bool, mtime_t);
+static void Flush (audio_output_t *, bool);
+static int VolumeSet(audio_output_t *, float, bool);
+
+struct aout_sys_t
+{
+ struct sio_hdl *hdl;
+ int delay, bpf;
+};
+
+static void onmove (void *addr, int delta)
+{
+ audio_output_t *aout = (audio_output_t *)addr;
+ struct aout_sys_t *sys = (struct aout_sys_t *)aout->sys;
+
+ sys->delay -= delta;
+}
/** Initializes an sndio playback stream */
static int Open (vlc_object_t *obj)
{
+ char fourcc[4];
+ unsigned int chans;
audio_output_t *aout = (audio_output_t *)obj;
+ struct aout_sys_t *sys;
+ struct sio_hdl *hdl;
+ struct sio_par par;
- struct sio_hdl *sio = sio_open (NULL, SIO_PLAY, 0 /* blocking */);
- if (sio == NULL)
+ hdl = sio_open (NULL, SIO_PLAY, 0);
+ if (hdl == NULL)
{
msg_Err (obj, "cannot create audio playback stream");
return VLC_EGENERIC;
}
- struct sio_par par;
sio_initpar (&par);
- par.bits = 16;
- par.bps = par.bits >> 3;
- par.sig = 1;
- par.le = SIO_LE_NATIVE;
+ vlc_fourcc_to_char (aout->format.i_format, fourcc);
+ do {
+ if (fourcc[0] == 's')
+ par.sig = 1;
+ else if (fourcc[0] == 'u')
+ par.sig = 0;
+ else
+ break;
+ if (fourcc[1] == '8' && fourcc[2] == ' ' && fourcc[3] == ' ') {
+ par.bits = 8;
+ break;
+ } else if (fourcc[1] == '1' && fourcc[2] == '6') {
+ par.bits = 16;
+ } else if (fourcc[1] == '2' && fourcc[2] == '4') {
+ par.bits = 24;
+ par.bps = 3;
+ } else if (fourcc[1] == '3' && fourcc[2] == '2') {
+ par.bits = 32;
+ }
+ if (fourcc[3] == 'l')
+ par.le = 1;
+ else if (fourcc[3] == 'b')
+ par.le = 0;
+ else
+ break;
+ } while (0);
par.pchan = aout_FormatNbChannels (&aout->format);
par.rate = aout->format.i_rate;
- par.xrun = SIO_SYNC;
-
- if (!sio_setpar (sio, &par) || !sio_getpar (sio, &par))
+ par.appbufsz = par.rate / 2;
+ if (!sio_setpar (hdl, &par) || !sio_getpar (hdl, &par))
{
msg_Err (obj, "cannot negotiate audio playback parameters");
goto error;
}
- if (par.bps != par.bits >> 3)
- {
- msg_Err (obj, "unsupported audio sample format (%u bits in %u bytes)",
- par.bits, par.bps);
- goto error;
- }
-
- audio_format_t f;
-
- switch (par.bits)
- {
- case 8:
- f.i_format = par.sig ? VLC_CODEC_S8 : VLC_CODEC_U8;
- break;
- case 16:
- f.i_format = par.sig ? (par.le ? VLC_CODEC_S16L : VLC_CODEC_S16B)
- : (par.le ? VLC_CODEC_U16L : VLC_CODEC_U16B);
- break;
- case 24:
- f.i_format = par.sig ? (par.le ? VLC_CODEC_S24L : VLC_CODEC_S24B)
- : (par.le ? VLC_CODEC_U24L : VLC_CODEC_U24B);
- break;
- case 32:
- f.i_format = par.sig ? (par.le ? VLC_CODEC_S32L : VLC_CODEC_S32B)
- : (par.le ? VLC_CODEC_U32L : VLC_CODEC_U32B);
- break;
- default:
- msg_Err (obj, "unsupported audio sample format (%u bits)",
- par.bits);
- goto error;
+ fourcc[0] = par.sig ? 's' : 'u';
+ if (par.bps == 1) {
+ fourcc[1] = '8';
+ fourcc[2] = ' ';
+ fourcc[3] = ' ';
+ } else {
+ fourcc[1] = '0' + (par.bps << 3) / 10;
+ fourcc[2] = '0' + (par.bps << 3) % 10;
+ fourcc[3] = par.le ? 'l' : 'b';
+ if (par.bits < (par.bps << 3) && !par.msb) {
+ msg_Err (obj, "unsupported LSB alignement (%u bits in %u bytes)",
+ par.bits, par.bps);
+ goto error;
+ }
}
- f.i_rate = par.rate;
-
/* Channel map */
- unsigned chans;
switch (par.pchan)
{
case 1:
chans = AOUT_CHAN_CENTER;
break;
case 2:
- chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+ chans = AOUT_CHANS_STEREO;
break;
case 4:
- chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
- | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
+ chans = AOUT_CHANS_4_0;
break;
case 6:
- chans = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
- | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
- | AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
+ chans = AOUT_CHANS_5_1;
+ break;
+ case 8:
+ chans = AOUT_CHANS_7_1;
break;
default:
msg_Err (aout, "unknown %u channels map", par.pchan);
goto error;
}
- f.i_original_channels = f.i_physical_channels = chans;
- aout_FormatPrepare (&f);
-
- aout->format = f;
- aout->sys = (void *)sio;
+ sys = malloc (sizeof(struct aout_sys_t));
+ if (sys == NULL) {
+ msg_Err (aout, "failed to allocate sndio structure");
+ goto error;
+ }
+ sys->hdl = hdl;
+ sys->bpf = par.bps * par.pchan;
+ sys->delay = 0;
+ aout->sys = sys;
+ aout->format.i_format =
+ VLC_FOURCC(fourcc[0], fourcc[1], fourcc[2], fourcc[3]);
+ msg_Warn(aout, "pchan = %u, rate = %u, bufsz = %u, round = %u\n",
+ par.pchan, par.rate, par.bufsz, par.round);
+ msg_Warn(aout, "orig_chans = 0x%x, phys_chans = 0x%x, chans = 0x%x\n",
+ aout->format.i_original_channels,
+ aout->format.i_physical_channels,
+ chans);
+ aout->format.i_original_channels = chans;
+ aout->format.i_physical_channels = chans;
+ aout->format.i_rate = par.rate;
aout->pf_play = Play;
aout->pf_pause = Pause;
- aout->pf_flush = NULL; /* sndio sucks! */
- aout_VolumeSoftInit (aout); /* TODO: sio_onvol() */
-
- sio_start (sio);
+ aout->pf_flush = Flush;
+ aout_VolumeHardInit (aout, VolumeSet);
+ VolumeSet(aout,
+ var_InheritInteger (aout, "volume") / (float)AOUT_VOLUME_DEFAULT,
+ var_InheritBool (aout, "mute"));
+ sio_onmove (hdl, onmove, aout);
+ sio_start (hdl);
return VLC_SUCCESS;
error:
- sio_close (sio);
+ sio_close (hdl);
return VLC_EGENERIC;
}
static void Close (vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
- struct sio_hdl *sio = (void *)aout->sys;
+ struct aout_sys_t *sys = (struct aout_sys_t *)aout->sys;
- sio_close (sio);
+ sio_close (sys->hdl);
+ free (sys);
}
static void Play (audio_output_t *aout, block_t *block)
{
- struct sio_hdl *sio = (void *)aout->sys;
- struct sio_par par;
+ struct aout_sys_t *sys = (struct aout_sys_t *)aout->sys;
- if (sio_getpar (sio, &par) == 0)
- {
- mtime_t delay = par.bufsz * CLOCK_FREQ / aout->format.i_rate;
-
- delay = block->i_pts - (mdate () - delay);
- aout_TimeReport (aout, block->i_pts - delay);
- }
+ aout_TimeReport (aout, block->i_pts -
+ sys->delay * CLOCK_FREQ / aout->format.i_rate);
+ sio_write (sys->hdl, block->p_buffer, block->i_nb_samples * sys->bpf);
+ sys->delay += block->i_nb_samples;
+ block_Release (block);
+}
- while (block->i_buffer > 0 && !sio_eof (sio))
- {
- size_t bytes = sio_write (sio, block->p_buffer, block->i_buffer);
+static void Pause (audio_output_t *aout, bool pause, mtime_t date)
+{
+ struct aout_sys_t *sys = (struct aout_sys_t *)aout->sys;
+ static char zeros[100];
+ unsigned int todo, n;
- block->p_buffer += bytes;
- block->i_buffer -= bytes;
- /* Note that i_nb_samples and i_pts are corrupted here. */
+ if (pause) {
+ sio_stop (sys->hdl);
+ sio_start (sys->hdl);
+ } else {
+ todo = sys->delay * sys->bpf;
+ while (todo > 0) {
+ n = todo;
+ if (n >= sizeof(zeros))
+ n = sizeof(zeros);
+ sio_write(sys->hdl, zeros, n);
+ todo -= n;
+ }
}
- block_Release (block);
+ (void)date;
}
-static void Pause (audio_output_t *aout, bool pause, mtime_t date)
+static void Flush (audio_output_t *aout, bool wait)
{
- struct sio_hdl *sio = (void *)aout->sys;
+ struct aout_sys_t *sys = (struct aout_sys_t *)aout->sys;
+
+ sys->delay = 0;
+ (void)wait;
+}
+
+static int VolumeSet(audio_output_t *aout, float vol, bool mute)
+{
+ struct aout_sys_t *sys = (struct aout_sys_t *)aout->sys;
+ int ctl;
- if (pause)
- sio_stop (sio);
- else
- sio_start (sio);
- (void) date;
+ if (mute)
+ ctl = 0;
+ else {
+ if (vol < 0)
+ vol = 0;
+ if (vol > 1)
+ vol = 1;
+ ctl = vol * SIO_MAXVOL;
+ }
+ sio_setvol (sys->hdl, ctl);
+ return VLC_SUCCESS;
}
--
1.7.6
--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
More information about the vlc-devel
mailing list