From 7ad714c98aa72c798549ac00fb5dde62be19569c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 17 Jul 2015 10:41:06 +0200 Subject: [PATCH 3/3] tunnel-new: Increase latency on underflow/overflow We need to adapt to communication latencies between us and the next server. Do this the simplest way possible by increasing the minimum latency whenever we've hit an underflow/overflow. Signed-off-by: Pierre Ossman --- src/modules/module-tunnel-sink-new.c | 20 ++++++++++++++++++++ src/modules/module-tunnel-source-new.c | 15 +++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/modules/module-tunnel-sink-new.c b/src/modules/module-tunnel-sink-new.c index a34ffea..0231795 100644 --- a/src/modules/module-tunnel-sink-new.c +++ b/src/modules/module-tunnel-sink-new.c @@ -62,6 +62,7 @@ PA_MODULE_USAGE( /* FIXME: Default latency to use until we have proper rewind support. * Probably best to keep this in sync with DEFAULT_FIXED_LATENCY. */ #define DEFAULT_LATENCY_USEC (250*PA_USEC_PER_MSEC) +#define LATENCY_INC_MAX_STEP_USEC (10*PA_USEC_PER_MSEC) #define TUNNEL_THREAD_FAILED_MAINLOOP 1 static void stream_state_cb(pa_stream *stream, void *userdata); @@ -297,6 +298,24 @@ static void stream_set_buffer_attr_cb(pa_stream *stream, int success, void *user stream_changed_buffer_attr_cb(stream, userdata); } +/* called when the server experiences an underrun of our buffer */ +static void stream_underflow_callback(pa_stream *stream, void *userdata) { + pa_usec_t old_min_latency, new_min_latency; + struct userdata *u = userdata; + pa_assert(u); + + old_min_latency = u->sink->thread_info.min_latency; + new_min_latency = PA_MIN(old_min_latency * 2, old_min_latency + LATENCY_INC_MAX_STEP_USEC); + new_min_latency = PA_MIN(new_min_latency, u->sink->thread_info.max_latency); + + if (old_min_latency != new_min_latency) { + pa_log_info("Increasing minimal latency to %0.2f ms", + (double) new_min_latency / PA_USEC_PER_MSEC); + + pa_sink_set_latency_range_within_thread(u->sink, new_min_latency, u->sink->thread_info.max_latency); + } +} + static void context_state_cb(pa_context *c, void *userdata) { struct userdata *u = userdata; pa_assert(u); @@ -352,6 +371,7 @@ static void context_state_cb(pa_context *c, void *userdata) { pa_stream_set_state_callback(u->stream, stream_state_cb, userdata); pa_stream_set_buffer_attr_callback(u->stream, stream_changed_buffer_attr_cb, userdata); + pa_stream_set_underflow_callback(u->stream, stream_underflow_callback, userdata); if (pa_stream_connect_playback(u->stream, u->remote_sink_name, &bufferattr, diff --git a/src/modules/module-tunnel-source-new.c b/src/modules/module-tunnel-source-new.c index c3ef936..ae7ec28 100644 --- a/src/modules/module-tunnel-source-new.c +++ b/src/modules/module-tunnel-source-new.c @@ -59,6 +59,7 @@ PA_MODULE_USAGE( "cookie=" ); +#define LATENCY_INC_MAX_STEP_USEC (10*PA_USEC_PER_MSEC) #define TUNNEL_THREAD_FAILED_MAINLOOP 1 static void stream_state_cb(pa_stream *stream, void *userdata); @@ -176,6 +177,7 @@ static void read_new_samples(struct userdata *u) { pa_memblock_unref_fixed(memchunk.memblock); } else { size_t bytes_to_generate = nbytes; + pa_usec_t old_min_latency, new_min_latency; /* we have a hole. generate silence */ memchunk = u->source->silence; @@ -190,6 +192,19 @@ static void read_new_samples(struct userdata *u) { } pa_memblock_unref(memchunk.memblock); + + /* there is no overflow callback so we're just going to have + * to assume that a hole means an overflow occured */ + old_min_latency = u->source->thread_info.min_latency; + new_min_latency = PA_MIN(old_min_latency * 2, old_min_latency + LATENCY_INC_MAX_STEP_USEC); + new_min_latency = PA_MIN(new_min_latency, u->source->thread_info.max_latency); + + if (old_min_latency != new_min_latency) { + pa_log_info("Increasing minimal latency to %0.2f ms", + (double) new_min_latency / PA_USEC_PER_MSEC); + + pa_source_set_latency_range_within_thread(u->source, new_min_latency, u->source->thread_info.max_latency); + } } pa_stream_drop(u->stream); -- 2.4.3