[vlc-devel] [patch] fix for sndio bits
Rémi Denis-Courmont
remi at remlab.net
Sat Mar 23 12:56:03 CET 2013
Hello,
Le vendredi 22 mars 2013 16:30:41, Alexandre Ratchov a écrit :
> 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
> @@ -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}
> +};
This is probably overkill. In VLC 2.1.x, only U8, S16N, S32N, FL32 and FL64
can occur in the VLC audio output, except for pass-through.
> +
> /** 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;
> 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);
Does this not break draining?
> - }
> - 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;
> + }
Does this really work when resuming from a long pause? This looks a bit
simplistic.
> }
> + (void) date;
> }
>
> static void VolumeChanged (void *arg, unsigned volume)
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list