From d11be520642119cdccd14efd976598bba85b2dff Mon Sep 17 00:00:00 2001 From: linruihao Date: Fri, 14 Mar 2025 17:13:55 +0800 Subject: [PATCH] feat(examples): Add kconfig option for a2dp_sink example to use new audio APIs --- .../a2dp_sink/main/Kconfig.projbuild | 7 +++ .../classic_bt/a2dp_sink/main/bt_app_av.c | 58 ++++++++++++++----- .../classic_bt/a2dp_sink/main/bt_app_av.h | 10 +++- .../classic_bt/a2dp_sink/main/main.c | 19 +++++- .../classic_bt/hfp_ag/main/bt_app_core.c | 2 +- 5 files changed, 79 insertions(+), 17 deletions(-) diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/Kconfig.projbuild b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/Kconfig.projbuild index c276f7282a..e627e8b5d1 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/Kconfig.projbuild +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/Kconfig.projbuild @@ -61,4 +61,11 @@ menu "A2DP Example Configuration" help This enables the AVRCP Cover Art feature in example and try to get cover art image from peer device. + config EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC + bool "Use External Codec Instead of Internal" + default n + select BT_A2DP_USE_EXTERNAL_CODEC + help + If enable, Bluedroid stack will not decode A2DP audio data, user need to decode it in application layer. + endmenu diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.c b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.c index 47c76babf2..a95e640def 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.c +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -321,21 +321,21 @@ static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param) /* when audio codec is configured, this event comes */ case ESP_A2D_AUDIO_CFG_EVT: { a2d = (esp_a2d_cb_param_t *)(p_param); - ESP_LOGI(BT_AV_TAG, "A2DP audio stream configuration, codec type: %d", a2d->audio_cfg.mcc.type); + esp_a2d_mcc_t *p_mcc = &a2d->audio_cfg.mcc; + ESP_LOGI(BT_AV_TAG, "A2DP audio stream configuration, codec type: %d", p_mcc->type); /* for now only SBC stream is supported */ - if (a2d->audio_cfg.mcc.type == ESP_A2D_MCT_SBC) { + if (p_mcc->type == ESP_A2D_MCT_SBC) { int sample_rate = 16000; int ch_count = 2; - char oct0 = a2d->audio_cfg.mcc.cie.sbc[0]; - if (oct0 & (0x01 << 6)) { + if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_32K) { sample_rate = 32000; - } else if (oct0 & (0x01 << 5)) { + } else if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_44K) { sample_rate = 44100; - } else if (oct0 & (0x01 << 4)) { + } else if (p_mcc->cie.sbc_info.samp_freq & ESP_A2D_SBC_CIE_SF_48K) { sample_rate = 48000; } - if (oct0 & (0x01 << 3)) { + if (p_mcc->cie.sbc_info.ch_mode & ESP_A2D_SBC_CIE_CH_MODE_MONO) { ch_count = 1; } #ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC @@ -362,11 +362,14 @@ static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param) i2s_channel_reconfig_std_slot(tx_chan, &slot_cfg); i2s_channel_enable(tx_chan); #endif - ESP_LOGI(BT_AV_TAG, "Configure audio player: %x-%x-%x-%x", - a2d->audio_cfg.mcc.cie.sbc[0], - a2d->audio_cfg.mcc.cie.sbc[1], - a2d->audio_cfg.mcc.cie.sbc[2], - a2d->audio_cfg.mcc.cie.sbc[3]); + ESP_LOGI(BT_AV_TAG, "Configure audio player: 0x%x-0x%x-0x%x-0x%x-0x%x-%d-%d", + p_mcc->cie.sbc_info.samp_freq, + p_mcc->cie.sbc_info.ch_mode, + p_mcc->cie.sbc_info.block_len, + p_mcc->cie.sbc_info.num_subbands, + p_mcc->cie.sbc_info.alloc_mthd, + p_mcc->cie.sbc_info.min_bitpool, + p_mcc->cie.sbc_info.max_bitpool); ESP_LOGI(BT_AV_TAG, "Audio player configured, sample rate: %d", sample_rate); } break; @@ -381,6 +384,17 @@ static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param) } break; } + /* when using external codec, after sep registration done, this event comes */ + case ESP_A2D_SEP_REG_STATE_EVT: { + a2d = (esp_a2d_cb_param_t *)(p_param); + if (a2d->a2d_sep_reg_stat.reg_state == ESP_A2D_SEP_REG_SUCCESS) { + ESP_LOGI(BT_AV_TAG, "A2DP register SEP success, seid: %d", a2d->a2d_sep_reg_stat.seid); + } + else { + ESP_LOGI(BT_AV_TAG, "A2DP register SEP fail, seid: %d, state: %d", a2d->a2d_sep_reg_stat.seid, a2d->a2d_sep_reg_stat.reg_state); + } + break; + } /* When protocol service capabilities configured, this event comes */ case ESP_A2D_SNK_PSC_CFG_EVT: { a2d = (esp_a2d_cb_param_t *)(p_param); @@ -591,6 +605,7 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) case ESP_A2D_AUDIO_STATE_EVT: case ESP_A2D_AUDIO_CFG_EVT: case ESP_A2D_PROF_STATE_EVT: + case ESP_A2D_SEP_REG_STATE_EVT: case ESP_A2D_SNK_PSC_CFG_EVT: case ESP_A2D_SNK_SET_DELAY_VALUE_EVT: case ESP_A2D_SNK_GET_DELAY_VALUE_EVT: { @@ -603,6 +618,8 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) } } +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE + void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) { write_ringbuf(data, len); @@ -613,6 +630,21 @@ void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) } } +#else + +void bt_app_a2d_audio_data_cb(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf) +{ + ESP_LOGI(BT_AV_TAG, "data_len: %d, number_frame: %d, ts: %lu", audio_buf->data_len, audio_buf->number_frame, audio_buf->timestamp); + + /* + * Normally, user should send the audio_buf to other task, decode and free audio buff, + * But the codec component is not merge into IDF now, so we just free audio data here + */ + esp_a2d_audio_buff_free(audio_buf); +} + +#endif + void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) { #if CONFIG_EXAMPLE_AVRCP_CT_COVER_ART_ENABLE diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.h b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.h index d0e6e6c789..50a2116627 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.h +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/bt_app_av.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -32,6 +32,14 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param); */ void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len); +/** + * @brief callback function for A2DP sink undecoded audio data + * + * @param [in] conn_hdl connection handle + * @param [in] audio_buf pointer to audio buff + */ +void bt_app_a2d_audio_data_cb(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf); + /** * @brief callback function for AVRCP controller * diff --git a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/main.c b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/main.c index ea9f4abf14..d4da955d2f 100644 --- a/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/main.c +++ b/examples/bluetooth/bluedroid/classic_bt/a2dp_sink/main/main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -164,8 +164,23 @@ static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) assert(esp_a2d_sink_init() == ESP_OK); esp_a2d_register_callback(&bt_app_a2d_cb); - esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); +#if CONFIG_EXAMPLE_A2DP_SINK_USE_EXTERNAL_CODEC == FALSE + esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); +#else + esp_a2d_mcc_t mcc = {0}; + mcc.type = ESP_A2D_MCT_SBC; + mcc.cie.sbc_info.samp_freq = 0xf; + mcc.cie.sbc_info.ch_mode = 0xf; + mcc.cie.sbc_info.block_len = 0xf; + mcc.cie.sbc_info.num_subbands = 0x3; + mcc.cie.sbc_info.alloc_mthd = 0x3; + mcc.cie.sbc_info.max_bitpool = 250; + mcc.cie.sbc_info.min_bitpool = 2; + /* register stream end point, only support mSBC currently */ + esp_a2d_sink_register_stream_endpoint(0, &mcc); + esp_a2d_sink_register_audio_data_callback(bt_app_a2d_audio_data_cb); +#endif /* Get the default value of the delay value */ esp_a2d_sink_get_delay_value(); /* Get local device name */ diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c index c1b8ba81b8..2b8821a567 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c @@ -92,7 +92,7 @@ static void bt_app_task_handler(void *arg) void bt_app_task_start_up(void) { bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t)); - xTaskCreate(bt_app_task_handler, "BtAppT", 2048, NULL, configMAX_PRIORITIES - 3, &bt_app_task_handle); + xTaskCreate(bt_app_task_handler, "BtAppT", 4096, NULL, configMAX_PRIORITIES - 3, &bt_app_task_handle); return; }