On Sun, May 20, 2012 at 11:59:48PM +0200, Alexandre Ratchov wrote: > This diff is supposed to make video smoother with the sndio > backend. It also adds support for 24-bit encodings, makes use of > the sndiod volume knob, removes the need for portaudio and makes > sndio the default backend on OpenBSD. > > I'm very interested in any regressions, and stuff that used to > work, possibly with other backends, but that doesn't work with this > one. >
Here's the updated diff, compared to previous one, it fixes pause/unpause. OK? -- Alexandre Index: Makefile =================================================================== RCS file: /cvs/ports/x11/vlc/Makefile,v retrieving revision 1.150 diff -u -p -r1.150 Makefile --- Makefile 2 Jun 2012 12:06:37 -0000 1.150 +++ Makefile 9 Jun 2012 10:39:17 -0000 @@ -8,7 +8,7 @@ COMMENT-jack= JACK audio output module f V= 2.0.1 DISTNAME= vlc-${V} PKGNAME-main= ${DISTNAME} -REVISION-main= 2 +REVISION-main= 3 PKGNAME-jack= vlc-jack-${V} REVISION-jack= 0 CATEGORIES= x11 Index: files/sndio.c =================================================================== RCS file: /cvs/ports/x11/vlc/files/sndio.c,v retrieving revision 1.1 diff -u -p -r1.1 sndio.c --- files/sndio.c 23 Apr 2012 13:47:08 -0000 1.1 +++ files/sndio.c 9 Jun 2012 10:39:17 -0000 @@ -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,159 +37,224 @@ 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", 0) + set_capability ("audio output", 120) set_callbacks (Open, Close ) 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; + 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); +} - delay = block->i_pts - (mdate () - delay); - aout_TimeReport (aout, block->i_pts - delay); +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; + + 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; + } } + (void)date; +} - while (block->i_buffer > 0 && !sio_eof (sio)) - { - size_t bytes = sio_write (sio, block->p_buffer, block->i_buffer); - - block->p_buffer += bytes; - block->i_buffer -= bytes; - /* Note that i_nb_samples and i_pts are corrupted here. */ - } - block_Release (block); +static void Flush (audio_output_t *aout, bool wait) +{ + struct aout_sys_t *sys = (struct aout_sys_t *)aout->sys; + + sys->delay = 0; + (void)wait; } -static void Pause (audio_output_t *aout, bool pause, mtime_t date) +static int VolumeSet(audio_output_t *aout, float vol, bool mute) { - struct sio_hdl *sio = (void *)aout->sys; + 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; }