diff --git a/pipewire-jack/src/pipewire-jack.c b/pipewire-jack/src/pipewire-jack.c index 1d7707cdb..b7851a3ae 100644 --- a/pipewire-jack/src/pipewire-jack.c +++ b/pipewire-jack/src/pipewire-jack.c @@ -6583,6 +6583,7 @@ void jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_ jack_nframes_t nframes, rate; int direction; struct spa_latency_info *info; + int64_t min, max; return_if_fail(o != NULL); c = o->client; @@ -6601,10 +6602,15 @@ void jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_ rate = jack_get_sample_rate((jack_client_t*)c); info = &o->port.latency[direction]; - range->min = (jack_nframes_t)((info->min_quantum * nframes) + - info->min_rate + (info->min_ns * rate) / SPA_NSEC_PER_SEC); - range->max = (jack_nframes_t)((info->max_quantum * nframes) + - info->max_rate + (info->max_ns * rate) / SPA_NSEC_PER_SEC); + min = (int64_t)(info->min_quantum * nframes) + + info->min_rate + + (info->min_ns * (int64_t)rate) / (int64_t)SPA_NSEC_PER_SEC; + max = (int64_t)(info->max_quantum * nframes) + + info->max_rate + + (info->max_ns * (int64_t)rate) / (int64_t)SPA_NSEC_PER_SEC; + + range->min = SPA_MAX(min, 0); + range->max = SPA_MAX(max, 0); pw_log_debug("%p: %s get %d latency range %d %d", c, o->port.name, mode, range->min, range->max); @@ -6649,13 +6655,13 @@ void jack_port_set_latency_range (jack_port_t *port, jack_latency_callback_mode_ nframes = 1; latency.min_rate = range->min; - if (latency.min_rate >= nframes) { + if (latency.min_rate >= (int32_t)nframes) { latency.min_quantum = latency.min_rate / nframes; latency.min_rate %= nframes; } latency.max_rate = range->max; - if (latency.max_rate >= nframes) { + if (latency.max_rate >= (int32_t)nframes) { latency.max_quantum = latency.max_rate / nframes; latency.max_rate %= nframes; } diff --git a/spa/include/spa/param/latency-utils.h b/spa/include/spa/param/latency-utils.h index fc7fb12d2..93c0f6687 100644 --- a/spa/include/spa/param/latency-utils.h +++ b/spa/include/spa/param/latency-utils.h @@ -38,21 +38,27 @@ spa_latency_info_combine_start(struct spa_latency_info *info, enum spa_direction { *info = SPA_LATENCY_INFO(direction, .min_quantum = FLT_MAX, - .max_quantum = 0.0f, - .min_rate = UINT32_MAX, - .max_rate = 0, - .min_ns = UINT64_MAX, - .max_ns = 0); + .max_quantum = FLT_MIN, + .min_rate = INT32_MAX, + .max_rate = INT32_MIN, + .min_ns = INT64_MAX, + .max_ns = INT64_MIN); } static inline void spa_latency_info_combine_finish(struct spa_latency_info *info) { if (info->min_quantum == FLT_MAX) info->min_quantum = 0; - if (info->min_rate == UINT32_MAX) + if (info->max_quantum == FLT_MIN) + info->max_quantum = 0; + if (info->min_rate == INT32_MAX) info->min_rate = 0; - if (info->min_ns == UINT64_MAX) + if (info->max_rate == INT32_MIN) + info->max_rate = 0; + if (info->min_ns == INT64_MAX) info->min_ns = 0; + if (info->max_ns == INT64_MIN) + info->max_ns = 0; } static inline int diff --git a/spa/include/spa/param/latency.h b/spa/include/spa/param/latency.h index 456c8b6cb..4087941ca 100644 --- a/spa/include/spa/param/latency.h +++ b/spa/include/spa/param/latency.h @@ -50,10 +50,10 @@ struct spa_latency_info { enum spa_direction direction; float min_quantum; float max_quantum; - uint32_t min_rate; - uint32_t max_rate; - uint64_t min_ns; - uint64_t max_ns; + int32_t min_rate; + int32_t max_rate; + int64_t min_ns; + int64_t max_ns; }; #define SPA_LATENCY_INFO(dir,...) ((struct spa_latency_info) { .direction = (dir), ## __VA_ARGS__ }) @@ -74,8 +74,8 @@ enum spa_param_process_latency { /** Helper structure for managing process latency objects */ struct spa_process_latency_info { float quantum; - uint32_t rate; - uint64_t ns; + int32_t rate; + int64_t ns; }; #define SPA_PROCESS_LATENCY_INFO_INIT(...) ((struct spa_process_latency_info) { __VA_ARGS__ }) diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c index 7e19d4beb..377bab71a 100644 --- a/src/pipewire/stream.c +++ b/src/pipewire/stream.c @@ -2371,7 +2371,8 @@ int pw_stream_get_time_n(struct pw_stream *stream, struct pw_time *time, size_t time->delay += (int64_t)(((impl->latency.min_quantum + impl->latency.max_quantum) / 2.0f) * quantum); time->delay += (impl->latency.min_rate + impl->latency.max_rate) / 2; - time->delay += ((impl->latency.min_ns + impl->latency.max_ns) / 2) * time->rate.denom / SPA_NSEC_PER_SEC; + time->delay += ((impl->latency.min_ns + impl->latency.max_ns) / 2) * + (int64_t)time->rate.denom / (int64_t)SPA_NSEC_PER_SEC; avail_buffers = spa_ringbuffer_get_read_index(&impl->dequeued.ring, &index); avail_buffers = SPA_CLAMP(avail_buffers, 0, (int32_t)impl->n_buffers); diff --git a/src/pipewire/stream.h b/src/pipewire/stream.h index 4f1206bf6..c4610a8fa 100644 --- a/src/pipewire/stream.h +++ b/src/pipewire/stream.h @@ -303,6 +303,13 @@ struct pw_stream_control { * caused by the hardware. The delay is usually quite stable and should only change when * the topology, quantum or samplerate of the graph changes. * + * The delay requires the application to send the stream early relative to other synchronized + * streams in order to arrive at the edge of the graph in time. This is usually done by + * delaying the other streams with the given delay. + * + * Note that the delay can be negative. A negative delay means that this stream should be + * delayed with the (positive) delay relative to other streams. + * * pw_time.queued and pw_time.buffered is expressed in the time domain of the stream, * or the format that is used for the buffers of this stream. *