[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.19-553-g26dfacf

Colin Guthrie gitmailer-noreply at 0pointer.de
Thu Sep 9 09:03:44 PDT 2010


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  b0042cec71ffb09d3720fdcc4223de8153fed67a (commit)

- Log -----------------------------------------------------------------
26dfacf echo-cancel: pause timer when echo canceling is off
7b87378 echo-cancel: improve accuracy
c47d689 alsa: make defines for smoother configuration
771fb0b echo-cancel: rework alignment code
f29acfd alsa: work around slightly broken _delay implementations
-----------------------------------------------------------------------

Summary of changes:
 src/modules/alsa/alsa-sink.c                 |    9 +-
 src/modules/alsa/alsa-source.c               |    9 +-
 src/modules/alsa/alsa-util.c                 |   46 ++++++-
 src/modules/alsa/alsa-util.h                 |    2 +-
 src/modules/echo-cancel/module-echo-cancel.c |  182 +++++++++++++++-----------
 5 files changed, 162 insertions(+), 86 deletions(-)

-----------------------------------------------------------------------

commit f29acfd0e0413a9bd126782763ee2dcf10357546
Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date:   Wed Sep 8 13:26:39 2010 +0200

    alsa: work around slightly broken _delay implementations
    
    Use snd_pcm_avail_delay() in pa_alsa_safe_delay() so that we can check the delay
    value against the avail value and patch it up when it looks invalid. Only do
    this for capture.

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index f824944..14f08a5 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -802,7 +802,7 @@ static void update_smoother(struct userdata *u) {
 
     /* Let's update the time smoother */
 
-    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, &delay, u->hwbuf_size, &u->sink->sample_spec)) < 0)) {
+    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, &delay, u->hwbuf_size, &u->sink->sample_spec, FALSE)) < 0)) {
         pa_log_warn("Failed to query DSP status data: %s", pa_alsa_strerror(err));
         return;
     }
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index dbaa305..fd6c189 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -760,7 +760,7 @@ static void update_smoother(struct userdata *u) {
 
     /* Let's update the time smoother */
 
-    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, &delay, u->hwbuf_size, &u->source->sample_spec)) < 0)) {
+    if (PA_UNLIKELY((err = pa_alsa_safe_delay(u->pcm_handle, &delay, u->hwbuf_size, &u->source->sample_spec, TRUE)) < 0)) {
         pa_log_warn("Failed to get delay: %s", pa_alsa_strerror(err));
         return;
     }
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 1cbb3f3..2d0d356 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1125,10 +1125,11 @@ snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa
     return n;
 }
 
-int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss) {
+int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss, pa_bool_t capture) {
     ssize_t k;
     size_t abs_k;
     int r;
+    snd_pcm_sframes_t avail = 0;
 
     pa_assert(pcm);
     pa_assert(delay);
@@ -1136,9 +1137,10 @@ int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_si
     pa_assert(ss);
 
     /* Some ALSA driver expose weird bugs, let's inform the user about
-     * what is going on */
+     * what is going on. We're going to get both the avail and delay values so
+     * that we can compare and check them for capture */
 
-    if ((r = snd_pcm_delay(pcm, delay)) < 0)
+    if ((r = snd_pcm_avail_delay(pcm, &avail, delay)) < 0)
         return r;
 
     k = (ssize_t) *delay * (ssize_t) pa_frame_size(ss);
@@ -1167,6 +1169,44 @@ int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_si
             *delay = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
     }
 
+    if (capture) {
+        abs_k = (size_t) avail * pa_frame_size(ss);
+
+        if (abs_k >= hwbuf_size * 5 ||
+            abs_k >= pa_bytes_per_second(ss)*10) {
+
+            PA_ONCE_BEGIN {
+                char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
+                pa_log(_("snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
+                         "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
+                       (unsigned long) k,
+                       (unsigned long) (pa_bytes_to_usec(k, ss) / PA_USEC_PER_MSEC),
+                       pa_strnull(dn));
+                pa_xfree(dn);
+                pa_alsa_dump(PA_LOG_ERROR, pcm);
+            } PA_ONCE_END;
+
+            /* Mhmm, let's try not to fail completely */
+            avail = (snd_pcm_sframes_t) (hwbuf_size / pa_frame_size(ss));
+        }
+
+        if (*delay < avail) {
+            PA_ONCE_BEGIN {
+                char *dn = pa_alsa_get_driver_name_by_pcm(pcm);
+                pa_log(_("snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
+                         "Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."),
+                       (unsigned long) *delay,
+                       (unsigned long) avail,
+                       pa_strnull(dn));
+                pa_xfree(dn);
+                pa_alsa_dump(PA_LOG_ERROR, pcm);
+            } PA_ONCE_END;
+
+            /* try to fixup */
+            *delay = avail;
+        }
+    }
+
     return 0;
 }
 
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index 1d1256b..9e29fd4 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -129,7 +129,7 @@ int pa_alsa_recover_from_poll(snd_pcm_t *pcm, int revents);
 pa_rtpoll_item* pa_alsa_build_pollfd(snd_pcm_t *pcm, pa_rtpoll *rtpoll);
 
 snd_pcm_sframes_t pa_alsa_safe_avail(snd_pcm_t *pcm, size_t hwbuf_size, const pa_sample_spec *ss);
-int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss);
+int pa_alsa_safe_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delay, size_t hwbuf_size, const pa_sample_spec *ss, pa_bool_t capture);
 int pa_alsa_safe_mmap_begin(snd_pcm_t *pcm, const snd_pcm_channel_area_t **areas, snd_pcm_uframes_t *offset, snd_pcm_uframes_t *frames, size_t hwbuf_size, const pa_sample_spec *ss);
 
 char *pa_alsa_get_driver_name(int card);

commit 771fb0b59bc90b19a2c69e8cbe51a4957917d588
Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date:   Wed Sep 8 18:49:48 2010 +0200

    echo-cancel: rework alignment code
    
    Rework the code to align capture and playback samples so that we can keep more
    accurate timings.

diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c
index 06583f4..4df77c3 100644
--- a/src/modules/echo-cancel/module-echo-cancel.c
+++ b/src/modules/echo-cancel/module-echo-cancel.c
@@ -173,6 +173,7 @@ struct userdata {
     pa_source_output *source_output;
     pa_memblockq *source_memblockq; /* echo canceler needs fixed sized chunks */
     pa_atomic_t source_active;
+    size_t source_skip;
 
     pa_sink *sink;
     pa_bool_t sink_auto_desc;
@@ -181,6 +182,7 @@ struct userdata {
     int64_t send_counter;          /* updated in sink IO thread */
     int64_t recv_counter;
     pa_atomic_t sink_active;
+    size_t sink_skip;
 
     pa_atomic_t request_resync;
 
@@ -594,8 +596,8 @@ static void apply_diff_time(struct userdata *u, int64_t diff_time) {
         if (diff > 0) {
             pa_log_info("Playback after capture (%lld), drop sink %lld", (long long) diff_time, (long long) diff);
 
-            /* go forwards on the read side */
-            pa_memblockq_drop(u->sink_memblockq, diff);
+            u->sink_skip = diff;
+            u->source_skip = 0;
         }
     } else if (diff_time > 0) {
         diff = pa_usec_to_bytes (diff_time, &u->source_output->sample_spec);
@@ -603,8 +605,8 @@ static void apply_diff_time(struct userdata *u, int64_t diff_time) {
         if (diff > 0) {
             pa_log_info("playback too far ahead (%lld), drop source %lld", (long long) diff_time, (long long) diff);
 
-            /* go back on the read side */
-            pa_memblockq_rewind(u->sink_memblockq, diff);
+            u->source_skip = diff;
+            u->sink_skip = 0;
         }
     }
 }
@@ -662,55 +664,66 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
         /* take fixed block from recorded samples */
         pa_memblockq_peek_fixed_size(u->source_memblockq, u->blocksize, &rchunk);
 
-        if (plen > u->blocksize) {
+        if (plen > u->blocksize && u->source_skip == 0) {
             uint8_t *rdata, *pdata, *cdata;
             pa_memchunk cchunk;
 
-            /* take fixed block from played samples */
-            pa_memblockq_peek_fixed_size(u->sink_memblockq, u->blocksize, &pchunk);
-
-            rdata = pa_memblock_acquire(rchunk.memblock);
-            rdata += rchunk.index;
-            pdata = pa_memblock_acquire(pchunk.memblock);
-            pdata += pchunk.index;
-
-            cchunk.index = 0;
-            cchunk.length = u->blocksize;
-            cchunk.memblock = pa_memblock_new(u->source->core->mempool, cchunk.length);
-            cdata = pa_memblock_acquire(cchunk.memblock);
-
-            /* perform echo cancelation */
-            u->ec->run(u->ec, rdata, pdata, cdata);
-
-            if (u->save_aec) {
-                if (u->captured_file)
-                    fwrite(rdata, 1, u->blocksize, u->captured_file);
-                if (u->played_file)
-                    fwrite(pdata, 1, u->blocksize, u->played_file);
-                if (u->canceled_file)
-                    fwrite(cdata, 1, u->blocksize, u->canceled_file);
-                pa_log_debug("AEC frame saved.");
+            if (u->sink_skip) {
+                size_t to_skip;
+
+                if (u->sink_skip > plen)
+                    to_skip = plen;
+                else
+                    to_skip = u->sink_skip;
+
+                pa_memblockq_drop(u->sink_memblockq, to_skip);
+                plen -= to_skip;
+
+                u->sink_skip -= to_skip;
             }
 
-            pa_memblock_release(cchunk.memblock);
-            pa_memblock_release(pchunk.memblock);
-            pa_memblock_release(rchunk.memblock);
-
-            /* drop consumed sink samples */
-            pa_memblockq_drop(u->sink_memblockq, u->blocksize);
-            pa_memblock_unref(pchunk.memblock);
-
-            pa_memblock_unref(rchunk.memblock);
-            /* the filtered samples now become the samples from our
-             * source */
-            rchunk = cchunk;
-
-            plen -= u->blocksize;
-        } else {
-            /* not enough played samples to perform echo cancelation,
-             * drop what we have */
-            pa_memblockq_drop(u->sink_memblockq, u->blocksize - plen);
-            plen = 0;
+            if (plen > u->blocksize && u->sink_skip == 0) {
+                /* take fixed block from played samples */
+                pa_memblockq_peek_fixed_size(u->sink_memblockq, u->blocksize, &pchunk);
+
+                rdata = pa_memblock_acquire(rchunk.memblock);
+                rdata += rchunk.index;
+                pdata = pa_memblock_acquire(pchunk.memblock);
+                pdata += pchunk.index;
+
+                cchunk.index = 0;
+                cchunk.length = u->blocksize;
+                cchunk.memblock = pa_memblock_new(u->source->core->mempool, cchunk.length);
+                cdata = pa_memblock_acquire(cchunk.memblock);
+
+                /* perform echo cancelation */
+                u->ec->run(u->ec, rdata, pdata, cdata);
+
+                if (u->save_aec) {
+                    if (u->captured_file)
+                        fwrite(rdata, 1, u->blocksize, u->captured_file);
+                    if (u->played_file)
+                        fwrite(pdata, 1, u->blocksize, u->played_file);
+                    if (u->canceled_file)
+                        fwrite(cdata, 1, u->blocksize, u->canceled_file);
+                    pa_log_debug("AEC frame saved.");
+                }
+
+                pa_memblock_release(cchunk.memblock);
+                pa_memblock_release(pchunk.memblock);
+                pa_memblock_release(rchunk.memblock);
+
+                /* drop consumed sink samples */
+                pa_memblockq_drop(u->sink_memblockq, u->blocksize);
+                pa_memblock_unref(pchunk.memblock);
+
+                pa_memblock_unref(rchunk.memblock);
+                /* the filtered samples now become the samples from our
+                 * source */
+                rchunk = cchunk;
+
+                plen -= u->blocksize;
+            }
         }
 
         /* forward the (echo-canceled) data to the virtual source */
@@ -718,8 +731,17 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
         pa_memblock_unref(rchunk.memblock);
 
         pa_memblockq_drop(u->source_memblockq, u->blocksize);
-
         rlen -= u->blocksize;
+
+        if (u->source_skip) {
+            if (u->source_skip > u->blocksize) {
+                u->source_skip -= u->blocksize;
+            }
+            else {
+                u->sink_skip += (u->blocksize - u->source_skip);
+                u->source_skip = 0;
+            }
+        }
     }
 }
 
@@ -773,19 +795,13 @@ static void source_output_process_rewind_cb(pa_source_output *o, size_t nbytes)
 /* Called from I/O thread context */
 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
     struct userdata *u;
-    size_t amount = 0;
 
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
     pa_log_debug("Sink process rewind %lld", (long long) nbytes);
 
-    if (u->sink->thread_info.rewind_nbytes > 0) {
-        amount = PA_MIN(u->sink->thread_info.rewind_nbytes, nbytes);
-        u->sink->thread_info.rewind_nbytes = 0;
-    }
-
-    pa_sink_process_rewind(u->sink, amount);
+    pa_sink_process_rewind(u->sink, nbytes);
 
     pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_REWIND, NULL, (int64_t) nbytes, NULL, NULL);
     u->send_counter -= nbytes;
@@ -807,8 +823,8 @@ static void source_output_snapshot_within_thread(struct userdata *u, struct snap
     snapshot->source_latency = latency;
     snapshot->source_delay = delay;
     snapshot->recv_counter = u->recv_counter;
-    snapshot->rlen = rlen;
-    snapshot->plen = plen;
+    snapshot->rlen = rlen + u->sink_skip;
+    snapshot->plen = plen + u->source_skip;
 }
 
 
@@ -900,6 +916,7 @@ static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
 
     pa_log_debug("Sink input update max rewind %lld", (long long) nbytes);
 
+    pa_memblockq_set_maxrewind (u->sink_memblockq, nbytes);
     pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
 }
 
@@ -922,7 +939,7 @@ static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
     pa_sink_input_assert_ref(i);
     pa_assert_se(u = i->userdata);
 
-    pa_log_debug("Sink input update max rewind %lld", (long long) nbytes);
+    pa_log_debug("Sink input update max request %lld", (long long) nbytes);
 
     pa_sink_set_max_request_within_thread(u->sink, nbytes);
 }

commit c47d6896136e04dff538240ae29fd0cac021b25b
Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date:   Thu Sep 9 12:29:59 2010 +0200

    alsa: make defines for smoother configuration
    
    Make new defines for the smoother window size and adjust time constants instead
    of reusing some unrelated constant.
    
    Increase the smoother window size even more because the bigger it is, the
    better. Since we have a 200ms max update interval and the max smoother history
    is 64 entries, 10seconds is a good default.
    
    Decrease the smoother adjust time to 1 second. The previous value of 4 seconds
    was too much to adapt quickly after a resume.

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 14f08a5..e92c6e5 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -78,6 +78,9 @@
 #define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC)                /* 10ms  -- Sleep at least 10ms on each iteration */
 #define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC)                /* 4ms   -- Wakeup at least this long before the buffer runs empty*/
 
+#define SMOOTHER_WINDOW_USEC  (10*PA_USEC_PER_SEC)                 /* 10s   -- smoother windows size */
+#define SMOOTHER_ADJUST_USEC  (1*PA_USEC_PER_SEC)                  /* 1s    -- smoother adjust time */
+
 #define SMOOTHER_MIN_INTERVAL (2*PA_USEC_PER_MSEC)                 /* 2ms   -- min smoother update interval */
 #define SMOOTHER_MAX_INTERVAL (200*PA_USEC_PER_MSEC)               /* 200ms -- max smoother update interval */
 
@@ -1756,8 +1759,8 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
     u->smoother = pa_smoother_new(
-            DEFAULT_TSCHED_BUFFER_USEC*2,
-            DEFAULT_TSCHED_BUFFER_USEC*2,
+            SMOOTHER_ADJUST_USEC,
+            SMOOTHER_WINDOW_USEC,
             TRUE,
             TRUE,
             5,
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index fd6c189..5f12675 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -73,6 +73,9 @@
 #define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC)                /* 10ms */
 #define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC)                /* 4ms */
 
+#define SMOOTHER_WINDOW_USEC  (10*PA_USEC_PER_SEC)                 /* 10s */
+#define SMOOTHER_ADJUST_USEC  (1*PA_USEC_PER_SEC)                  /* 1s */
+
 #define SMOOTHER_MIN_INTERVAL (2*PA_USEC_PER_MSEC)                 /* 2ms */
 #define SMOOTHER_MAX_INTERVAL (200*PA_USEC_PER_MSEC)               /* 200ms */
 
@@ -1567,8 +1570,8 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
 
     u->smoother = pa_smoother_new(
-            DEFAULT_TSCHED_BUFFER_USEC*2,
-            DEFAULT_TSCHED_BUFFER_USEC*2,
+            SMOOTHER_ADJUST_USEC,
+            SMOOTHER_WINDOW_USEC,
             TRUE,
             TRUE,
             5,

commit 7b873785ca40c7d1d3109f8cc8202b996ebe1522
Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date:   Thu Sep 9 12:39:15 2010 +0200

    echo-cancel: improve accuracy
    
    Make the echo canceler drift up to 1ms now that things are more accurate.
    Add 10 samples of headroom to allow for timing inaccuracies.

diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c
index 4df77c3..467e216 100644
--- a/src/modules/echo-cancel/module-echo-cancel.c
+++ b/src/modules/echo-cancel/module-echo-cancel.c
@@ -295,7 +295,7 @@ static void time_callback(pa_mainloop_api *a, pa_time_event *e, const struct tim
         new_rate = base_rate;
     }
     else {
-        if (diff_time > 4000) {
+        if (diff_time > 1000) {
             /* diff too big, quickly adjust */
             pa_asyncmsgq_post(u->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_APPLY_DIFF_TIME,
                 NULL, diff_time, NULL, NULL);
@@ -594,6 +594,10 @@ static void apply_diff_time(struct userdata *u, int64_t diff_time) {
         diff = pa_usec_to_bytes (-diff_time, &u->source_output->sample_spec);
 
         if (diff > 0) {
+            /* add some extra safety samples to compensate for jitter in the
+             * timings */
+            diff += 10 * pa_frame_size (&u->source_output->sample_spec);
+
             pa_log_info("Playback after capture (%lld), drop sink %lld", (long long) diff_time, (long long) diff);
 
             u->sink_skip = diff;

commit 26dfacf20b34642ccc4aefa2eb01fb67c38b9fc2
Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date:   Thu Sep 9 16:20:20 2010 +0200

    echo-cancel: pause timer when echo canceling is off
    
    While the sink or source is in the suspended state, disable the timer
    callback because we are not doing any echo canceling then.

diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c
index 467e216..8ae45a5 100644
--- a/src/modules/echo-cancel/module-echo-cancel.c
+++ b/src/modules/echo-cancel/module-echo-cancel.c
@@ -172,7 +172,6 @@ struct userdata {
     pa_bool_t source_auto_desc;
     pa_source_output *source_output;
     pa_memblockq *source_memblockq; /* echo canceler needs fixed sized chunks */
-    pa_atomic_t source_active;
     size_t source_skip;
 
     pa_sink *sink;
@@ -181,11 +180,11 @@ struct userdata {
     pa_memblockq *sink_memblockq;
     int64_t send_counter;          /* updated in sink IO thread */
     int64_t recv_counter;
-    pa_atomic_t sink_active;
     size_t sink_skip;
 
     pa_atomic_t request_resync;
 
+    int active_mask;
     pa_time_event *time_event;
     pa_usec_t adjust_time;
 
@@ -272,8 +271,8 @@ static void time_callback(pa_mainloop_api *a, pa_time_event *e, const struct tim
     pa_assert(u->time_event == e);
     pa_assert_ctl_context();
 
-    if (pa_atomic_load (&u->sink_active) == 0 || pa_atomic_load (&u->source_active) == 0)
-        goto done;
+    if (u->active_mask != 3)
+        return;
 
     /* update our snapshots */
     pa_asyncmsgq_send(u->source_output->source->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT, &latency_snapshot, 0, NULL);
@@ -318,7 +317,6 @@ static void time_callback(pa_mainloop_api *a, pa_time_event *e, const struct tim
         pa_sink_input_set_rate(u->sink_input, new_rate);
     }
 
-done:
     pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time);
 }
 
@@ -398,14 +396,18 @@ static int source_set_state_cb(pa_source *s, pa_source_state_t state) {
         !PA_SOURCE_OUTPUT_IS_LINKED(pa_source_output_get_state(u->source_output)))
         return 0;
 
-    pa_log_debug("Source state %d", state);
+    pa_log_debug("Source state %d %d", state, u->active_mask);
 
     if (state == PA_SOURCE_RUNNING) {
-        pa_atomic_store (&u->source_active, 1);
+        /* restart timer when both sink and source are active */
+        u->active_mask |= 1;
+        if (u->active_mask == 3)
+            pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time);
+
         pa_atomic_store (&u->request_resync, 1);
         pa_source_output_cork(u->source_output, FALSE);
     } else if (state == PA_SOURCE_SUSPENDED) {
-        pa_atomic_store (&u->source_active, 0);
+        u->active_mask &= ~1;
         pa_source_output_cork(u->source_output, TRUE);
     }
     return 0;
@@ -422,14 +424,18 @@ static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) {
         !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
         return 0;
 
-    pa_log_debug("Sink state %d", state);
+    pa_log_debug("Sink state %d %d", state, u->active_mask);
 
     if (state == PA_SINK_RUNNING) {
-        pa_atomic_store (&u->sink_active, 1);
+        /* restart timer when both sink and source are active */
+        u->active_mask |= 2;
+        if (u->active_mask == 3)
+            pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time);
+
         pa_atomic_store (&u->request_resync, 1);
         pa_sink_input_cork(u->sink_input, FALSE);
     } else if (state == PA_SINK_SUSPENDED) {
-        pa_atomic_store (&u->sink_active, 0);
+        u->active_mask &= ~2;
         pa_sink_input_cork(u->sink_input, TRUE);
     }
     return 0;
@@ -598,7 +604,7 @@ static void apply_diff_time(struct userdata *u, int64_t diff_time) {
              * timings */
             diff += 10 * pa_frame_size (&u->source_output->sample_spec);
 
-            pa_log_info("Playback after capture (%lld), drop sink %lld", (long long) diff_time, (long long) diff);
+            pa_log("Playback after capture (%lld), drop sink %lld", (long long) diff_time, (long long) diff);
 
             u->sink_skip = diff;
             u->source_skip = 0;
@@ -607,7 +613,7 @@ static void apply_diff_time(struct userdata *u, int64_t diff_time) {
         diff = pa_usec_to_bytes (diff_time, &u->source_output->sample_spec);
 
         if (diff > 0) {
-            pa_log_info("playback too far ahead (%lld), drop source %lld", (long long) diff_time, (long long) diff);
+            pa_log("playback too far ahead (%lld), drop source %lld", (long long) diff_time, (long long) diff);
 
             u->source_skip = diff;
             u->sink_skip = 0;
@@ -1574,6 +1580,9 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    /* our source and sink are not suspended when we create them */
+    u->active_mask = 3;
+
     if (u->adjust_time > 0)
         u->time_event = pa_core_rttime_new(m->core, pa_rtclock_now() + u->adjust_time, time_callback, u);
 
@@ -1629,6 +1638,9 @@ void pa__done(pa_module*m) {
     /* See comments in source_output_kill_cb() above regarding
      * destruction order! */
 
+    if (u->time_event)
+        u->core->mainloop->time_free(u->time_event);
+
     if (u->source_output)
         pa_source_output_unlink(u->source_output);
     if (u->sink_input)
@@ -1649,9 +1661,6 @@ void pa__done(pa_module*m) {
     if (u->sink)
         pa_sink_unref(u->sink);
 
-    if (u->time_event)
-        u->core->mainloop->time_free(u->time_event);
-
     if (u->source_memblockq)
         pa_memblockq_free(u->source_memblockq);
     if (u->sink_memblockq)

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list