From f2f60ee0ec77cb119dbf6503fcba2d3ebb961532 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 4 Mar 2024 15:34:42 +0100 Subject: [PATCH] jack-tunnel: convert JACK time to MONOTONIC JACK current_msec can be in MONOTONIC_RAW or MONOTONIC, depending on how JACK was compiled (but it's likely MONOTONIC_RAW). PipeWire requires the nsec field to be in MONOTONIC so take some time snapshots from both clocks and apply a translation. Also make sure we only get the nsec time from streams that exist. See #3886 --- src/modules/module-ffado-driver.c | 14 +++++++++++++- src/modules/module-jack-tunnel.c | 23 +++++++++++++++++++++++ src/modules/module-jack-tunnel/weakjack.h | 2 ++ src/modules/module-netjack2-driver.c | 13 ++++++++++++- 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/modules/module-ffado-driver.c b/src/modules/module-ffado-driver.c index 5adcaf3f7..e06165259 100644 --- a/src/modules/module-ffado-driver.c +++ b/src/modules/module-ffado-driver.c @@ -679,6 +679,18 @@ static int create_filters(struct impl *impl) return res; } +static inline uint64_t get_time_nsec(struct impl *impl) +{ + uint64_t nsec; + if (impl->sink.filter) + nsec = pw_filter_get_nsec(impl->sink.filter); + else if (impl->source.filter) + nsec = pw_filter_get_nsec(impl->source.filter); + else + nsec = 0; + return nsec; +} + static void *ffado_process_thread(void *arg) { struct impl *impl = arg; @@ -689,7 +701,7 @@ static void *ffado_process_thread(void *arg) ffado_wait_response response; response = ffado_streaming_wait(impl->dev); - nsec = pw_filter_get_nsec(impl->source.filter); + nsec = get_time_nsec(impl); switch (response) { case ffado_wait_ok: diff --git a/src/modules/module-jack-tunnel.c b/src/modules/module-jack-tunnel.c index 510086011..00d1d651f 100644 --- a/src/modules/module-jack-tunnel.c +++ b/src/modules/module-jack-tunnel.c @@ -664,6 +664,18 @@ static int create_filters(struct impl *impl) return res; } +static inline uint64_t get_time_nsec(struct impl *impl) +{ + uint64_t nsec; + if (impl->sink.filter) + nsec = pw_filter_get_nsec(impl->sink.filter); + else if (impl->source.filter) + nsec = pw_filter_get_nsec(impl->source.filter); + else + nsec = 0; + return nsec; +} + static void *jack_process_thread(void *arg) { struct impl *impl = arg; @@ -693,11 +705,22 @@ static void *jack_process_thread(void *arg) jack_time_t next_usecs; float period_usecs; jack_position_t pos; + uint64_t t1, t2, t3; + int64_t d1; jack.get_cycle_times(impl->client, ¤t_frames, ¤t_usecs, &next_usecs, &period_usecs); + /* convert from JACK (likely MONOTONIC_RAW) to MONOTONIC */ + t1 = get_time_nsec(impl) / 1000; + t2 = jack.get_time(); + t3 = get_time_nsec(impl) / 1000; + d1 = t1 + (t3 - t1) / 2 - t2; + + current_usecs += d1; + next_usecs += d1; + c->nsec = current_usecs * SPA_NSEC_PER_USEC; c->rate = SPA_FRACTION(1, impl->samplerate); c->position = current_frames; diff --git a/src/modules/module-jack-tunnel/weakjack.h b/src/modules/module-jack-tunnel/weakjack.h index 42580f798..e9ad7f4a7 100644 --- a/src/modules/module-jack-tunnel/weakjack.h +++ b/src/modules/module-jack-tunnel/weakjack.h @@ -21,6 +21,7 @@ struct weakjack { jack_nframes_t (*cycle_wait) (jack_client_t* client); void (*cycle_signal) (jack_client_t* client, int status); + jack_time_t (*get_time) (void); jack_nframes_t (*frame_time) (const jack_client_t *); int (*get_cycle_times) (const jack_client_t *client, jack_nframes_t *current_frames, @@ -111,6 +112,7 @@ static inline int weakjack_load_by_path(struct weakjack *jack, const char *path) spa_zero(*jack); LOAD_SYM(cycle_wait); LOAD_SYM(cycle_signal); + LOAD_SYM(get_time); LOAD_SYM(frame_time); LOAD_SYM(get_cycle_times); LOAD_SYM(transport_query); diff --git a/src/modules/module-netjack2-driver.c b/src/modules/module-netjack2-driver.c index 1b37ec800..60ee205f0 100644 --- a/src/modules/module-netjack2-driver.c +++ b/src/modules/module-netjack2-driver.c @@ -607,6 +607,17 @@ static int create_filters(struct impl *impl) return res; } +static inline uint64_t get_time_nsec(struct impl *impl) +{ + uint64_t nsec; + if (impl->sink.filter) + nsec = pw_filter_get_nsec(impl->sink.filter); + else if (impl->source.filter) + nsec = pw_filter_get_nsec(impl->source.filter); + else + nsec = 0; + return nsec; +} static void on_data_io(void *data, int fd, uint32_t mask) @@ -627,7 +638,7 @@ on_data_io(void *data, int fd, uint32_t mask) if (nframes == 0) return; - nsec = pw_filter_get_nsec(impl->source.filter); + nsec = get_time_nsec(impl); if (!impl->done) { impl->pw_xrun++;