aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-04-08 10:01:04 -0700
committerChris Robinson <[email protected]>2017-04-08 10:01:04 -0700
commit1f64f9d016790797ecd81e00f0392b34abdddcb6 (patch)
treebcb335ba4056d24d3ee1189601f98bb07ef883c4
parentf1a5b6b6681b1c9950266f2e6bec22dcba6cba97 (diff)
Try to write the full configured buffer length with PulseAudio
This basically ignores tlength even if it's smaller than what was requested. It keeps up-to-date with minreq changes too now, in case that happens.
-rw-r--r--Alc/backends/pulseaudio.c52
1 files changed, 37 insertions, 15 deletions
diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c
index 79ca38e5..0eda2abd 100644
--- a/Alc/backends/pulseaudio.c
+++ b/Alc/backends/pulseaudio.c
@@ -626,6 +626,11 @@ static void ALCpulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata)
self->attr = *pa_stream_get_buffer_attr(stream);
TRACE("minreq=%d, tlength=%d, prebuf=%d\n", self->attr.minreq, self->attr.tlength, self->attr.prebuf);
+ /* FIXME: Update the device's UpdateSize (and/or NumUpdates) using the new
+ * buffer attributes? Changing UpdateSize will change the ALC_REFRESH
+ * property, which probably shouldn't change between device resets. But
+ * leaving it alone means ALC_REFRESH will be off.
+ */
}
static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pdata)
@@ -797,7 +802,6 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
ALCpulsePlayback *self = ptr;
ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
ALuint buffer_size;
- ALint update_size;
size_t frame_size;
ssize_t len;
@@ -806,18 +810,30 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
pa_threaded_mainloop_lock(self->loop);
frame_size = pa_frame_size(&self->spec);
- update_size = device->UpdateSize * frame_size;
-
- /* Sanitize buffer metrics, in case we actually have less than what we
- * asked for. */
- buffer_size = minu(update_size*device->NumUpdates, self->attr.tlength);
- update_size = minu(update_size, buffer_size/2);
- do {
- len = pa_stream_writable_size(self->stream) - self->attr.tlength +
- buffer_size;
- if(len < update_size)
+ buffer_size = device->UpdateSize * device->NumUpdates * frame_size;
+
+ while(!self->killNow && device->Connected)
+ {
+ len = pa_stream_writable_size(self->stream);
+ if(len < 0)
{
- if(pa_stream_is_corked(self->stream) == 1)
+ ERR("Failed to get writable size: %ld", (long)len);
+ aluHandleDisconnect(device);
+ break;
+ }
+
+ /* Make sure we're going to write at least 2 'periods' (minreqs), in
+ * case the server increased it since starting playback.
+ */
+ buffer_size = maxu(buffer_size, self->attr.minreq*2);
+
+ /* NOTE: This assumes pa_stream_writable_size returns between 0 and
+ * tlength, else there will be more latency than intended.
+ */
+ len = mini(len - (ssize_t)self->attr.tlength, 0) + buffer_size;
+ if(len < self->attr.minreq)
+ {
+ if(pa_stream_is_corked(self->stream))
{
pa_operation *o;
o = pa_stream_cork(self->stream, 0, NULL, NULL);
@@ -826,11 +842,12 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
pa_threaded_mainloop_wait(self->loop);
continue;
}
- len -= len%update_size;
+ len -= len%self->attr.minreq;
while(len > 0)
{
size_t newlen = len;
+ int ret;
void *buf;
pa_free_cb_t free_func = NULL;
@@ -842,10 +859,15 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
aluMixData(device, buf, newlen/frame_size);
- pa_stream_write(self->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE);
+ ret = pa_stream_write(self->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE);
+ if(ret != PA_OK)
+ {
+ ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret));
+ break;
+ }
len -= newlen;
}
- } while(!self->killNow && device->Connected);
+ }
pa_threaded_mainloop_unlock(self->loop);
return 0;