diff --git a/spa/plugins/bluez5/bap-codec-lc3.c b/spa/plugins/bluez5/bap-codec-lc3.c index 3e4a0c091..66a5902a7 100644 --- a/spa/plugins/bluez5/bap-codec-lc3.c +++ b/spa/plugins/bluez5/bap-codec-lc3.c @@ -1008,6 +1008,13 @@ static int codec_get_block_size(void *data) return this->codesize; } +static uint64_t codec_get_interval(void *data) +{ + struct impl *this = data; + + return (uint64_t)this->frame_dus * 1000; +} + static int codec_abr_process (void *data, size_t unsent) { return -ENOTSUP; @@ -1120,6 +1127,7 @@ const struct media_codec bap_codec_lc3 = { .init = codec_init, .deinit = codec_deinit, .get_block_size = codec_get_block_size, + .get_interval = codec_get_interval, .abr_process = codec_abr_process, .start_encode = codec_start_encode, .encode = codec_encode, diff --git a/spa/plugins/bluez5/bluez5-dbus.c b/spa/plugins/bluez5/bluez5-dbus.c index fdea5bda7..aca2c75eb 100644 --- a/spa/plugins/bluez5/bluez5-dbus.c +++ b/spa/plugins/bluez5/bluez5-dbus.c @@ -3357,7 +3357,6 @@ static int transport_update_props(struct spa_bt_transport *transport, transport->bap_bis = qos.bis; transport->delay_us = qos.qos.delay; transport->latency_us = (unsigned int)qos.qos.latency * 1000; - transport->bap_interval = qos.qos.interval; spa_bt_transport_emit_delay_changed(transport); } diff --git a/spa/plugins/bluez5/defs.h b/spa/plugins/bluez5/defs.h index 298376f4a..a797073ec 100644 --- a/spa/plugins/bluez5/defs.h +++ b/spa/plugins/bluez5/defs.h @@ -659,7 +659,6 @@ struct spa_bt_transport { uint8_t bap_cis; uint8_t bap_big; uint8_t bap_bis; - uint32_t bap_interval; struct spa_bt_iso_io *iso_io; struct spa_bt_sco_io *sco_io; diff --git a/spa/plugins/bluez5/iso-io.c b/spa/plugins/bluez5/iso-io.c index f70486829..6b1e7378f 100644 --- a/spa/plugins/bluez5/iso-io.c +++ b/spa/plugins/bluez5/iso-io.c @@ -135,6 +135,9 @@ static int set_timers(struct group *group) { struct timespec now; + if (group->duration == 0) + return -EINVAL; + spa_system_clock_gettime(group->data_system, CLOCK_MONOTONIC, &now); group->next = SPA_ROUND_UP(SPA_TIMESPEC_TO_NSEC(&now) + group->duration, group->duration); @@ -244,11 +247,6 @@ static struct group *group_create(struct spa_bt_transport *t, struct group *group; uint8_t id; - if (t->bap_interval <= 5000) { - errno = EINVAL; - return NULL; - } - if (t->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE)) { id = t->bap_cig; } else if (t->profile & (SPA_BT_PROFILE_BAP_BROADCAST_SINK | SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { @@ -268,7 +266,7 @@ static struct group *group_create(struct spa_bt_transport *t, group->log = log; group->data_loop = data_loop; group->data_system = data_system; - group->duration = t->bap_interval * SPA_NSEC_PER_USEC; + group->duration = 0; spa_list_init(&group->streams); @@ -325,20 +323,22 @@ static struct stream *stream_create(struct spa_bt_transport *t, struct group *gr struct spa_audio_info format = { 0 }; int res; bool sink; - if((t->profile == SPA_BT_PROFILE_BAP_SINK) || - (t->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK)) { + + if (t->profile == SPA_BT_PROFILE_BAP_SINK || + t->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) { sink = true; } else { sink = false; } - - if (!t->media_codec->bap) { + if (!t->media_codec->bap || !t->media_codec->get_interval) { res = -EINVAL; goto fail; } if (sink) { + uint64_t interval; + res = t->media_codec->validate_config(t->media_codec, 0, t->configuration, t->configuration_len, &format); if (res < 0) goto fail; @@ -355,6 +355,20 @@ static struct stream *stream_create(struct spa_bt_transport *t, struct group *gr res = -EINVAL; goto fail; } + + interval = t->media_codec->get_interval(codec_data); + if (interval <= 5000) { + res = -EINVAL; + goto fail; + } + + if (group->duration == 0) { + group->duration = interval; + } else if (interval != group->duration) { + /* SDU_Interval in ISO group must be same for each direction */ + res = -EINVAL; + goto fail; + } } stream = calloc(1, sizeof(struct stream)); @@ -364,7 +378,7 @@ static struct stream *stream_create(struct spa_bt_transport *t, struct group *gr stream->fd = t->fd; stream->sink = sink; stream->group = group; - stream->this.duration = group->duration; + stream->this.duration = sink ? group->duration : 0; stream->codec = t->media_codec; stream->this.codec_data = codec_data; @@ -452,6 +466,9 @@ void spa_bt_iso_io_set_cb(struct spa_bt_iso_io *this, spa_bt_iso_io_pull_t pull, struct stream *stream = SPA_CONTAINER_OF(this, struct stream, this); bool was_enabled, enabled; + if (!stream->sink) + return; + was_enabled = group_is_enabled(stream->group); stream->pull = pull; diff --git a/spa/plugins/bluez5/media-codecs.h b/spa/plugins/bluez5/media-codecs.h index 7d7df5246..5084bfc72 100644 --- a/spa/plugins/bluez5/media-codecs.h +++ b/spa/plugins/bluez5/media-codecs.h @@ -26,7 +26,7 @@ #define SPA_TYPE_INTERFACE_Bluez5CodecMedia SPA_TYPE_INFO_INTERFACE_BASE "Bluez5:Codec:Media:Private" -#define SPA_VERSION_BLUEZ5_CODEC_MEDIA 7 +#define SPA_VERSION_BLUEZ5_CODEC_MEDIA 8 struct spa_bluez5_codec_a2dp { struct spa_interface iface; @@ -81,8 +81,6 @@ struct media_codec { const struct media_codec *duplex_codec; /**< Codec for non-standard A2DP duplex channel */ - struct spa_log *log; - /** If fill_caps is NULL, no endpoint is registered (for sharing with another codec). */ int (*fill_caps) (const struct media_codec *codec, uint32_t flags, uint8_t caps[A2DP_MAX_CAPS_SIZE]); @@ -126,6 +124,16 @@ struct media_codec { /** Number of bytes needed for encoding */ int (*get_block_size) (void *data); + /** + * Duration of the next packet in nanoseconds. + * + * For BAP this shall be constant and equal to the SDU interval. + * + * \param data Codec data from init() + * \return Duration in nanoseconds. + */ + uint64_t (*get_interval) (void *data); + int (*abr_process) (void *data, size_t unsent); /**