Bluetooth: Audio: Add broadcast source metadata update function
Add API to do the BAP Broadcast Source Metadata update procedure, which updates the metadata of a broadcast source while it is streaming. This is also makes all checks for the "head stream" the same. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
302ec9fa37
commit
1424df424c
4 changed files with 128 additions and 1 deletions
|
@ -2077,7 +2077,7 @@ int bt_audio_broadcast_source_create(struct bt_audio_broadcast_source_create_par
|
||||||
/** @brief Reconfigure audio broadcast source.
|
/** @brief Reconfigure audio broadcast source.
|
||||||
*
|
*
|
||||||
* Reconfigure an audio broadcast source with a new codec and codec quality of
|
* Reconfigure an audio broadcast source with a new codec and codec quality of
|
||||||
* service parameters.
|
* service parameters. This can only be done when the source is stopped.
|
||||||
*
|
*
|
||||||
* @param source Pointer to the broadcast source
|
* @param source Pointer to the broadcast source
|
||||||
* @param codec Codec configuration.
|
* @param codec Codec configuration.
|
||||||
|
@ -2089,6 +2089,22 @@ int bt_audio_broadcast_source_reconfig(struct bt_audio_broadcast_source *source,
|
||||||
struct bt_codec *codec,
|
struct bt_codec *codec,
|
||||||
struct bt_codec_qos *qos);
|
struct bt_codec_qos *qos);
|
||||||
|
|
||||||
|
/** @brief Modify the metadata of an audio broadcast source.
|
||||||
|
*
|
||||||
|
* Modify the metadata an audio broadcast source. This can only be done when
|
||||||
|
* the source is started. To update the metadata in the stopped state, use
|
||||||
|
* bt_audio_broadcast_source_reconfig().
|
||||||
|
*
|
||||||
|
* @param source Pointer to the broadcast source.
|
||||||
|
* @param meta Metadata entries.
|
||||||
|
* @param meta_count Number of metadata entries.
|
||||||
|
*
|
||||||
|
* @return Zero on success or (negative) error code otherwise.
|
||||||
|
*/
|
||||||
|
int bt_audio_broadcast_source_update_metadata(struct bt_audio_broadcast_source *source,
|
||||||
|
const struct bt_codec_data meta[],
|
||||||
|
size_t meta_count);
|
||||||
|
|
||||||
/** @brief Start audio broadcast source.
|
/** @brief Start audio broadcast source.
|
||||||
*
|
*
|
||||||
* Start an audio broadcast source with one or more audio streams.
|
* Start an audio broadcast source with one or more audio streams.
|
||||||
|
|
|
@ -765,6 +765,81 @@ int bt_audio_broadcast_source_reconfig(struct bt_audio_broadcast_source *source,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void broadcast_source_store_metadata(struct bt_codec *codec,
|
||||||
|
const struct bt_codec_data meta[],
|
||||||
|
size_t meta_count)
|
||||||
|
{
|
||||||
|
size_t old_meta_count;
|
||||||
|
|
||||||
|
old_meta_count = codec->meta_count;
|
||||||
|
|
||||||
|
/* Update metadata */
|
||||||
|
codec->meta_count = meta_count;
|
||||||
|
(void)memcpy(codec->meta, meta, meta_count * sizeof(*meta));
|
||||||
|
if (old_meta_count > meta_count) {
|
||||||
|
size_t meta_count_diff = old_meta_count - meta_count;
|
||||||
|
|
||||||
|
/* If we previously had more metadata entries we reset the
|
||||||
|
* data that was not overwritten by the new metadata
|
||||||
|
*/
|
||||||
|
(void)memset(&codec->meta[meta_count],
|
||||||
|
0, meta_count_diff * sizeof(*meta));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int bt_audio_broadcast_source_update_metadata(struct bt_audio_broadcast_source *source,
|
||||||
|
const struct bt_codec_data meta[],
|
||||||
|
size_t meta_count)
|
||||||
|
{
|
||||||
|
struct bt_audio_broadcast_subgroup *subgroup;
|
||||||
|
enum bt_audio_state broadcast_state;
|
||||||
|
|
||||||
|
CHECKIF(source == NULL) {
|
||||||
|
LOG_DBG("source is NULL");
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECKIF((meta == NULL && meta_count != 0) ||
|
||||||
|
(meta != NULL && meta_count == 0)) {
|
||||||
|
LOG_DBG("Invalid metadata combination: %p %zu",
|
||||||
|
meta, meta_count);
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECKIF(meta_count > CONFIG_BT_CODEC_MAX_METADATA_COUNT) {
|
||||||
|
LOG_DBG("Invalid meta_count: %zu (max %d)",
|
||||||
|
meta_count, CONFIG_BT_CODEC_MAX_METADATA_COUNT);
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < meta_count; i++) {
|
||||||
|
CHECKIF(meta[i].data.data_len > sizeof(meta[i].value)) {
|
||||||
|
LOG_DBG("Invalid meta[%zu] data_len %u",
|
||||||
|
i, meta[i].data.data_len);
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
broadcast_state = broadcast_source_get_state(source);
|
||||||
|
if (broadcast_source_get_state(source) != BT_AUDIO_EP_STATE_STREAMING) {
|
||||||
|
LOG_DBG("Broadcast source invalid state: %u", broadcast_state);
|
||||||
|
|
||||||
|
return -EBADMSG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: We should probably find a way to update the metadata
|
||||||
|
* for each subgroup individually
|
||||||
|
*/
|
||||||
|
SYS_SLIST_FOR_EACH_CONTAINER(&source->subgroups, subgroup, _node) {
|
||||||
|
broadcast_source_store_metadata(subgroup->codec, meta, meta_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int bt_audio_broadcast_source_start(struct bt_audio_broadcast_source *source,
|
int bt_audio_broadcast_source_start(struct bt_audio_broadcast_source *source,
|
||||||
struct bt_le_ext_adv *adv)
|
struct bt_le_ext_adv *adv)
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,6 +15,7 @@ extern enum bst_result_t bst_result;
|
||||||
|
|
||||||
CREATE_FLAG(broadcaster_found);
|
CREATE_FLAG(broadcaster_found);
|
||||||
CREATE_FLAG(base_received);
|
CREATE_FLAG(base_received);
|
||||||
|
CREATE_FLAG(flag_base_metadata_updated);
|
||||||
CREATE_FLAG(pa_synced);
|
CREATE_FLAG(pa_synced);
|
||||||
CREATE_FLAG(flag_syncable);
|
CREATE_FLAG(flag_syncable);
|
||||||
CREATE_FLAG(pa_sync_lost);
|
CREATE_FLAG(pa_sync_lost);
|
||||||
|
@ -30,6 +31,8 @@ static struct bt_audio_lc3_preset preset_16_2_1 =
|
||||||
static K_SEM_DEFINE(sem_started, 0U, ARRAY_SIZE(streams));
|
static K_SEM_DEFINE(sem_started, 0U, ARRAY_SIZE(streams));
|
||||||
static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams));
|
static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams));
|
||||||
|
|
||||||
|
static struct bt_codec_data metadata[CONFIG_BT_CODEC_MAX_METADATA_COUNT];
|
||||||
|
|
||||||
/* Create a mask for the maximum BIS we can sync to using the number of streams
|
/* Create a mask for the maximum BIS we can sync to using the number of streams
|
||||||
* we have. We add an additional 1 since the bis indexes start from 1 and not
|
* we have. We add an additional 1 since the bis indexes start from 1 and not
|
||||||
* 0.
|
* 0.
|
||||||
|
@ -76,6 +79,17 @@ static void base_recv_cb(struct bt_audio_broadcast_sink *sink,
|
||||||
uint32_t base_bis_index_bitfield = 0U;
|
uint32_t base_bis_index_bitfield = 0U;
|
||||||
|
|
||||||
if (TEST_FLAG(base_received)) {
|
if (TEST_FLAG(base_received)) {
|
||||||
|
|
||||||
|
if (base->subgroup_count > 0 &&
|
||||||
|
memcmp(metadata, base->subgroups[0].codec.meta,
|
||||||
|
sizeof(base->subgroups[0].codec.meta)) != 0) {
|
||||||
|
|
||||||
|
(void)memcpy(metadata, base->subgroups[0].codec.meta,
|
||||||
|
sizeof(base->subgroups[0].codec.meta));
|
||||||
|
|
||||||
|
SET_FLAG(flag_base_metadata_updated);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +249,10 @@ static void test_main(void)
|
||||||
printk("Waiting for data\n");
|
printk("Waiting for data\n");
|
||||||
WAIT_FOR_FLAG(flag_received);
|
WAIT_FOR_FLAG(flag_received);
|
||||||
|
|
||||||
|
/* Ensure that we also see the metadata update */
|
||||||
|
printk("Waiting for metadata update\n");
|
||||||
|
WAIT_FOR_FLAG(flag_base_metadata_updated)
|
||||||
|
|
||||||
/* The order of PA sync lost and BIG Sync lost is irrelevant
|
/* The order of PA sync lost and BIG Sync lost is irrelevant
|
||||||
* and depend on timeout parameters. We just wait for PA first, but
|
* and depend on timeout parameters. We just wait for PA first, but
|
||||||
* either way will work.
|
* either way will work.
|
||||||
|
@ -293,6 +311,10 @@ static void test_sink_disconnect(void)
|
||||||
printk("Waiting for data\n");
|
printk("Waiting for data\n");
|
||||||
WAIT_FOR_FLAG(flag_received);
|
WAIT_FOR_FLAG(flag_received);
|
||||||
|
|
||||||
|
/* Ensure that we also see the metadata update */
|
||||||
|
printk("Waiting for metadata update\n");
|
||||||
|
WAIT_FOR_FLAG(flag_base_metadata_updated)
|
||||||
|
|
||||||
err = bt_audio_broadcast_sink_stop(g_sink);
|
err = bt_audio_broadcast_sink_stop(g_sink);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
FAIL("Unable to stop sink: %d", err);
|
FAIL("Unable to stop sink: %d", err);
|
||||||
|
|
|
@ -244,6 +244,8 @@ static int stop_extended_adv(struct bt_le_ext_adv *adv)
|
||||||
|
|
||||||
static void test_main(void)
|
static void test_main(void)
|
||||||
{
|
{
|
||||||
|
struct bt_codec_data new_metadata[1] =
|
||||||
|
BT_CODEC_LC3_CONFIG_META(BT_AUDIO_CONTEXT_TYPE_ALERTS);
|
||||||
struct bt_audio_broadcast_source *source;
|
struct bt_audio_broadcast_source *source;
|
||||||
struct bt_le_ext_adv *adv;
|
struct bt_le_ext_adv *adv;
|
||||||
int err;
|
int err;
|
||||||
|
@ -299,6 +301,18 @@ static void test_main(void)
|
||||||
/* Keeping running for a little while */
|
/* Keeping running for a little while */
|
||||||
k_sleep(K_SECONDS(15));
|
k_sleep(K_SECONDS(15));
|
||||||
|
|
||||||
|
/* Update metadata while streaming */
|
||||||
|
printk("Updating metadata\n");
|
||||||
|
err = bt_audio_broadcast_source_update_metadata(source, new_metadata,
|
||||||
|
ARRAY_SIZE(new_metadata));
|
||||||
|
if (err != 0) {
|
||||||
|
FAIL("Failed to update metadata broadcast source: %d", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keeping running for a little while */
|
||||||
|
k_sleep(K_SECONDS(5));
|
||||||
|
|
||||||
printk("Stopping broadcast source\n");
|
printk("Stopping broadcast source\n");
|
||||||
SET_FLAG(flag_stopping);
|
SET_FLAG(flag_stopping);
|
||||||
err = bt_audio_broadcast_source_stop(source);
|
err = bt_audio_broadcast_source_stop(source);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue