[PATCH] alsa-plugins: Pulse: only underrun if no more data has been written

David Henningsson david.henningsson at canonical.com
Tue Aug 23 13:42:33 CEST 2011


If more data has already been written after the underrun, the underrun
will automatically end and therefore we should not report it or
restart the stream.

Signed-off-by: David Henningsson <david.henningsson at canonical.com>
---
 pulse/pcm_pulse.c |   36 ++++++++++++++++++++++++++++++++++--
 1 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c
index d6c6792..92f4777 100644
--- a/pulse/pcm_pulse.c
+++ b/pulse/pcm_pulse.c
@@ -40,8 +40,10 @@ typedef struct snd_pcm_pulse {
 	size_t ptr;
 	int underrun;
 	int handle_underrun;
+	int handle_underrun_detect;
 
 	size_t offset;
+	int64_t written;
 
 	pa_stream *stream;
 
@@ -460,6 +462,7 @@ static snd_pcm_sframes_t pulse_write(snd_pcm_ioplug_t * io,
 
 	/* Make sure the buffer pointer is in sync */
 	pcm->last_size -= writebytes;
+	pcm->written += writebytes;
 	ret = update_ptr(pcm);
 	if (ret < 0)
 		goto finish;
@@ -585,6 +588,23 @@ static void stream_request_cb(pa_stream * p, size_t length, void *userdata)
 	update_active(pcm);
 }
 
+#if defined(PA_CHECK_VERSION) && PA_CHECK_VERSION(0,99,0)
+
+#define has_underrun_detect 1
+
+static inline int do_underrun_detect(snd_pcm_pulse_t *pcm, pa_stream *p)
+{
+	return pcm->handle_underrun_detect &&
+		pcm->written <= pa_stream_get_underflow_index(p);
+}
+
+#else
+
+#define has_underrun_detect 0
+#define do_underrun_detect(pcm, p) 0
+
+#endif
+
 static void stream_underrun_cb(pa_stream * p, void *userdata)
 {
 	snd_pcm_pulse_t *pcm = userdata;
@@ -594,7 +614,8 @@ static void stream_underrun_cb(pa_stream * p, void *userdata)
 	if (!pcm->p)
 		return;
 
-	pcm->underrun = 1;
+	if (pcm->handle_underrun || do_underrun_detect(pcm, p))
+		pcm->underrun = 1;
 }
 
 static void stream_latency_cb(pa_stream *p, void *userdata) {
@@ -697,7 +718,7 @@ static int pulse_prepare(snd_pcm_ioplug_t * io)
 	if (io->stream == SND_PCM_STREAM_PLAYBACK) {
 		pa_stream_set_write_callback(pcm->stream,
 					     stream_request_cb, pcm);
-		if (pcm->handle_underrun)
+		if (pcm->handle_underrun_detect || pcm->handle_underrun)
 			pa_stream_set_underflow_callback(pcm->stream,
 							 stream_underrun_cb, pcm);
 		r = pa_stream_connect_playback(pcm->stream, pcm->device,
@@ -739,6 +760,7 @@ static int pulse_prepare(snd_pcm_ioplug_t * io)
 
 	pcm->offset = 0;
 	pcm->underrun = 0;
+	pcm->written = 0;
 
 	/* Reset fake ringbuffer */
 	pcm->last_size = 0;
@@ -984,6 +1006,7 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse)
 	const char *device = NULL;
 	const char *fallback_name = NULL;
 	int handle_underrun = 0;
+	int handle_underrun_detect = 1;
 	int err;
 	snd_pcm_pulse_t *pcm;
 
@@ -1017,6 +1040,14 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse)
 			handle_underrun = err;
 			continue;
 		}
+		if (strcmp(id, "handle_underrun_detect") == 0) {
+			if ((err = snd_config_get_bool(n)) < 0) {
+				SNDERR("Invalid value for %s", id);
+				return -EINVAL;
+			}
+			handle_underrun_detect = err;
+			continue;
+		}
 		if (strcmp(id, "fallback") == 0) {
 			if (snd_config_get_string(n, &fallback_name) < 0) {
 				SNDERR("Invalid value for %s", id);
@@ -1051,6 +1082,7 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse)
 	}
 
 	pcm->handle_underrun = handle_underrun;
+	pcm->handle_underrun_detect = has_underrun_detect && handle_underrun_detect;
 
 	err = pulse_connect(pcm->p, server, fallback_name != NULL);
 	if (err < 0)
-- 
1.7.5.4


--------------040808080001070501040605--


More information about the Alsa-devel mailing list