From 01ebc9920f34cb0a26d3487b424afbc84e5aa780 Mon Sep 17 00:00:00 2001 From: Graham Wacey Date: Tue, 23 Apr 2024 22:40:01 +0100 Subject: [PATCH] applications: nrf5340_audio: Rail the presentation delay. Ensure the preferred presentation delay is within the range of the min and max delays, rail if not. Search for the presentation delay function updated to search over the end points for the direction. Signed-off-by: Graham Wacey --- applications/nrf5340_audio/src/audio/Kconfig | 23 ++---- .../src/bluetooth/bt_stream/le_audio.c | 26 +++++++ .../src/bluetooth/bt_stream/le_audio.h | 11 +++ .../bt_stream/unicast/unicast_client.c | 74 +++++++++++++------ 4 files changed, 93 insertions(+), 41 deletions(-) diff --git a/applications/nrf5340_audio/src/audio/Kconfig b/applications/nrf5340_audio/src/audio/Kconfig index 8d9665091333..51f02db97fa5 100644 --- a/applications/nrf5340_audio/src/audio/Kconfig +++ b/applications/nrf5340_audio/src/audio/Kconfig @@ -34,14 +34,16 @@ config AUDIO_MIN_PRES_DLY_US int "The minimum presentation delay" default 4000 help - The minimum presentation delay in micro seconds determined by - the audio system processing and the minimum buffering. + The minimum allowable presentation delay in microseconds. + This needs to allow time for decoding and internal routing. + For 48kHz sampling rate and 96kbps bitrate this is about 4000 us. config AUDIO_MAX_PRES_DLY_US int "The maximum presentation delay" default 60000 help - The maximum presentation delay in micro seconds. + The maximum allowable presentation delay in microseconds. + Increasing this will also increase the FIFO buffers to allow buffering. choice AUDIO_SYSTEM_SAMPLE_RATE prompt "System audio sample rate" @@ -108,21 +110,6 @@ config AUDIO_BIT_DEPTH_OCTETS help Bit depth of one sample in storage given in octets. -config AUDIO_MIN_PRES_DLY_US - int "The minimum presentation delay" - default 4000 - help - The minimum allowable presentation delay in microseconds. - This needs to allow time for decoding and internal routing. - For 48kHz sampling rate and 96kbps bitrate this is about 4000 us. - -config AUDIO_MAX_PRES_DLY_US - int "The maximum presentation delay" - default 60000 - help - The maximum allowable presentation delay in microseconds. - Increasing this will also increase the FIFO buffers to allow buffering. - choice AUDIO_SOURCE_GATEWAY prompt "Audio source for gateway" default AUDIO_SOURCE_I2S if WALKIE_TALKIE_DEMO diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.c b/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.c index 6d03b400cb04..bf38c5b90e01 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.c @@ -36,6 +36,32 @@ bool le_audio_ep_state_check(struct bt_bap_ep *ep, enum bt_bap_ep_state state) return false; } +bool le_audio_ep_qos_configured(struct bt_bap_ep *ep) +{ + int ret; + struct bt_bap_ep_info ep_info; + + if (ep == NULL) { + LOG_DBG("EP is NULL"); + /* If an endpoint is NULL it is not in any of the states */ + return false; + } + + ret = bt_bap_ep_get_info(ep, &ep_info); + if (ret) { + LOG_WRN("Unable to get info for ep"); + return false; + } + + if (ep_info.state == BT_BAP_EP_STATE_IDLE || + ep_info.state == BT_BAP_EP_STATE_CODEC_CONFIGURED || + ep_info.state == BT_BAP_EP_STATE_RELEASING) { + return false; + } + + return true; +} + int le_audio_freq_hz_get(const struct bt_audio_codec_cfg *codec, int *freq_hz) { int ret; diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.h b/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.h index 3cdfc8d4dd2d..981db0ef756a 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.h +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/le_audio.h @@ -79,6 +79,17 @@ struct le_audio_encoded_audio { */ bool le_audio_ep_state_check(struct bt_bap_ep *ep, enum bt_bap_ep_state state); +/** + * @brief Check if an endpoint has had the QoS configured. + * If the endpoint is NULL, it is not in the state, and this function returns false. + * + * @param[in] ep The endpoint to check. + * + * @retval true The endpoint QoS is configured. + * @retval false Otherwise. + */ +bool le_audio_ep_qos_configured(struct bt_bap_ep *ep); + /** * @brief Decode the audio sampling frequency in the codec configuration. * diff --git a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.c b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.c index 3baef5fdcdb6..492ced0148c4 100644 --- a/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.c +++ b/applications/nrf5340_audio/src/bluetooth/bt_stream/unicast/unicast_client.c @@ -144,54 +144,78 @@ static void le_audio_event_publish(enum le_audio_evt_type event, struct bt_conn */ static int headset_pres_delay_find(uint8_t index, uint32_t *pres_dly_us) { - uint32_t pres_dly_min = headsets[index].sink_ep->qos_pref.pd_min; - uint32_t pres_dly_max = headsets[index].sink_ep->qos_pref.pd_max; - uint32_t pref_dly_min = headsets[index].sink_ep->qos_pref.pref_pd_min; - uint32_t pref_dly_max = headsets[index].sink_ep->qos_pref.pref_pd_max; + uint32_t pd_min = headsets[index].sink_ep->qos_pref.pd_min; + uint32_t pd_max = headsets[index].sink_ep->qos_pref.pd_max; + uint32_t pref_pd_min = headsets[index].sink_ep->qos_pref.pref_pd_min; + uint32_t pref_pd_max = headsets[index].sink_ep->qos_pref.pref_pd_max; LOG_DBG("Index: %d, Pref min: %d, pref max: %d, pres_min: %d, pres_max: %d", index, - pref_dly_min, pref_dly_max, pres_dly_min, pres_dly_max); + headsets[index].sink_ep->qos_pref.pd_min, + headsets[index].sink_ep->qos_pref.pref_pd_max, + headsets[index].sink_ep->qos_pref.pd_min, headsets[index].sink_ep->qos_pref.pd_max); + + *pres_dly_us = 0; for (int i = 0; i < ARRAY_SIZE(headsets); i++) { - if (headsets[i].sink_ep != NULL) { - pres_dly_min = MAX(pres_dly_min, headsets[i].sink_ep->qos_pref.pd_min); - pres_dly_max = MIN(pres_dly_max, headsets[i].sink_ep->qos_pref.pd_max); - pref_dly_min = MAX(pref_dly_min, headsets[i].sink_ep->qos_pref.pref_pd_min); - pref_dly_max = MIN(pref_dly_max, headsets[i].sink_ep->qos_pref.pref_pd_max); + if (le_audio_ep_qos_configured(headsets[i].sink_ep)) { + LOG_DBG("i: %d, Pref min: %d, pref max: %d, pres_min: %d, pres_max: %d", i, + headsets[i].sink_ep->qos_pref.pd_min, + headsets[i].sink_ep->qos_pref.pref_pd_max, + headsets[i].sink_ep->qos_pref.pd_min, + headsets[i].sink_ep->qos_pref.pd_max); + + pd_min = MAX(pd_min, headsets[i].sink_ep->qos_pref.pd_min); + pref_pd_min = MAX(pref_pd_min, headsets[i].sink_ep->qos_pref.pref_pd_min); + + if (headsets[i].sink_ep->qos_pref.pd_max) { + pd_max = MIN(pd_max, headsets[i].sink_ep->qos_pref.pd_max); + } + + if (headsets[i].sink_ep->qos_pref.pref_pd_max) { + pref_pd_max = + MIN(pref_pd_max, headsets[i].sink_ep->qos_pref.pref_pd_max); + } } } if (IS_ENABLED(CONFIG_BT_AUDIO_PRES_DELAY_SRCH_MIN)) { - *pres_dly_us = pres_dly_min; + *pres_dly_us = pd_min; return 0; } if (IS_ENABLED(CONFIG_BT_AUDIO_PRES_DELAY_SRCH_MAX)) { - *pres_dly_us = pres_dly_max; + *pres_dly_us = pd_max; return 0; } if (IS_ENABLED(CONFIG_BT_AUDIO_PRES_DELAY_SRCH_PREF_MIN)) { - /* Preferred min is 0, so we set min supported */ - if (pref_dly_min == 0) { - *pres_dly_us = pres_dly_min; + if (pref_pd_min == 0 || pref_pd_min < pd_min) { + *pres_dly_us = pd_min; + } else if (pref_pd_min <= pd_max) { + *pres_dly_us = pref_pd_min; } else { - *pres_dly_us = pref_dly_min; + LOG_ERR("Min pref delay, %d, greater than max pres delay, %d", pref_pd_min, + pd_max); + + return -ENOTSUP; } return 0; } if (IS_ENABLED(CONFIG_BT_AUDIO_PRES_DELAY_SRCH_PREF_MAX)) { - /* Preferred max is 0, so we set max supported */ - if (pref_dly_max == 0) { - *pres_dly_us = pres_dly_max; + if (pref_pd_max == 0 || pref_pd_max > pd_max) { + *pres_dly_us = pd_max; + } else if (pref_pd_max >= pd_min) { + *pres_dly_us = pref_pd_max; } else { - *pres_dly_us = pref_dly_max; - } + LOG_ERR("Max pref delay, %d, is less than min pres delay, %d", pref_pd_max, + pd_min); + return -ENOTSUP; + } return 0; } @@ -932,6 +956,9 @@ static void stream_configured_cb(struct bt_bap_stream *stream, LOG_INF("%s sink stream configured", headsets[channel_index].ch_name); le_audio_print_codec(headsets[channel_index].sink_stream.codec_cfg, stream->ep->dir); + LOG_DBG("Configured Stream info: %s, %p, dir %d", headsets[channel_index].ch_name, + (void *)stream, stream->ep->dir); + } else if (stream->ep->dir == BT_AUDIO_DIR_SOURCE) { LOG_INF("%s source stream configured", headsets[channel_index].ch_name); le_audio_print_codec(headsets[channel_index].source_stream.codec_cfg, @@ -940,8 +967,6 @@ static void stream_configured_cb(struct bt_bap_stream *stream, LOG_WRN("Endpoint direction not recognized: %d", stream->ep->dir); return; } - LOG_DBG("Configured Stream info: %s, %p, dir %d", headsets[channel_index].ch_name, - (void *)stream, stream->ep->dir); ret = headset_pres_delay_find(channel_index, &new_pres_dly_us); if (ret) { @@ -949,6 +974,9 @@ static void stream_configured_cb(struct bt_bap_stream *stream, return; } + LOG_INF("Presentation delay for %s set at %d us", headsets[channel_index].ch_name, + new_pres_dly_us); + if (headsets[channel_index].waiting_for_source_disc) { return; }