summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/module-echo-cancel.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/src/modules/module-echo-cancel.c b/src/modules/module-echo-cancel.c
index b080ec25a..498f0940c 100644
--- a/src/modules/module-echo-cancel.c
+++ b/src/modules/module-echo-cancel.c
@@ -40,6 +40,7 @@
#include <pulse/timeval.h>
#include <pulse/rtclock.h>
+#include <pulsecore/atomic.h>
#include <pulsecore/macro.h>
#include <pulsecore/core-error.h>
#include <pulsecore/namereg.h>
@@ -128,6 +129,8 @@ struct userdata {
pa_source_output *source_output;
pa_memblockq *source_memblockq; /* echo canceler needs fixed sized chunks */
uint64_t rec_counter;
+ pa_atomic_t source_active;
+ pa_atomic_t request_source_snapshot;
pa_sink *sink;
pa_bool_t sink_auto_desc;
@@ -135,6 +138,8 @@ struct userdata {
pa_memblockq *sink_memblockq;
uint64_t send_counter; /* updated in sink IO thread */
uint64_t play_counter;
+ pa_atomic_t sink_active;
+ pa_atomic_t request_sink_snapshot;
pa_time_event *time_event;
pa_usec_t adjust_time;
@@ -205,6 +210,9 @@ 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;
+
pa_asyncmsgq_send(u->source_output->source->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL);
pa_asyncmsgq_send(u->sink_input->sink->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL);
@@ -229,10 +237,7 @@ static void time_callback(pa_mainloop_api *a, pa_time_event *e, const struct tim
buffer_latency = pa_bytes_to_usec(buffer, &u->source_output->sample_spec);
/* capture and playback samples are perfectly aligned when diff_time is 0 */
- if (u->latency_snapshot.rec_counter && u->latency_snapshot.play_counter)
- diff_time = (play_time - buffer_latency) - rec_time;
- else
- diff_time = 0;
+ diff_time = (play_time - buffer_latency) - rec_time;
pa_log_debug("diff %lld %lld %lld %lld %lld", (long long) rec_time, (long long) play_time,
(long long) diff_time, (long long) buffer_latency,
@@ -296,6 +301,7 @@ 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);
}
@@ -377,12 +383,13 @@ static int source_set_state_cb(pa_source *s, pa_source_state_t state) {
pa_log_debug("Source state %d", state);
- if (state == PA_SINK_RUNNING) {
- u->rec_counter = 0;
- u->play_counter = 0;
- u->send_counter = 0;
+ if (state == PA_SOURCE_RUNNING) {
+ pa_atomic_store (&u->source_active, 1);
+ pa_atomic_store (&u->request_sink_snapshot, 1);
+ pa_atomic_store (&u->request_source_snapshot, 1);
pa_source_output_cork(u->source_output, FALSE);
- } else if (state == PA_SINK_SUSPENDED) {
+ } else if (state == PA_SOURCE_SUSPENDED) {
+ pa_atomic_store (&u->source_active, 0);
pa_source_output_cork(u->source_output, TRUE);
}
return 0;
@@ -402,11 +409,12 @@ static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) {
pa_log_debug("Sink state %d", state);
if (state == PA_SINK_RUNNING) {
- u->rec_counter = 0;
- u->play_counter = 0;
- u->send_counter = 0;
+ pa_atomic_store (&u->sink_active, 1);
+ pa_atomic_store (&u->request_sink_snapshot, 1);
+ pa_atomic_store (&u->request_source_snapshot, 1);
pa_sink_input_cork(u->sink_input, FALSE);
} else if (state == PA_SINK_SUSPENDED) {
+ pa_atomic_store (&u->sink_active, 0);
pa_sink_input_cork(u->sink_input, TRUE);
}
return 0;
@@ -589,7 +597,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
/* if we have a play_counter, take a snapshot of the capture position so
* that we can start to realign */
- if (u->rec_counter == 0 && u->play_counter) {
+ if (pa_atomic_load (&u->request_source_snapshot) == 1 && pa_atomic_load (&u->request_sink_snapshot) == 0) {
now = pa_rtclock_now();
delay = pa_memblockq_get_length(o->thread_info.delay_memblockq);
@@ -604,6 +612,7 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
rec_counter -= delay;
u->rec_counter = rec_counter;
+ pa_atomic_store (&u->request_source_snapshot, 0);
/* counter changed, we need to recalculate alignment */
u->need_realign = TRUE;
@@ -643,7 +652,8 @@ static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk)
plen = pa_memblockq_get_length(u->sink_memblockq);
- if (u->need_realign && u->rec_counter && u->play_counter) {
+ if (u->need_realign && (pa_atomic_load (&u->request_source_snapshot) == 0) &&
+ (pa_atomic_load (&u->request_sink_snapshot) == 0)) {
pa_log_debug("alignment play: %lld, record: %lld (%lld %lld)",
(long long) u->play_counter,
(long long) u->rec_counter + plen,
@@ -786,22 +796,24 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
if (i->thread_info.underrun_for > 0) {
pa_log_debug("Handling end of underrun.");
- u->send_counter = 0;
+ pa_atomic_store (&u->request_sink_snapshot, 1);
}
- if (u->send_counter == 0) {
+ if (pa_atomic_load (&u->request_sink_snapshot) == 1) {
now = pa_rtclock_now();
latency = pa_sink_get_latency_within_thread(i->sink);
delay = pa_memblockq_get_length(i->thread_info.render_memblockq);
delay = (u->sink_input->thread_info.resampler ? pa_resampler_request(u->sink_input->thread_info.resampler, delay) : delay);
- /* convert to sample position */
+ /* convert to sample position, use the sample rate from the source
+ * because we don't want to use the adjusted samplerate */
send_counter = pa_usec_to_bytes (now + latency, &u->source_output->sample_spec);
send_counter += delay;
/* convert to sample position */
new_count = u->send_counter = send_counter;
+ pa_atomic_store (&u->request_sink_snapshot, 0);
pa_log_debug("snapshot playback %lld %lld %lld %lld (%lld %lld)", (long long) send_counter,
(long long) u->send_counter, (long long) chunk->length, (long long) latency,
@@ -1059,7 +1071,7 @@ static void sink_input_update_sink_requested_latency_cb(pa_sink_input *i) {
latency = pa_sink_get_requested_latency_within_thread(i->sink);
pa_log_debug("Sink input update requested latency %lld", (long long) latency);
- u->send_counter = 0;
+ pa_atomic_store (&u->request_sink_snapshot, 1);
}
/* Called from I/O thread context */
@@ -1073,7 +1085,7 @@ static void source_output_update_source_requested_latency_cb(pa_source_output *o
latency = pa_source_get_requested_latency_within_thread(o->source);
pa_log_debug("source output update requested latency %lld", (long long) latency);
- u->rec_counter = 0;
+ pa_atomic_store (&u->request_source_snapshot, 1);
}
/* Called from I/O thread context */