From ac3ac3382b1a7d90371d52e04d835fecb5e7405c Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sun, 21 Dec 2025 15:07:16 +0200 Subject: [PATCH] bluez5: iso-io: delay streaming start until all acquires are complete For better start synchronization, we should wait until all ISO nodes that are going to be started finish creating ISO io. Add a separate ready flag for startup that is set when all Acquire requests are complete. --- spa/plugins/bluez5/bluez5-dbus.c | 27 ++++++++++++++++++++++----- spa/plugins/bluez5/iso-io.c | 26 +++++++++++++++++++++++++- spa/plugins/bluez5/iso-io.h | 2 ++ 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/spa/plugins/bluez5/bluez5-dbus.c b/spa/plugins/bluez5/bluez5-dbus.c index 2030ff674..95a235f5e 100644 --- a/spa/plugins/bluez5/bluez5-dbus.c +++ b/spa/plugins/bluez5/bluez5-dbus.c @@ -4029,6 +4029,20 @@ static int transport_create_iso_io(struct spa_bt_transport *transport) return 0; } +static void transport_check_iso_ready(struct spa_bt_monitor *monitor) +{ + struct spa_bt_transport *t; + + /* Mark ISO ready after all pending acquires are complete */ + spa_list_for_each(t, &monitor->transport_list, link) + if (t->acquire_call) + return; + + spa_list_for_each(t, &monitor->transport_list, link) + if (t->iso_io) + spa_bt_iso_io_ready(t->iso_io); +} + static bool transport_in_same_cig(struct spa_bt_transport *transport, struct spa_bt_transport *other) { return (other->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE)) && @@ -4105,8 +4119,8 @@ finish: * is handled separately. */ if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || - (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) - return; + (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) + goto exit; } else { if (transport_create_iso_io(transport) < 0) spa_log_error(monitor->log, "transport %p: transport_create_iso_io failed", @@ -4117,9 +4131,9 @@ finish: */ /* TODO: handling multiple BIGs support */ if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || - (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { + (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE); - return; + goto exit; } if (!transport->bap_initiator) @@ -4166,7 +4180,7 @@ finish: if (!transport_in_same_cig(transport, t)) continue; if (t->acquire_call) - return; + goto exit; } spa_list_for_each(t, &monitor->transport_list, link) { if (!transport_in_same_cig(transport, t)) @@ -4175,6 +4189,9 @@ finish: spa_bt_transport_set_state(t, SPA_BT_TRANSPORT_STATE_ACTIVE); } } + +exit: + transport_check_iso_ready(monitor); } static int do_transport_acquire(struct spa_bt_transport *transport) diff --git a/spa/plugins/bluez5/iso-io.c b/spa/plugins/bluez5/iso-io.c index aaae32600..02d74c2a7 100644 --- a/spa/plugins/bluez5/iso-io.c +++ b/spa/plugins/bluez5/iso-io.c @@ -80,6 +80,7 @@ struct stream { int fd; bool sink; bool idle; + bool ready; spa_bt_iso_io_pull_t pull; @@ -268,6 +269,11 @@ static void group_on_timeout(struct spa_source *source) if (!exp) return; + spa_list_for_each(stream, &group->streams, link) { + if (!stream->ready) + goto done; + } + spa_list_for_each(stream, &group->streams, link) { if (!stream->sink) { if (!stream->pull) { @@ -343,7 +349,7 @@ done: group->next += exp * group->duration_tx; spa_list_for_each(stream, &group->streams, link) { - if (!stream->sink) + if (!stream->sink || !stream->ready) continue; if (resync) @@ -576,6 +582,24 @@ void spa_bt_iso_io_destroy(struct spa_bt_iso_io *this) free(stream); } +static int do_ready(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) +{ + struct stream *stream = user_data; + + stream->ready = true; + return 0; +} + +void spa_bt_iso_io_ready(struct spa_bt_iso_io *this) +{ + struct stream *stream = SPA_CONTAINER_OF(this, struct stream, this); + struct group *group = stream->group; + int res; + + res = spa_loop_locked(group->data_loop, do_ready, 0, NULL, 0, stream); + spa_assert_se(res == 0); +} + static bool group_is_enabled(struct group *group) { struct stream *stream; diff --git a/spa/plugins/bluez5/iso-io.h b/spa/plugins/bluez5/iso-io.h index c59ebc075..a0082b420 100644 --- a/spa/plugins/bluez5/iso-io.h +++ b/spa/plugins/bluez5/iso-io.h @@ -47,6 +47,8 @@ void spa_bt_iso_io_destroy(struct spa_bt_iso_io *io); void spa_bt_iso_io_set_cb(struct spa_bt_iso_io *io, spa_bt_iso_io_pull_t pull, void *user_data); int spa_bt_iso_io_recv_errqueue(struct spa_bt_iso_io *io); +void spa_bt_iso_io_ready(struct spa_bt_iso_io *io); + void spa_bt_iso_io_set_source_buffer(struct spa_bt_iso_io *io, struct spa_bt_decode_buffer *buffer); int32_t spa_bt_iso_io_get_source_target_latency(struct spa_bt_iso_io *io); void spa_bt_iso_io_check_rx_sync(struct spa_bt_iso_io *io, uint64_t position);