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.
This commit is contained in:
Pauli Virtanen 2025-12-21 15:07:16 +02:00 committed by Wim Taymans
parent 8b36e2d9b7
commit ac3ac3382b
3 changed files with 49 additions and 6 deletions

View file

@ -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)

View file

@ -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;

View file

@ -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);