Skip to content

Commit 96244e0

Browse files
author
Jiang Jiang Jian
committed
Merge branch 'feature/bt_support_external_codec' into 'master'
feat(bt/bluedroid): Support external codec in Bluedroid HFP and A2DP Closes BT-3937 See merge request espressif/esp-idf!36607
2 parents c3a3cc8 + a5f620e commit 96244e0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+3693
-503
lines changed

components/bt/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,9 @@ if(CONFIG_BT_ENABLED)
288288
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp.c"
289289
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c"
290290
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c"
291+
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink_ext_coedc.c"
291292
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c"
293+
"host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source_ext_codec.c"
292294
"host/bluedroid/btc/profile/std/a2dp/btc_av.c"
293295
"host/bluedroid/btc/profile/std/avrc/btc_avrc.c"
294296
"host/bluedroid/btc/profile/std/avrc/bta_avrc_co.c"

components/bt/host/bluedroid/Kconfig.in

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,15 @@ config BT_A2DP_ENABLE
8989
help
9090
Advanced Audio Distribution Profile
9191

92+
config BT_A2DP_USE_EXTERNAL_CODEC
93+
bool "Use External Codec for A2DP"
94+
depends on BT_A2DP_ENABLE
95+
default n
96+
help
97+
If enable, user shall register audio codec capability to A2DP and encode/decode
98+
audio data in application layer. The internal codec in A2DP will be remove in
99+
the future, it is recommend to use external codec for new design.
100+
92101
config BT_AVRCP_ENABLED
93102
bool
94103
depends on BT_A2DP_ENABLE
@@ -184,6 +193,15 @@ choice BT_HFP_AUDIO_DATA_PATH
184193
bool "HCI"
185194
endchoice
186195

196+
config BT_HFP_USE_EXTERNAL_CODEC
197+
bool "Use External Codec for HFP"
198+
depends on BT_HFP_ENABLE && BT_HFP_AUDIO_DATA_PATH_HCI
199+
default n
200+
help
201+
If enable, user shall encode/decode audio data in application layer. The internal
202+
codec in HFP will be remove in the future, it is recommend to use external codec
203+
for new design.
204+
187205
config BT_HFP_WBS_ENABLE
188206
bool "Wide Band Speech"
189207
depends on BT_HFP_ENABLE && BT_HFP_AUDIO_DATA_PATH_HCI

components/bt/host/bluedroid/api/esp_a2dp_api.c

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -14,6 +14,37 @@
1414

1515
#if BTC_AV_INCLUDED
1616

17+
esp_a2d_audio_buff_t *esp_a2d_audio_buff_alloc(uint16_t size)
18+
{
19+
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
20+
return NULL;
21+
}
22+
23+
if (size == 0) {
24+
return NULL;
25+
}
26+
27+
uint8_t *p_buf = NULL, *p_data;
28+
btc_av_audio_buff_alloc(size, &p_buf, &p_data);
29+
if (p_buf == NULL) {
30+
return NULL;
31+
}
32+
33+
esp_a2d_audio_buff_t *audio_buf = (esp_a2d_audio_buff_t *)p_buf;
34+
audio_buf->buff_size = size;
35+
audio_buf->data_len = 0;
36+
audio_buf->data = p_data;
37+
return audio_buf;
38+
}
39+
40+
void esp_a2d_audio_buff_free(esp_a2d_audio_buff_t *audio_buf)
41+
{
42+
if (audio_buf == NULL) {
43+
return;
44+
}
45+
btc_av_audio_buff_free((uint8_t *)audio_buf);
46+
}
47+
1748
#if BTC_AV_SINK_INCLUDED
1849
esp_err_t esp_a2d_sink_init(void)
1950
{
@@ -36,6 +67,35 @@ esp_err_t esp_a2d_sink_init(void)
3667
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
3768
}
3869

70+
esp_err_t esp_a2d_sink_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_t *mcc)
71+
{
72+
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
73+
return ESP_ERR_INVALID_STATE;
74+
}
75+
76+
if (g_a2dp_on_deinit || g_a2dp_sink_ongoing_deinit) {
77+
return ESP_ERR_INVALID_STATE;
78+
}
79+
80+
if (seid >= ESP_A2D_MAX_SEPS) {
81+
return ESP_ERR_INVALID_ARG;
82+
}
83+
84+
btc_msg_t msg;
85+
msg.sig = BTC_SIG_API_CALL;
86+
msg.pid = BTC_PID_A2DP;
87+
msg.act = BTC_AV_SINK_API_REG_SEP_EVT;
88+
89+
btc_av_args_t arg;
90+
memset(&arg, 0, sizeof(btc_av_args_t));
91+
arg.reg_sep.seid = seid;
92+
memcpy(&arg.reg_sep.mcc, mcc, sizeof(esp_a2d_mcc_t));
93+
94+
/* Switch to BTC context */
95+
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL);
96+
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
97+
}
98+
3999
esp_err_t esp_a2d_sink_deinit(void)
40100
{
41101
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
@@ -81,6 +141,30 @@ esp_err_t esp_a2d_sink_register_data_callback(esp_a2d_sink_data_cb_t callback)
81141
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
82142
}
83143

