[vlc-devel] [patch] fix for sndio bits
Alexandre Ratchov
alex at caoua.org
Fri Mar 22 15:30:41 CET 2013
Hi,
The diff below is to fix compilation and functionning of the sndio
backend (for OpenBSD audio), trying to take into account Remi
remarks from this thread:
http://mailman.videolan.org/pipermail/vlc-devel/2012-June/088948.html
According to git log, the current vlc/sndio backend was developped
for roaraudio sndio "emulation"; it's different from the OpenBSD
audio api, addressed by this diff.
-- Alexandre
diff --git a/configure.ac b/configure.ac
index 5b3501d..5c579e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3440,7 +3440,7 @@ dnl
AC_ARG_ENABLE([sndio],
[AS_HELP_STRING([--disable-sndio],
[support the OpenBSD sndio (default auto)])],, [
- AS_IF([test "$SYS" = "opensd"], [
+ AS_IF([test "$SYS" = "openbsd"], [
enable_sndio="yes"
])
])
diff --git a/modules/audio_output/sndio.c b/modules/audio_output/sndio.c
index 7f121dc..f484dc3 100644
--- a/modules/audio_output/sndio.c
+++ b/modules/audio_output/sndio.c
@@ -32,7 +32,7 @@
#include <sndio.h>
static int Open (vlc_object_t *);
-static void Close (vlc_objec_t *);
+static void Close (vlc_object_t *);
vlc_module_begin ()
set_shortname ("sndio")
@@ -43,8 +43,9 @@ vlc_module_begin ()
set_callbacks (Open, Close)
vlc_module_end ()
-static int TimeGet (audio_output, mtime_t *);
+static int TimeGet (audio_output_t *, mtime_t *);
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);
static int MuteSet (audio_output_t *, bool);
@@ -54,87 +55,106 @@ static void PositionChanged (void *, int);
struct aout_sys_t
{
struct sio_hdl *hdl;
- unsigned long long read_offset;
- unsigned long long write_offset;
+ int started;
+ int delay;
unsigned rate;
+ unsigned bpf;
unsigned volume;
bool mute;
};
+struct fmt_to_par {
+ unsigned int format, sig, bits, le;
+} fmt_to_par[] = {
+ {VLC_CODEC_S8, 1, 8, 0},
+ {VLC_CODEC_U8, 0, 8, 0},
+ {VLC_CODEC_S16L, 1, 16, 1},
+ {VLC_CODEC_S16B, 1, 16, 0},
+ {VLC_CODEC_U16L, 0, 16, 1},
+ {VLC_CODEC_U16B, 0, 16, 0},
+ {VLC_CODEC_S24L, 1, 24, 1},
+ {VLC_CODEC_S24B, 1, 24, 0},
+ {VLC_CODEC_U24L, 0, 24, 1},
+ {VLC_CODEC_U24B, 0, 24, 0},
+ {VLC_CODEC_S32L, 1, 32, 1},
+ {VLC_CODEC_S32B, 1, 32, 0},
+ {VLC_CODEC_U32L, 0, 32, 1},
+ {VLC_CODEC_U32B, 0, 32, 0},
+ {0, 0, 0, 0}
+};
+
/** Initializes an sndio playback stream */
static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
{
aout_sys_t *sys = aout->sys;
+ struct fmt_to_par *fp;
sys->hdl = sio_open (NULL, SIO_PLAY, 0 /* blocking */);
if (sys->hdl == NULL)
{
- msg_Err (obj, "cannot create audio playback stream");
- free (sys);
+ msg_Err (aout, "cannot create audio playback stream");
return VLC_EGENERIC;
}
- aout->sys = sys;
struct sio_par par;
sio_initpar (&par);
- par.bits = 16;
- par.bps = par.bits >> 3;
- par.sig = 1;
- par.le = SIO_LE_NATIVE;
+ for (fp = fmt_to_par; ; fp++) {
+ if (fp->format == 0) {
+ par.bits = 16;
+ par.sig = 1;
+ break;
+ }
+ if (fp->format == fmt->i_format) {
+ par.sig = fp->sig;
+ par.bits = fp->bits;
+ par.le = fp->le;
+ break;
+ }
+ }
par.pchan = aout_FormatNbChannels (fmt);
par.rate = fmt->i_rate;
- par.xrun = SIO_SYNC;
+ par.round = par.rate / 50;
+ par.appbufsz = par.rate / 4;
if (!sio_setpar (sys->hdl, &par) || !sio_getpar (sys->hdl, &par))
{
- msg_Err (obj, "cannot negotiate audio playback parameters");
+ msg_Err (aout, "cannot negotiate audio playback parameters");
goto error;
}
- if (par.bps != par.bits >> 3)
+ if (par.bps != par.bits >> 3 && !par.msb)
{
- msg_Err (obj, "unsupported audio sample format (%u bits in %u bytes)",
+ msg_Err (aout, "unsupported audio sample format (%u bits in %u bytes)",
par.bits, par.bps);
goto error;
}
- if (par.sig != (par.bits != 8))
- {
- msg_Err (obj, "unsupported audio sample format (%ssigned)",
- par.sig ? "" : "un");
- goto error;
- }
-#ifdef WORDS_BIGENDIAN
- if (par.le)
- {
- msg_Err (obj, "unsupported audio sample format (little endian)");
- goto error;
- }
-#else
- if (!par.le)
- {
- msg_Err (obj, "unsupported audio sample format (big endian)");
- goto error;
- }
-#endif
- switch (par.bits)
+
+ switch (par.bps)
{
- case 8:
- fmt->i_format = VLC_CODEC_U8;
+ case 1:
+ fmt->i_format = par.sig ? VLC_CODEC_S8 : VLC_CODEC_U8;
break;
- case 16:
- fmt->i_format = VLC_CODEC_S16N;
+ case 2:
+ fmt->i_format = par.sig ? (par.le ? VLC_CODEC_S16L : VLC_CODEC_S16B)
+ : (par.le ? VLC_CODEC_U16L : VLC_CODEC_U16B);
break;
- case 32:
- fmt->i_format = VLC_CODEC_S32N;
+ case 3:
+ fmt->i_format = par.sig ? (par.le ? VLC_CODEC_S24L : VLC_CODEC_S24B)
+ : (par.le ? VLC_CODEC_U24L : VLC_CODEC_U24B);
+ break;
+ case 4:
+ fmt->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)",
+ msg_Err (aout, "unsupported audio sample format (%u bits)",
par.bits);
goto error;
}
fmt->i_rate = par.rate;
sys->rate = par.rate;
+ sys->bpf = par.bps * par.pchan;
/* Channel map */
unsigned chans;
@@ -163,10 +183,9 @@ static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
fmt->i_original_channels = fmt->i_physical_channels = chans;
aout_FormatPrepare (fmt);
- aout->sys = sys;
aout->time_get = TimeGet;
aout->play = Play;
- aout->pause = NULL;
+ aout->pause = Pause;
aout->flush = Flush;
if (sio_onvol(sys->hdl, VolumeChanged, aout))
{
@@ -179,8 +198,8 @@ static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
aout->mute_set = NULL;
}
- sys->read_offset = 0;
- sys->write_offset = 0;
+ sys->started = 0;
+ sys->delay = 0;
sio_onmove (sys->hdl, PositionChanged, aout);
sio_start (sys->hdl);
return VLC_SUCCESS;
@@ -190,9 +209,8 @@ error:
return VLC_EGENERIC;
}
-static void Close (vlc_object_t *obj)
+static void Stop (audio_output_t *aout)
{
- audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
sio_close (sys->hdl);
@@ -203,18 +221,19 @@ static void PositionChanged (void *arg, int delta)
audio_output_t *aout = arg;
aout_sys_t *sys = aout->sys;
- sys->read_offset += delta;
+ sys->delay -= delta;
+ sys->started = 1;
}
static int TimeGet (audio_output_t *aout, mtime_t *restrict delay)
{
aout_sys_t *sys = aout->sys;
- long long frames = sys->write_offset - sys->read_offset;
-
- if (frames == 0)
- return -1;
- *delay = frames * CLOCK_FREQ / sys->rate;
+ if (!sys->started)
+ *delay = 0;
+ else
+ *delay = (mtime_t)sys->delay * CLOCK_FREQ / sys->rate;
+ msg_Err (aout, "TimeGet *delay = %lld", (long long)*delay);
return 0;
}
@@ -222,35 +241,43 @@ static void Play (audio_output_t *aout, block_t *block)
{
aout_sys_t *sys = aout->sys;
- sys->write_offset += block->i_nb_samples;
-
- while (block->i_buffer > 0 && !sio_eof (sys->hdl))
- {
- size_t bytes = sio_write (sys->hdl, block->p_buffer, block->i_buffer);
-
- block->p_buffer += bytes;
- block->i_buffer -= bytes;
- /* Note that i_nb_samples and i_pts are not updated here. */
- }
+ sio_write (sys->hdl, block->p_buffer, block->i_nb_samples * sys->bpf);
+ sys->delay += block->i_nb_samples;
block_Release (block);
}
static void Flush (audio_output_t *aout, bool wait)
{
- if (wait)
- {
- long long frames = sys->write_offset - sys->read_offset;
+ aout_sys_t *sys = aout->sys;
- if (frames > 0)
- msleep (frames * CLOCK_FREQ / sys->rate);
- }
- else
- {
+ sio_stop (sys->hdl);
+ sio_start (sys->hdl);
+ sys->started = 0;
+ sys->delay = 0;
+ (void)wait;
+}
+
+static void Pause (audio_output_t *aout, bool pause, mtime_t date)
+{
+ aout_sys_t *sys = aout->sys;
+ char zero[1024];
+ int n, todo;
+
+ if (pause) {
sio_stop (sys->hdl);
- sys->read_offset = 0;
- sys->write_offset = 0;
sio_start (sys->hdl);
+ } else {
+ memset (zero, 0, sizeof (zero));
+ todo = sys->delay * sys->bpf;
+ while (todo > 0) {
+ n = sizeof (zero);
+ if (n > todo)
+ n = todo;
+ sio_write(sys->hdl, zero, n);
+ todo -= n;
+ }
}
+ (void) date;
}
static void VolumeChanged (void *arg, unsigned volume)
@@ -267,8 +294,13 @@ static void VolumeChanged (void *arg, unsigned volume)
static int VolumeSet (audio_output_t *aout, float fvol)
{
aout_sys_t *sys = aout->sys;
- unsigned volume = lroundf (fvol * SIO_MAXVOL);
+ unsigned volume;
+ if (fvol < 0)
+ fvol = 0;
+ if (fvol > 1)
+ fvol = 1;
+ volume = lroundf (fvol * SIO_MAXVOL);
if (!sys->mute && !sio_setvol (sys->hdl, volume))
return -1;
sys->volume = volume;
@@ -300,7 +332,7 @@ static int Open (vlc_object_t *obj)
return VLC_SUCCESS;
}
-static int Close (vlc_object_t *obj)
+static void Close (vlc_object_t *obj)
{
audio_output_t *aout = (audio_output_t *)obj;
aout_sys_t *sys = aout->sys;
More information about the vlc-devel
mailing list