Date: Friday, November 19, 2010 @ 11:25:41
  Author: heftig
Revision: 99957

Oops, forgot patches

Added:
  alsa-plugins/trunk/Add_handle_underrun_option.patch
  alsa-plugins/trunk/Fix_invalid_buffer_pointer_return_value.patch

-----------------------------------------------+
 Add_handle_underrun_option.patch              |   86 ++++++++++++++++++++++++
 Fix_invalid_buffer_pointer_return_value.patch |   75 ++++++++++++++++++++
 2 files changed, 161 insertions(+)

Added: Add_handle_underrun_option.patch
===================================================================
--- Add_handle_underrun_option.patch                            (rev 0)
+++ Add_handle_underrun_option.patch    2010-11-19 16:25:41 UTC (rev 99957)
@@ -0,0 +1,86 @@
+From: Takashi Iwai <ti...@suse.de>
+Date: Fri, 9 Jul 2010 12:05:03 +0000 (+0200)
+Subject: pulse: Add handle_underrun option
+X-Git-Url: 
http://git.alsa-project.org/?p=alsa-plugins.git;a=commitdiff_plain;h=c20d516e229620129ee20175d8fee8511cc3a4bd
+
+pulse: Add handle_underrun option
+
+Added a config option "handle_underrun" to specify whether pulse plugin
+handles the underrun reported from PA.  The default value is now set to
+false, i.e. it will ignore underruns in PA (for good reasons below).
+You can take back to the old behavior by setting handle_underrun true.
+
+The original idea was brought by David Henningsson <di...@ubuntu.com>,
+while this patch is simplified and makes the behavior configurable.
+
+The reasons for avoiding underruns (cited from David's original patch):
+
+ Reporting underruns to ALSA seems to do more bad than good, for these reasons:
+ * If pulseaudio gets an underrun, the normal way to end that underrun is to
+   feed it with more buffers. This is different from the ALSA way of dealing
+   with underruns, which requires hardware buffer pointers to be reset.
+ * In addition, underrun signals are delivered asynchronously from pulseaudio.
+   This means that there might be more buffers on the way to pulseaudio when
+   the underrun is reported, making the underrun obsolete. Unfortunately,
+   there is currently no known way to determine whether this is the case or
+   not.
+
+Signed-off-by: Takashi Iwai <ti...@suse.de>
+---
+
+diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c
+index b322898..2df0a80 100644
+--- a/pulse/pcm_pulse.c
++++ b/pulse/pcm_pulse.c
+@@ -39,6 +39,7 @@ typedef struct snd_pcm_pulse {
+       size_t last_size;
+       size_t ptr;
+       int underrun;
++      int handle_underrun;
+ 
+       size_t offset;
+ 
+@@ -696,8 +697,9 @@ 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);
+-              pa_stream_set_underflow_callback(pcm->stream,
+-                                               stream_underrun_cb, pcm);
++              if (pcm->handle_underrun)
++                      pa_stream_set_underflow_callback(pcm->stream,
++                                                       stream_underrun_cb, 
pcm);
+               r = pa_stream_connect_playback(pcm->stream, pcm->device,
+                                              &pcm->buffer_attr,
+                                              PA_STREAM_AUTO_TIMING_UPDATE |
+@@ -980,6 +982,7 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse)
+       snd_config_iterator_t i, next;
+       const char *server = NULL;
+       const char *device = NULL;
++      int handle_underrun = 0;
+       int err;
+       snd_pcm_pulse_t *pcm;
+ 
+@@ -1005,6 +1008,14 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse)
+                       }
+                       continue;
+               }
++              if (strcmp(id, "handle_underrun") == 0) {
++                      if ((err = snd_config_get_bool(n)) < 0) {
++                              SNDERR("Invalid value for %s", id);
++                              return -EINVAL;
++                      }
++                      handle_underrun = err;
++                      continue;
++              }
+               SNDERR("Unknown field %s", id);
+               return -EINVAL;
+       }
+@@ -1028,6 +1039,8 @@ SND_PCM_PLUGIN_DEFINE_FUNC(pulse)
+               goto error;
+       }
+ 
++      pcm->handle_underrun = handle_underrun;
++
+       err = pulse_connect(pcm->p, server);
+       if (err < 0)
+               goto error;

Added: Fix_invalid_buffer_pointer_return_value.patch
===================================================================
--- Fix_invalid_buffer_pointer_return_value.patch                               
(rev 0)
+++ Fix_invalid_buffer_pointer_return_value.patch       2010-11-19 16:25:41 UTC 
(rev 99957)
@@ -0,0 +1,75 @@
+From: David Henningsson <di...@ubuntu.com>
+Date: Sat, 9 Jan 2010 08:09:14 +0000 (+0100)
+Subject: pulse: Fix invalid buffer pointer return value
+X-Git-Url: 
http://git.alsa-project.org/?p=alsa-plugins.git;a=commitdiff_plain;h=1675414eca06dcfc20899adf104ace05acfe26a0
+
+pulse: Fix invalid buffer pointer return value
+
+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 <di...@ubuntu.com>
+Signed-off-by: Takashi Iwai <ti...@suse.de>
+---
+
+diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c
+index 02a837e..b322898 100644
+--- a/pulse/pcm_pulse.c
++++ b/pulse/pcm_pulse.c
+@@ -90,6 +90,10 @@ static int update_ptr(snd_pcm_pulse_t *pcm)
+       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 @@ static snd_pcm_sframes_t pulse_write(snd_pcm_ioplug_t * io,
+       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 @@ static snd_pcm_sframes_t pulse_write(snd_pcm_ioplug_t * 
io,
+           (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 @@ static snd_pcm_sframes_t pulse_read(snd_pcm_ioplug_t * io,
+ 
+               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 @@ static int pulse_prepare(snd_pcm_ioplug_t * io)
+       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);
+ 

Reply via email to