A2DP
This manual describes the Advanced Audio Distribution Profile API definition. A2DP defines the protocols and procedures that realize distribution of audio content of high-quality in mono or stereo on ACL channels.
Terminology and Concepts
A2DP Roles
The following roles are defined for devices that implement this profile:
A2DP SDP Record
A2DP local record a2dp_sdp_record
should be registered by bt_sdp_record_add()
.
static const uint8_t a2dp_sdp_record[] =
{
SDP_DATA_ELEM_SEQ_HDR,
0x39,//0x55,
//attribute SDP_ATTR_SRV_CLASS_ID_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_SRV_CLASS_ID_LIST >> 8),
(uint8_t)SDP_ATTR_SRV_CLASS_ID_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x03,
SDP_UUID16_HDR,
(uint8_t)(UUID_AUDIO_SINK >> 8),
(uint8_t)(UUID_AUDIO_SINK),
//attribute SDP_ATTR_PROTO_DESC_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_PROTO_DESC_LIST >> 8),
(uint8_t)SDP_ATTR_PROTO_DESC_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x10,
SDP_DATA_ELEM_SEQ_HDR,
0x06,
SDP_UUID16_HDR,
(uint8_t)(UUID_L2CAP >> 8),
(uint8_t)(UUID_L2CAP),
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(PSM_AVDTP >> 8),
(uint8_t)(PSM_AVDTP),
SDP_DATA_ELEM_SEQ_HDR,
0x06,
SDP_UUID16_HDR,
(uint8_t)(UUID_AVDTP >> 8),
(uint8_t)(UUID_AVDTP),
SDP_UNSIGNED_TWO_BYTE,
0x01,
0x03,
//attribute SDP_ATTR_BROWSE_GROUP_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_BROWSE_GROUP_LIST >> 8),
(uint8_t)SDP_ATTR_BROWSE_GROUP_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x03,
SDP_UUID16_HDR,
(uint8_t)(UUID_PUBLIC_BROWSE_GROUP >> 8),
(uint8_t)(UUID_PUBLIC_BROWSE_GROUP),
/*
//attribute SDP_ATTR_LANG_BASE_ATTR_ID_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_LANG_BASE_ATTR_ID_LIST >> 8),
(uint8_t)SDP_ATTR_LANG_BASE_ATTR_ID_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x09,
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_LANG_ENGLISH >> 8),
(uint8_t)SDP_LANG_ENGLISH,
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_CHARACTER_UTF8 >> 8),
(uint8_t)SDP_CHARACTER_UTF8,
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_BASE_LANG_OFFSET >> 8),
(uint8_t)SDP_BASE_LANG_OFFSET,
*/
//attribute SDP_ATTR_PROFILE_DESC_LIST
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_PROFILE_DESC_LIST >> 8),
(uint8_t)SDP_ATTR_PROFILE_DESC_LIST,
SDP_DATA_ELEM_SEQ_HDR,
0x08,
SDP_DATA_ELEM_SEQ_HDR,
0x06,
SDP_UUID16_HDR,
(uint8_t)(UUID_ADVANCED_AUDIO_DISTRIBUTION >> 8),
(uint8_t)(UUID_ADVANCED_AUDIO_DISTRIBUTION),
SDP_UNSIGNED_TWO_BYTE,
0x01,//version 1.4
0x04,
//attribute SDP_ATTR_SUPPORTED_FEATURES
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)(SDP_ATTR_SUPPORTED_FEATURES >> 8),
(uint8_t)SDP_ATTR_SUPPORTED_FEATURES,
SDP_UNSIGNED_TWO_BYTE,
0x00,
0x03
/*
//attribute SDP_ATTR_SRV_NAME
SDP_UNSIGNED_TWO_BYTE,
(uint8_t)((SDP_ATTR_SRV_NAME + SDP_BASE_LANG_OFFSET) >> 8),
(uint8_t)(SDP_ATTR_SRV_NAME + SDP_BASE_LANG_OFFSET),
SDP_STRING_HDR,
0x09,
0x61, 0x32, 0x64, 0x70, 0x5f, 0x73, 0x69, 0x6e, 0x6b //a2dp_sink
*/
};
Feature Set
The functions provided by A2DP APIs are as below.
Connecting and Disconnecting: Including functions to connect/disconnect A2DP.
Streaming: Including functions to send stream data, etc.
Provided APIs
This figure shows the relationship between applications and A2DP and Bluetooth Host. Above the horizon line is developed by the applications. Below the horizon line is developed by Realtek.

