diff options
-rw-r--r-- | src/modules/module-echo-cancel.c | 50 |
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 */ |