[pulseaudio-commits] src/modules

Tanu Kaskinen tanuk at kemper.freedesktop.org
Sun Nov 5 13:24:11 UTC 2017


 src/modules/alsa/alsa-sink.c |   39 ++++++++++++++++++++-------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

New commits:
commit 83e12c43b110fc45056b625ea005b96d231dd415
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Tue Oct 31 15:29:25 2017 +0200

    alsa-sink: update max_rewind when updating the latency
    
    Previously max_rewind was always set to the full hw buffer size, but
    the actual maximum rewind amount is limited to the part of the hw buffer
    that is in use.
    
    The rewind request that was done when lowering the sink latency had to
    be moved to happen before updating max_rewind.
    
    The practical benefit of this change: When using a filter source on a
    monitor source, the filter source latency is increased by max_rewind.
    Without this change the max_rewind of an alsa sink is often
    unnecessarily high, which leads to unnecessarily high latency with
    filter sources.
    
    Monitor sources themselves don't suffer from the latency issue, because
    they use the current sink latency instead of max_rewind for the extra
    buffer that they keep to deal with rewinds.

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 96fd02ae..7936cfac 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -969,13 +969,15 @@ static int suspend(struct userdata *u) {
 }
 
 /* Called from IO context */
-static int update_sw_params(struct userdata *u) {
+static int update_sw_params(struct userdata *u, bool may_need_rewind) {
+    size_t old_unused;
     snd_pcm_uframes_t avail_min;
     int err;
 
     pa_assert(u);
 
     /* Use the full buffer if no one asked us for anything specific */
+    old_unused = u->hwbuf_unused;
     u->hwbuf_unused = 0;
 
     if (u->use_tsched) {
@@ -1019,9 +1021,21 @@ static int update_sw_params(struct userdata *u) {
         return err;
     }
 
+    /* If we're lowering the latency, we need to do a rewind, because otherwise
+     * we might end up in a situation where the hw buffer contains more data
+     * than the new configured latency. The rewind has to be requested before
+     * updating max_rewind, because the rewind amount is limited to max_rewind.
+     *
+     * If may_need_rewind is false, it means that we're just starting playback,
+     * and rewinding is never needed in that situation. */
+    if (may_need_rewind && u->hwbuf_unused > old_unused) {
+        pa_log_debug("Requesting rewind due to latency change.");
+        pa_sink_request_rewind(u->sink, (size_t) -1);
+    }
+
     pa_sink_set_max_request_within_thread(u->sink, u->hwbuf_size - u->hwbuf_unused);
-     if (pa_alsa_pcm_is_hw(u->pcm_handle))
-         pa_sink_set_max_rewind_within_thread(u->sink, u->hwbuf_size);
+    if (pa_alsa_pcm_is_hw(u->pcm_handle))
+        pa_sink_set_max_rewind_within_thread(u->sink, u->hwbuf_size - u->hwbuf_unused);
     else {
         pa_log_info("Disabling rewind_within_thread for device %s", u->device_name);
         pa_sink_set_max_rewind_within_thread(u->sink, 0);
@@ -1122,7 +1136,7 @@ static int unsuspend(struct userdata *u) {
         goto fail;
     }
 
-    if (update_sw_params(u) < 0)
+    if (update_sw_params(u, false) < 0)
         goto fail;
 
     if (build_pollfd(u) < 0)
@@ -1518,7 +1532,6 @@ static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
 
 static void sink_update_requested_latency_cb(pa_sink *s) {
     struct userdata *u = s->userdata;
-    size_t before;
     pa_assert(u);
     pa_assert(u->use_tsched); /* only when timer scheduling is used
                                * we can dynamically adjust the
@@ -1527,19 +1540,7 @@ static void sink_update_requested_latency_cb(pa_sink *s) {
     if (!u->pcm_handle)
         return;
 
-    before = u->hwbuf_unused;
-    update_sw_params(u);
-
-    /* Let's check whether we now use only a smaller part of the
-    buffer then before. If so, we need to make sure that subsequent
-    rewinds are relative to the new maximum fill level and not to the
-    current fill level. Thus, let's do a full rewind once, to clear
-    things up. */
-
-    if (u->hwbuf_unused > before) {
-        pa_log_debug("Requesting rewind due to latency change.");
-        pa_sink_request_rewind(s, (size_t) -1);
-    }
+    update_sw_params(u, true);
 }
 
 static pa_idxset* sink_get_formats(pa_sink *s) {
@@ -2396,7 +2397,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
 
     reserve_update(u);
 
-    if (update_sw_params(u) < 0)
+    if (update_sw_params(u, false) < 0)
         goto fail;
 
     if (u->ucm_context) {



More information about the pulseaudio-commits mailing list