X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faudio_output%2Fsndio.c;h=a60c309c02c4834215ef05bc978753777f5a269f;hb=1ab9abf37e549f6dd500e15dd3bf0c16dc29bdde;hp=aea6ea67657e766406c6ee269d75f20abc8457ba;hpb=a944af6d0b953aa34839226c1799706026488142;p=vlc diff --git a/modules/audio_output/sndio.c b/modules/audio_output/sndio.c index aea6ea6765..a60c309c02 100644 --- a/modules/audio_output/sndio.c +++ b/modules/audio_output/sndio.c @@ -32,7 +32,7 @@ #include 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,7 +43,7 @@ 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 Flush (audio_output_t *, bool); static int VolumeSet (audio_output_t *, float); @@ -54,8 +54,8 @@ 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 volume; bool mute; @@ -69,75 +69,77 @@ static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt) 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; + switch (fmt->i_format) { + case VLC_CODEC_S8: + par.bits = 8; + par.sig = 0; + break; + case VLC_CODEC_S16N: + par.bits = 16; + par.sig = 1; + par.le = SIO_LE_NATIVE; + break; + case VLC_CODEC_S32N: + case VLC_CODEC_FL32: + case VLC_CODEC_FL64: + par.bits = 32; + par.sig = 1; + par.le = SIO_LE_NATIVE; + break; + default: + /* use a common audio format */ + par.bits = 16; + par.sig = 1; + par.le = SIO_LE_NATIVE; + } 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)", + msg_Err (aout, "unsupported audio sample format (%ssigned)", par.sig ? "" : "un"); goto error; } -#ifdef WORDS_BIGENDIAN - if (par.le) + if (par.bps > 1 && par.le != SIO_LE_NATIVE) { - msg_Err (obj, "unsupported audio sample format (little endian)"); + msg_Err (aout, "unsupported audio sample format (%s endian)", + par.le ? "little" : "big"); goto error; } -#else - if (!par.le) - { - msg_Err (obj, "unsupported audio sample format (big endian)"); - goto error; - } -#endif switch (par.bits) { case 8: fmt->i_format = VLC_CODEC_U8; break; case 16: - fmt->i_format = par.sig - ? (par.le ? VLC_CODEC_S16L : VLC_CODEC_S16B) - : (par.le ? VLC_CODEC_U16L : VLC_CODEC_U16B); - break; - case 24: - fmt->i_format = par.sig - ? (par.le ? VLC_CODEC_S24L : VLC_CODEC_S24B) - : (par.le ? VLC_CODEC_U24L : VLC_CODEC_U24B); + fmt->i_format = VLC_CODEC_S16N; break; case 32: - fmt->i_format = par.sig - ? (par.le ? VLC_CODEC_S32L : VLC_CODEC_S32B) - : (par.le ? VLC_CODEC_U32L : VLC_CODEC_U32B); + fmt->i_format = VLC_CODEC_S32N; break; default: - msg_Err (obj, "unsupported audio sample format (%u bits)", + msg_Err (aout, "unsupported audio sample format (%u bits)", par.bits); goto error; } @@ -172,7 +174,6 @@ 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; @@ -188,8 +189,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; @@ -199,9 +200,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); @@ -212,18 +212,17 @@ 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) + return -1; + *delay = (mtime_t)sys->delay * CLOCK_FREQ / sys->rate; return 0; } @@ -231,35 +230,20 @@ 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_buffer); + 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); - sys->read_offset = 0; - sys->write_offset = 0; - sio_start (sys->hdl); - } + sio_stop (sys->hdl); + sys->started = 0; + sys->delay = 0; + sio_start (sys->hdl); + (void)wait; } static void VolumeChanged (void *arg, unsigned volume) @@ -276,8 +260,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; @@ -309,7 +298,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;