144+
esp_err_t esp_a2d_sink_register_audio_data_callback(esp_a2d_sink_audio_data_cb_t callback)
145+
{
146+
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
147+
return ESP_ERR_INVALID_STATE;
148+
}
149+
150+
if (g_a2dp_sink_ongoing_deinit) {
151+
return ESP_ERR_INVALID_STATE;
152+
}
153+
154+
btc_msg_t msg;
155+
msg.sig = BTC_SIG_API_CALL;
156+
msg.pid = BTC_PID_A2DP;
157+
msg.act = BTC_AV_SINK_API_REG_AUDIO_DATA_CB_EVT;
158+
159+
btc_av_args_t arg;
160+
memset(&arg, 0, sizeof(btc_av_args_t));
161+
arg.audio_data_cb = callback;
162+
163+
/* Switch to BTC context */
164+
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL);
165+
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
166+
}
167+
84168
esp_err_t esp_a2d_sink_connect(esp_bd_addr_t remote_bda)
85169
{
86170
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
@@ -251,6 +335,35 @@ esp_err_t esp_a2d_source_init(void)
251335
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
252336
}
253337

338+
esp_err_t esp_a2d_source_register_stream_endpoint(uint8_t seid, const esp_a2d_mcc_t *mcc)
339+
{
340+
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
341+
return ESP_ERR_INVALID_STATE;
342+
}
343+
344+
if (g_a2dp_on_deinit || g_a2dp_sink_ongoing_deinit) {
345+
return ESP_ERR_INVALID_STATE;
346+
}
347+
348+
if (seid >= ESP_A2D_MAX_SEPS) {
349+
return ESP_ERR_INVALID_ARG;
350+
}
351+
352+
btc_msg_t msg;
353+
msg.sig = BTC_SIG_API_CALL;
354+
msg.pid = BTC_PID_A2DP;
355+
msg.act = BTC_AV_SRC_API_REG_SEP_EVT;
356+
357+
btc_av_args_t arg;
358+
memset(&arg, 0, sizeof(btc_av_args_t));
359+
arg.reg_sep.seid = seid;
360+
memcpy(&arg.reg_sep.mcc, mcc, sizeof(esp_a2d_mcc_t));
361+
362+
/* Switch to BTC context */
363+
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL);
364+
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
365+
}
366+
254367
esp_err_t esp_a2d_source_deinit(void)
255368
{
256369
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
@@ -348,6 +461,26 @@ esp_err_t esp_a2d_source_register_data_callback(esp_a2d_source_data_cb_t callbac
348461
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
349462
}
350463

464+
esp_err_t esp_a2d_source_audio_data_send(esp_a2d_conn_hdl_t conn_hdl, esp_a2d_audio_buff_t *audio_buf)
465+
{
466+
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED || !btc_av_is_started()) {
467+
return ESP_ERR_INVALID_STATE;
468+
}
469+
470+
if (audio_buf == NULL || audio_buf->data_len == 0 || conn_hdl == 0) {
471+
return ESP_ERR_INVALID_ARG;
472+
}
473+
474+
if (!btc_a2d_src_audio_mtu_check(audio_buf->data_len)) {
475+
return ESP_ERR_INVALID_SIZE;
476+
}
477+
478+
if (btc_a2d_src_audio_data_send(conn_hdl, audio_buf) != BT_STATUS_SUCCESS) {
479+
return ESP_FAIL;
480+
}
481+
return ESP_OK;
482+
}
483+
351484
#endif /* BTC_AV_SRC_INCLUDED */
352485

353486
#endif /* #if BTC_AV_INCLUDED */

