diff options
-rw-r--r-- | src/modules/alsa/alsa-sink.c | 15 | ||||
-rw-r--r-- | src/modules/alsa/alsa-source.c | 12 | ||||
-rw-r--r-- | src/modules/bluetooth/module-bluetooth-device.c | 11 | ||||
-rw-r--r-- | src/modules/module-combine.c | 11 | ||||
-rw-r--r-- | src/modules/module-esound-sink.c | 11 | ||||
-rw-r--r-- | src/modules/module-raop-sink.c | 11 | ||||
-rw-r--r-- | src/modules/module-tunnel.c | 13 | ||||
-rw-r--r-- | src/modules/rtp/module-rtp-recv.c | 10 | ||||
-rw-r--r-- | src/pulse/stream.c | 22 | ||||
-rw-r--r-- | src/pulsecore/time-smoother.c | 41 | ||||
-rw-r--r-- | src/pulsecore/time-smoother.h | 14 | ||||
-rw-r--r-- | src/tests/smoother-test.c | 8 |
12 files changed, 136 insertions, 43 deletions
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 0dc0e2b3..942b59e0 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -1286,7 +1286,7 @@ static void thread_func(void *userdata) { pa_log_info("Starting playback."); snd_pcm_start(u->pcm_handle); - pa_smoother_resume(u->smoother, pa_rtclock_usec()); + pa_smoother_resume(u->smoother, pa_rtclock_usec(), TRUE); } update_smoother(u); @@ -1495,7 +1495,6 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca snd_pcm_uframes_t period_frames, tsched_frames; size_t frame_size; pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, ignore_dB = FALSE; - pa_usec_t usec; pa_sink_new_data data; pa_assert(m); @@ -1559,10 +1558,14 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca u->rtpoll = pa_rtpoll_new(); 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, TRUE, 5); - usec = pa_rtclock_usec(); - pa_smoother_set_time_offset(u->smoother, usec); - pa_smoother_pause(u->smoother, usec); + u->smoother = pa_smoother_new( + DEFAULT_TSCHED_BUFFER_USEC*2, + DEFAULT_TSCHED_BUFFER_USEC*2, + TRUE, + TRUE, + 5, + pa_rtclock_usec(), + TRUE); if (reserve_init(u, pa_modargs_get_value( ma, "device_id", diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index 348cd082..a5d2e295 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -776,7 +776,7 @@ static int unsuspend(struct userdata *u) { /* FIXME: We need to reload the volume somehow */ snd_pcm_start(u->pcm_handle); - pa_smoother_resume(u->smoother, pa_rtclock_usec()); + pa_smoother_resume(u->smoother, pa_rtclock_usec(), TRUE); pa_log_info("Resumed successfully..."); @@ -1416,8 +1416,14 @@ 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->alsa_rtpoll_item = NULL; - u->smoother = pa_smoother_new(DEFAULT_TSCHED_WATERMARK_USEC*2, DEFAULT_TSCHED_WATERMARK_USEC*2, TRUE, 5); - pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec()); + u->smoother = pa_smoother_new( + DEFAULT_TSCHED_WATERMARK_USEC*2, + DEFAULT_TSCHED_WATERMARK_USEC*2, + TRUE, + TRUE, + 5, + pa_rtclock_usec(), + FALSE); if (reserve_init(u, pa_modargs_get_value( ma, "device_id", diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index 96b95b4f..4613172e 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -869,7 +869,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off if (start_stream_fd(u) < 0) failed = TRUE; - pa_smoother_resume(u->read_smoother, pa_rtclock_usec()); + pa_smoother_resume(u->read_smoother, pa_rtclock_usec(), TRUE); break; case PA_SOURCE_UNLINKED: @@ -1965,7 +1965,14 @@ int pa__init(pa_module* m) { u->core = m->core; u->service_fd = -1; u->stream_fd = -1; - u->read_smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10); + u->read_smoother = pa_smoother_new( + PA_USEC_PER_SEC, + PA_USEC_PER_SEC*2, + TRUE, + TRUE, + 10, + 0, + FALSE); u->sample_spec = m->core->default_sample_spec; u->modargs = ma; diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index b7e18bc3..a1ef8da4 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -664,7 +664,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse if (PA_PTR_TO_UINT(data) == PA_SINK_SUSPENDED) pa_smoother_pause(u->thread_info.smoother, pa_rtclock_usec()); else - pa_smoother_resume(u->thread_info.smoother, pa_rtclock_usec()); + pa_smoother_resume(u->thread_info.smoother, pa_rtclock_usec(), TRUE); break; @@ -1043,7 +1043,14 @@ int pa__init(pa_module*m) { pa_atomic_store(&u->thread_info.running, FALSE); u->thread_info.in_null_mode = FALSE; u->thread_info.counter = 0; - u->thread_info.smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10); + u->thread_info.smoother = pa_smoother_new( + PA_USEC_PER_SEC, + PA_USEC_PER_SEC*2, + TRUE, + TRUE, + 10, + 0, + FALSE); if (pa_modargs_get_value_u32(ma, "adjust_time", &u->adjust_time) < 0) { pa_log("Failed to parse adjust_time value"); diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index 5c47f444..a1a783aa 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -150,7 +150,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse case PA_SINK_RUNNING: if (u->sink->thread_info.state == PA_SINK_SUSPENDED) - pa_smoother_resume(u->smoother, pa_rtclock_usec()); + pa_smoother_resume(u->smoother, pa_rtclock_usec(), TRUE); break; @@ -545,7 +545,14 @@ int pa__init(pa_module*m) { u->module = m; m->userdata = u; u->fd = -1; - u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10); + u->smoother = pa_smoother_new( + PA_USEC_PER_SEC, + PA_USEC_PER_SEC*2, + TRUE, + TRUE, + 10, + 0, + FALSE); pa_memchunk_reset(&u->memchunk); u->offset = 0; diff --git a/src/modules/module-raop-sink.c b/src/modules/module-raop-sink.c index d8ddf184..4d68b1b0 100644 --- a/src/modules/module-raop-sink.c +++ b/src/modules/module-raop-sink.c @@ -192,7 +192,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse case PA_SINK_RUNNING: if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { - pa_smoother_resume(u->smoother, pa_rtclock_usec()); + pa_smoother_resume(u->smoother, pa_rtclock_usec(), TRUE); /* The connection can be closed when idle, so check to see if we need to reestablish it */ @@ -540,7 +540,14 @@ int pa__init(pa_module*m) { u->module = m; m->userdata = u; u->fd = -1; - u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10); + u->smoother = pa_smoother_new( + PA_USEC_PER_SEC, + PA_USEC_PER_SEC*2, + TRUE, + TRUE, + 10, + 0, + FALSE); pa_memchunk_reset(&u->raw_memchunk); pa_memchunk_reset(&u->encoded_memchunk); u->offset = 0; diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 1d658ba0..5ea58aa0 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -405,7 +405,7 @@ static void check_smoother_status(struct userdata *u, pa_bool_t past) { if (u->remote_suspended || u->remote_corked) pa_smoother_pause(u->smoother, x); else - pa_smoother_resume(u->smoother, x); + pa_smoother_resume(u->smoother, x, TRUE); } /* Called from IO thread context */ @@ -1815,7 +1815,14 @@ int pa__init(pa_module*m) { u->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));; u->source = NULL; #endif - u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC*2, TRUE, 10); + u->smoother = pa_smoother_new( + PA_USEC_PER_SEC, + PA_USEC_PER_SEC*2, + TRUE, + TRUE, + 10, + pa_rtclock_usec(), + FALSE); u->ctag = 1; u->device_index = u->channel = PA_INVALID_INDEX; u->time_event = NULL; @@ -1933,8 +1940,6 @@ int pa__init(pa_module*m) { u->fragsize = (uint32_t) -1; #endif - pa_smoother_set_time_offset(u->smoother, pa_rtclock_usec()); - if (!(u->thread = pa_thread_new(thread_func, u))) { pa_log("Failed to create thread."); goto fail; diff --git a/src/modules/rtp/module-rtp-recv.c b/src/modules/rtp/module-rtp-recv.c index 209770f9..445941cc 100644 --- a/src/modules/rtp/module-rtp-recv.c +++ b/src/modules/rtp/module-rtp-recv.c @@ -430,8 +430,14 @@ static struct session *session_new(struct userdata *u, const pa_sdp_info *sdp_in s->sdp_info = *sdp_info; s->rtpoll_item = NULL; s->intended_latency = LATENCY_USEC; - s->smoother = pa_smoother_new(PA_USEC_PER_SEC*5, PA_USEC_PER_SEC*2, TRUE, 10); - pa_smoother_set_time_offset(s->smoother, pa_timeval_load(&now)); + s->smoother = pa_smoother_new( + PA_USEC_PER_SEC*5, + PA_USEC_PER_SEC*2, + TRUE, + TRUE, + 10, + pa_timeval_load(&now), + FALSE); s->last_rate_update = pa_timeval_load(&now); pa_atomic_store(&s->timestamp, (int) now.tv_sec); diff --git a/src/pulse/stream.c b/src/pulse/stream.c index c4a54af6..ff3644ff 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -393,7 +393,8 @@ static void check_smoother_status(pa_stream *s, pa_bool_t aposteriori, pa_bool_t if (s->suspended || s->corked || force_stop) pa_smoother_pause(s->smoother, x); else if (force_start || s->buffer_attr.prebuf == 0) - pa_smoother_resume(s->smoother, x); + pa_smoother_resume(s->smoother, x, TRUE); + /* Please note that we have no idea if playback actually started * if prebuf is non-zero! */ @@ -1064,14 +1065,17 @@ static int create_stream( if (flags & PA_STREAM_INTERPOLATE_TIMING) { pa_usec_t x; - if (s->smoother) - pa_smoother_free(s->smoother); - - s->smoother = pa_smoother_new(SMOOTHER_ADJUST_TIME, SMOOTHER_HISTORY_TIME, !(flags & PA_STREAM_NOT_MONOTONIC), SMOOTHER_MIN_HISTORY); - x = pa_rtclock_usec(); - pa_smoother_set_time_offset(s->smoother, x); - pa_smoother_pause(s->smoother, x); + + pa_assert(!s->smoother); + s->smoother = pa_smoother_new( + SMOOTHER_ADJUST_TIME, + SMOOTHER_HISTORY_TIME, + !(flags & PA_STREAM_NOT_MONOTONIC), + TRUE, + SMOOTHER_MIN_HISTORY, + x, + TRUE); } if (!dev) @@ -1623,7 +1627,7 @@ static void stream_get_timing_info_callback(pa_pdispatch *pd, uint32_t command, pa_smoother_put(o->stream->smoother, u, calc_time(o->stream, TRUE)); if (i->playing) - pa_smoother_resume(o->stream->smoother, x); + pa_smoother_resume(o->stream->smoother, x, TRUE); } } diff --git a/src/pulsecore/time-smoother.c b/src/pulsecore/time-smoother.c index 65621948..55ac8687 100644 --- a/src/pulsecore/time-smoother.c +++ b/src/pulsecore/time-smoother.c @@ -78,17 +78,26 @@ struct pa_smoother { /* Cached parameters for our interpolation polynomial y=ax^3+b^2+cx */ double a, b, c; - pa_bool_t abc_valid; + pa_bool_t abc_valid:1; pa_bool_t monotonic:1; pa_bool_t paused:1; + pa_bool_t smoothing:1; /* If FALSE we skip the polonyomial interpolation step */ pa_usec_t pause_time; unsigned min_history; }; -pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_bool_t monotonic, unsigned min_history) { +pa_smoother* pa_smoother_new( + pa_usec_t adjust_time, + pa_usec_t history_time, + pa_bool_t monotonic, + pa_bool_t smoothing, + unsigned min_history, + pa_usec_t time_offset, + pa_bool_t paused) { + pa_smoother *s; pa_assert(adjust_time > 0); @@ -116,9 +125,13 @@ pa_smoother* pa_smoother_new(pa_usec_t adjust_time, pa_usec_t history_time, pa_b s->abc_valid = FALSE; s->paused = FALSE; + s->smoothing = smoothing; s->min_history = min_history; + s->paused = paused; + s->time_offset = s->pause_time = time_offset; + return s; } @@ -278,7 +291,7 @@ static void estimate(pa_smoother *s, pa_usec_t x, pa_usec_t *y, double *deriv) { pa_assert(s); pa_assert(y); - if (x >= s->px) { + if (!s->smoothing || x >= s->px) { int64_t t; /* The requested point is right of the point where we wanted @@ -348,7 +361,6 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) { * we can adjust our position smoothly from this one */ estimate(s, x, &ney, &nde); s->ex = x; s->ey = ney; s->de = nde; - s->ry = y; } @@ -359,8 +371,13 @@ void pa_smoother_put(pa_smoother *s, pa_usec_t x, pa_usec_t y) { s->dp = avg_gradient(s, x); /* And calculate when we want to be on track again */ - s->px = s->ex + s->adjust_time; - s->py = s->ry + (pa_usec_t) llrint(s->dp * (double) s->adjust_time); + if (s->smoothing) { + s->px = s->ex + s->adjust_time; + s->py = s->ry + (pa_usec_t) llrint(s->dp * (double) s->adjust_time); + } else { + s->px = s->ex; + s->py = s->ry; + } s->abc_valid = FALSE; @@ -420,7 +437,7 @@ void pa_smoother_pause(pa_smoother *s, pa_usec_t x) { s->pause_time = x; } -void pa_smoother_resume(pa_smoother *s, pa_usec_t x) { +void pa_smoother_resume(pa_smoother *s, pa_usec_t x, pa_bool_t fix_now) { pa_assert(s); if (!s->paused) @@ -433,6 +450,16 @@ void pa_smoother_resume(pa_smoother *s, pa_usec_t x) { s->paused = FALSE; s->time_offset += x - s->pause_time; + + if (fix_now) + pa_smoother_fix_now(s); +} + +void pa_smoother_fix_now(pa_smoother *s) { + pa_assert(s); + + s->px = s->ex; + s->py = s->ry; } pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay) { diff --git a/src/pulsecore/time-smoother.h b/src/pulsecore/time-smoother.h index 2051e640..5244a7e7 100644 --- a/src/pulsecore/time-smoother.h +++ b/src/pulsecore/time-smoother.h @@ -27,7 +27,15 @@ typedef struct pa_smoother pa_smoother; -pa_smoother* pa_smoother_new(pa_usec_t x_adjust_time, pa_usec_t x_history_time, pa_bool_t monotonic, unsigned min_history); +pa_smoother* pa_smoother_new( + pa_usec_t x_adjust_time, + pa_usec_t x_history_time, + pa_bool_t monotonic, + pa_bool_t smoothing, + unsigned min_history, + pa_usec_t x_offset, + pa_bool_t paused); + void pa_smoother_free(pa_smoother* s); /* Adds a new value to our dataset. x = local/system time, y = remote time */ @@ -42,8 +50,10 @@ pa_usec_t pa_smoother_translate(pa_smoother *s, pa_usec_t x, pa_usec_t y_delay); void pa_smoother_set_time_offset(pa_smoother *s, pa_usec_t x_offset); void pa_smoother_pause(pa_smoother *s, pa_usec_t x); -void pa_smoother_resume(pa_smoother *s, pa_usec_t x); +void pa_smoother_resume(pa_smoother *s, pa_usec_t x, pa_bool_t abrupt); void pa_smoother_reset(pa_smoother *s); +void pa_smoother_fix_now(pa_smoother *s); + #endif diff --git a/src/tests/smoother-test.c b/src/tests/smoother-test.c index 798dfed5..2cc9f58b 100644 --- a/src/tests/smoother-test.c +++ b/src/tests/smoother-test.c @@ -45,10 +45,12 @@ int main(int argc, char*argv[]) { srand(0); + pa_log_set_level(PA_LOG_DEBUG); + for (m = 0, u = 0; u < PA_ELEMENTSOF(msec); u+= 2) { msec[u] = m+1 + (rand() % 100) - 50; - msec[u+1] = m + (rand() % 2000) - 1000; + msec[u+1] = m + (rand() % 2000) - 1000 + 5000; m += rand() % 100; @@ -59,7 +61,7 @@ int main(int argc, char*argv[]) { msec[u+1] = 0; } - s = pa_smoother_new(700*PA_USEC_PER_MSEC, 2000*PA_USEC_PER_MSEC, TRUE, 6); + s = pa_smoother_new(700*PA_USEC_PER_MSEC, 2000*PA_USEC_PER_MSEC, FALSE, TRUE, 6, 0, TRUE); for (x = 0, u = 0; x < PA_USEC_PER_SEC * 10; x += PA_USEC_PER_MSEC) { @@ -67,6 +69,8 @@ int main(int argc, char*argv[]) { pa_smoother_put(s, (pa_usec_t) msec[u] * PA_USEC_PER_MSEC, (pa_usec_t) msec[u+1] * PA_USEC_PER_MSEC); printf("%i\t\t%i\n", msec[u], msec[u+1]); u += 2; + + pa_smoother_resume(s, (pa_usec_t) msec[u] * PA_USEC_PER_MSEC, TRUE); } printf("%llu\t%llu\n", (unsigned long long) (x/PA_USEC_PER_MSEC), (unsigned long long) (pa_smoother_get(s, x)/PA_USEC_PER_MSEC)); |