A2DP Struct
The table below shows a simple description of A2DP APIs. A2DP related APIs are provided in the sdk\inc\framework\bt\bt_a2dp.h
.
Header File |
Description |
API Reference |
---|---|---|
|
Connect A2DP, send stream data etc. |
Functions
A2DP Init
A2DP initialization procedure involves profile initialization and stream endpoint registration.
void app_a2dp_init(void)
{
if (app_cfg_const.supported_profile_mask & A2DP_PROFILE_MASK)
{
bt_sdp_record_add((void *)a2dp_sdp_record);
bt_a2dp_init(app_cfg_const.a2dp_link_number, A2DP_LATENCY_MS);
if (app_cfg_const.a2dp_codec_type_sbc)
{
T_BT_A2DP_STREAM_END_POINT sep;
sep.codec_type = BT_A2DP_CODEC_TYPE_SBC;
sep.u.codec_sbc.sampling_frequency_mask = app_cfg_const.sbc_sampling_frequency;
sep.u.codec_sbc.channel_mode_mask = app_cfg_const.sbc_channel_mode;
sep.u.codec_sbc.block_length_mask = app_cfg_const.sbc_block_length;
sep.u.codec_sbc.subbands_mask = app_cfg_const.sbc_subbands;
sep.u.codec_sbc.allocation_method_mask = app_cfg_const.sbc_allocation_method;
sep.u.codec_sbc.min_bitpool = app_cfg_const.sbc_min_bitpool;
sep.u.codec_sbc.max_bitpool = app_cfg_const.sbc_max_bitpool;
bt_a2dp_stream_endpoint_add(sep);
}
if (app_cfg_const.a2dp_codec_type_aac)
{
T_BT_A2DP_STREAM_END_POINT sep;
sep.codec_type = BT_A2DP_CODEC_TYPE_AAC;
sep.u.codec_aac.object_type_mask = app_cfg_const.aac_object_type;
sep.u.codec_aac.sampling_frequency_mask = app_cfg_const.aac_sampling_frequency;
sep.u.codec_aac.channel_number_mask = app_cfg_const.aac_channel_number;
sep.u.codec_aac.vbr_supported = app_cfg_const.aac_vbr_supported;
sep.u.codec_aac.bit_rate = app_cfg_const.aac_bit_rate;
bt_a2dp_stream_endpoint_add(sep);
}
bt_mgr_cback_register(app_a2dp_bt_cback);
}
}
A2DP Connect

A2DP Connect Request

A2DP Disconnect Request

A2DP Connect Confirm
static void app_a2dp_bt_cback(T_BT_EVENT event_type, void *event_buf, uint16_t buf_len)
{
T_BT_EVENT_PARAM *param = event_buf;
T_APP_BR_LINK *p_link;
switch (event_type)
{
case BT_EVENT_A2DP_CONN_IND:
{
p_link = app_find_br_link(param->bt_a2dp_conn_ind.bd_addr);
if (p_link != NULL)
{
bt_a2dp_connect_cfm(p_link->bd_addr, true);
}
}
break;
case BT_EVENT_A2DP_CONN_CMPL:
break;
case BT_EVENT_A2DP_CONN_FAIL:
/*If both devices initiate a connection at the same time, both channels shall be closed and BT_EVENT_A2DP_CONN_FAIL will be received.
Each device shall wait a random time (not more than 1s and not less than 100ms) and then try to initiate the A2DP connection again. */
break;
case BT_EVENT_A2DP_CONFIG_CMPL:
{
p_link = app_find_br_link(param->bt_a2dp_config_cmpl.bd_addr);
if (p_link != NULL)
{
T_BT_EVENT_PARAM_A2DP_CONFIG_CMPL *cfg = ¶m->bt_a2dp_config_cmpl;
p_link->a2dp_codec_type = param->bt_a2dp_config_cmpl.codec_type;
if (p_link->a2dp_codec_type == BT_A2DP_CODEC_TYPE_SBC)
{
p_link->a2dp_codec_info.sbc.sampling_frequency = cfg->codec_info.sbc.sampling_frequency;
p_link->a2dp_codec_info.sbc.channel_mode = cfg->codec_info.sbc.channel_mode;
p_link->a2dp_codec_info.sbc.block_length = cfg->codec_info.sbc.block_length;
p_link->a2dp_codec_info.sbc.subbands = cfg->codec_info.sbc.subbands;
p_link->a2dp_codec_info.sbc.allocation_method = cfg->codec_info.sbc.allocation_method;
p_link->a2dp_codec_info.sbc.min_bitpool = cfg->codec_info.sbc.min_bitpool;
p_link->a2dp_codec_info.sbc.max_bitpool = cfg->codec_info.sbc.max_bitpool;
}
else if (p_link->a2dp_codec_type == BT_A2DP_CODEC_TYPE_AAC)
{
p_link->a2dp_codec_info.aac.object_type = cfg->codec_info.aac.object_type;
p_link->a2dp_codec_info.aac.sampling_frequency = cfg->codec_info.aac.sampling_frequency;
p_link->a2dp_codec_info.aac.channel_number = cfg->codec_info.aac.channel_number;
p_link->a2dp_codec_info.aac.vbr_supported = cfg->codec_info.aac.vbr_supported;
p_link->a2dp_codec_info.aac.allocation_method = cfg->codec_info.aac.allocation_method;
p_link->a2dp_codec_info.aac.bit_rate = cfg->codec_info.aac.bit_rate;
}
else
{
memcpy(p_link->a2dp_codec_info.vendor.info, cfg->codec_info.vendor.info, 12);
}
}
}
break;
case BT_EVENT_A2DP_DISCONN_CMPL:
break;
}
}
A2DP Streaming

A2DP Stream Open Request
Note
bt_avrcp_play()
is recommended to start music.

A2DP Stream Start Request

A2DP Stream Start Confirm

A2DP Stream Close Request
Note
bt_avrcp_pause()
is recommended to stop music.

A2DP Stream Susupend Request
static void app_a2dp_src_send_data(void)
{
//get media data
if (a2dp_credits > 0)
{
if (bt_a2dp_stream_data_send(a2dp_sink_addr, frame_num, p_data, length))
{
a2dp_credits--;
}
else
{
APP_PRINT_ERROR0("app_a2dp_src_send_data: send a2dp media pkt failed");
}
}
}
Sample Projects
SDK provides a corresponding demo application for developers’ reference in development. The BR/EDR Audio gives a simple example on how to use A2DP.