[PATCH] pulse: Fix invalid buffer pointer return value

David Henningsson diwic at ubuntu.com
Sat Jan 9 09:09:14 CET 2010


This patch improves recovering from underruns, and prevents hangs inside
snd_pcm_write* and snd_pcm_read* due to snd_pcm_avail* returning too
low values. It especially helps low latency situations.

Signed-off-by: David Henningsson <diwic at ubuntu.com>
---
 pulse/pcm_pulse.c |   15 ++++++++++++++-
 1 files changed, 14 insertions(+), 1 deletions(-)

Index: alsa-plugins-1.0.22/pulse/pcm_pulse.c
===================================================================
--- alsa-plugins-1.0.22.orig/pulse/pcm_pulse.c	2010-02-28 17:12:02.000000000 -0500
+++ alsa-plugins-1.0.22/pulse/pcm_pulse.c	2010-02-28 17:12:25.000000000 -0500
@@ -90,6 +90,10 @@
 	if (pcm->io.stream == SND_PCM_STREAM_CAPTURE)
 		size -= pcm->offset;
 
+	/* Prevent accidental overrun of the fake ringbuffer */
+	if (size >= pcm->buffer_attr.tlength)
+		size = pcm->buffer_attr.tlength-1;
+
 	if (size > pcm->last_size) {
 		pcm->ptr += size - pcm->last_size;
 		pcm->ptr %= pcm->buffer_attr.tlength;
@@ -424,6 +428,7 @@
 	snd_pcm_pulse_t *pcm = io->private_data;
 	const char *buf;
 	snd_pcm_sframes_t ret = 0;
+	size_t writebytes;
 
 	assert(pcm);
 
@@ -445,13 +450,15 @@
 	    (char *) areas->addr + (areas->first +
 				    areas->step * offset) / 8;
 
-	ret = pa_stream_write(pcm->stream, buf, size * pcm->frame_size, NULL, 0, 0);
+	writebytes = size * pcm->frame_size;
+	ret = pa_stream_write(pcm->stream, buf, writebytes, NULL, 0, 0);
 	if (ret < 0) {
 		ret = -EIO;
 		goto finish;
 	}
 
 	/* Make sure the buffer pointer is in sync */
+	pcm->last_size -= writebytes;
 	ret = update_ptr(pcm);
 	if (ret < 0)
 		goto finish;
@@ -528,6 +535,7 @@
 
 		dst_buf = (char *) dst_buf + frag_length;
 		remain_size -= frag_length;
+		pcm->last_size -= frag_length;
 	}
 
 	/* Make sure the buffer pointer is in sync */
@@ -730,6 +738,11 @@
 	pcm->offset = 0;
 	/*pcm->underrun = 0;*/
 
+	/* Reset fake ringbuffer */
+	pcm->last_size = 0;
+	pcm->ptr = 0;
+	update_ptr(pcm);
+
       finish:
 	pa_threaded_mainloop_unlock(pcm->p->mainloop);
 

--------------040006090607070407080605--


More information about the Alsa-devel mailing list