components/bt/host/bluedroid/api/esp_hf_ag_api.c

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -528,6 +528,8 @@ esp_err_t esp_hf_ag_out_call(esp_bd_addr_t remote_addr, int num_active, int num_
528528
return (status == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
529529
}
530530

531+
#if (BTM_SCO_HCI_INCLUDED == TRUE)
532+
531533
esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_hf_outgoing_data_cb_t send)
532534
{
533535
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
@@ -548,7 +550,73 @@ esp_err_t esp_hf_ag_register_data_callback(esp_hf_incoming_data_cb_t recv, esp_h
548550
return (status == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
549551
}
550552

551-
#if (BTM_SCO_HCI_INCLUDED == TRUE)
553+
esp_err_t esp_hf_ag_register_audio_data_callback(esp_hf_ag_audio_data_cb_t callback)
554+
{
555+
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
556+
return ESP_ERR_INVALID_STATE;
557+
}
558+
559+
btc_msg_t msg;
560+
msg.sig = BTC_SIG_API_CALL;
561+
msg.pid = BTC_PID_HF;
562+
msg.act = BTC_HF_REGISTER_AUDIO_DATA_CALLBACK_EVT;
563+
564+
btc_hf_args_t arg;
565+
memset(&arg, 0, sizeof(btc_hf_args_t));
566+
arg.reg_audio_data_cb.callback = callback;
567+
568+
/* Switch to BTC context */
569+
bt_status_t status = btc_transfer_context(&msg, &arg, sizeof(btc_hf_args_t), NULL, NULL);
570+
return (status == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
571+
}
572+
573+
esp_hf_audio_buff_t *esp_hf_ag_audio_buff_alloc(uint16_t size)
574+
{
575+
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
576+
return NULL;
577+
}
578+
579+
if (size == 0) {
580+
return NULL;
581+
}
582+
583+
uint8_t *p_buf = NULL, *p_data;
584+
BTA_AgAudioBuffAlloc(size, &p_buf, &p_data);
585+
if (p_buf == NULL) {
586+
return NULL;
587+
}
588+
589+
esp_hf_audio_buff_t *audio_buf = (esp_hf_audio_buff_t *)p_buf;
590+
audio_buf->buff_size = size;
591+
audio_buf->data_len = 0;
592+
audio_buf->data = p_data;
593+
return audio_buf;
594+
}
595+
596+
void esp_hf_ag_audio_buff_free(esp_hf_audio_buff_t *audio_buf)
597+
{
598+
if (audio_buf == NULL) {
599+
return;
600+
}
601+
BTA_AgAudioBuffFree((UINT8 *)audio_buf);
602+
}
603+
604+
esp_err_t esp_hf_ag_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf)
605+
{
606+
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
607+
return ESP_ERR_INVALID_STATE;
608+
}
609+
610+
if (audio_buf == NULL || audio_buf->data_len == 0) {
611+
return ESP_ERR_INVALID_ARG;
612+
}
613+
614+
if (btc_hf_ag_audio_data_send(sync_conn_hdl, (uint8_t *)audio_buf, audio_buf->data, audio_buf->data_len)) {
615+
return ESP_OK;
616+
}
617+
return ESP_FAIL;
618+
}
619+
552620
esp_err_t esp_hf_ag_pkt_stat_nums_get(uint16_t sync_conn_handle)
553621
{
554622
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {

components/bt/host/bluedroid/api/esp_hf_client_api.c

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -541,6 +541,71 @@ void esp_hf_client_outgoing_data_ready(void)
541541
BTA_HfClientCiData();
542542
}
543543

544+
esp_err_t esp_hf_client_register_audio_data_callback(esp_hf_client_audio_data_cb_t callback)
545+
{
546+
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
547+
return ESP_ERR_INVALID_STATE;
548+
}
549+
550+
btc_msg_t msg;
551+
msg.sig = BTC_SIG_API_CALL;
552+
msg.pid = BTC_PID_HF_CLIENT;
553+
msg.act = BTC_HF_CLIENT_REGISTER_AUDIO_DATA_CALLBACK_EVT;
554+
555+
btc_hf_client_args_t arg;
556+
memset(&arg, 0, sizeof(btc_hf_client_args_t));
557+
arg.reg_audio_data_cb.callback = callback;
558+
559+
/* Switch to BTC context */
560+
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL, NULL);
561+
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
562+
}
563+
564+
esp_hf_audio_buff_t *esp_hf_client_audio_buff_alloc(uint16_t size)
565+
{
566+
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
567+
return NULL;
568+
}
569+
570+
if (size == 0) {
571+
return NULL;
572+
}
573+
574+
uint8_t *p_buf = NULL, *p_data;
575+
BTA_HfClientAudioBuffAlloc(size, &p_buf, &p_data);
576+
if (p_buf == NULL) {
577+
return NULL;
578+
}
579+
580+
esp_hf_audio_buff_t *audio_buf = (esp_hf_audio_buff_t *)p_buf;
581+
audio_buf->buff_size = size;
582+
audio_buf->data_len = 0;
583+
audio_buf->data = p_data;
584+
return audio_buf;
585+
}
586+
587+
void esp_hf_client_audio_buff_free(esp_hf_audio_buff_t *audio_buf)
588+
{
589+
if (audio_buf == NULL) {
590+
return;
591+
}
592+
BTA_HfClientAudioBuffFree((UINT8 *)audio_buf);
593+
}
594+
595+
esp_err_t esp_hf_client_audio_data_send(esp_hf_sync_conn_hdl_t sync_conn_hdl, esp_hf_audio_buff_t *audio_buf)
596+
{
597+
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
598+
return ESP_ERR_INVALID_STATE;
599+
}
600+
601+
if (audio_buf == NULL || audio_buf->data_len == 0) {
602+
return ESP_ERR_INVALID_ARG;
603+
}
604+
605+
BTA_HfClientAudioDataSend(sync_conn_hdl, (uint8_t *)audio_buf, audio_buf->data, audio_buf->data_len);
606+
return ESP_OK;
607+
}
608+
544609
void esp_hf_client_pcm_resample_init(uint32_t src_sps, uint32_t bits, uint32_t channels)
545610
{
546611
BTA_DmPcmInitSamples(src_sps, bits, channels);

0 commit comments

Comments
 (0)