esp-idf: A2DP Source stream audio to two Sink device (IDFGH-253)

Hello all, @blueMoodBHD @mywang-espressif @igrr @FayeY

I want to add new functionality to the A2DP source capability of the esp-idf. Especially I want to stream audio from ESP32 to two bluetooth speaker.

I want to reach this funtionality with the design guidelines of the bluetooth.org from the study called “WHITE PAPER ON USAGE OF MULTIPLE HEADPHONES”: (https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=110679)

In this study there are use cases how should a source device act if the user wants to connect two sink audio device.

One of the scenario follows the next steps:

  1. AVDTP & AVCTP Connection establish with Sink device 1
  2. A2DP SEP Disc/Selec with Sink device 1
  3. SET_CONFIG for Sink device 1
  4. OPEN connection with Sink device 1
  5. START meadia Sink device 1 (ESP_A2D_MEDIA_CTRL_START)
  6. STREAM Media to Sink device 1 ---- new device connection----
  7. GAP/ACL Connect to Sink device 2
  8. AVDTP Establish, SEP Disc/Select with Sink device 2
  9. Suspend media to Sink device 1 (ESP_A2D_MEDIA_CTRL_SUSPEND)
  10. SET_CONFIG to Sink device 2
  11. OPEN connection with Sink device 2
  12. START Media on Sink device 2 (ESP_A2D_MEDIA_CTRL_START)
  13. STREAM Media to Sink device 1
  14. STREAM Media to Sink device 2
  15. HAPPY USERs

Would somebody give some idea how to start for the 7-8, and 10th steps? The base application would be the A2DP_source example code.

The study states we need to have two (or more) Stream End Point, SEPs on the SRC device that support the SBC codec.

I have already figured out the SEPs are initialized with the bta_av_api_register() function in the bt/bluedroid/bta/av/bta_av_main.c file. The SEPs are handled in a tBTA_AV_SCB struct with the following code: tBTA_AV_SEP seps[BTA_AV_MAX_SEPS]; Here it can be seen the BlueDroid stack is already prepared somehow to handle more connection. As I go through the code in the current esp-idf there are two streams are handled. One seperated stream for the source device and one seperated stream for sink device. And that is why the BTA_AV_MAX_SEPS equals two. I guess…

In the bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c file, the btc_a2dp_source_send_aa_frame() function prepares the audio data/frame what we want to send to the sink device. And it would be good if the created frame would be sended to both of the connected devices in a queue. In that manner all SNK devices will be receiving identical A2DP media packets. But I have no idea where to start in this manner. Maybe the btc_a2dp_source_task_handler() function needs some rework too.

The study mentioned the following:

When the SRC connects to another SNK device the configuration of the SBC codec should be the same as the configuration of the SBC codec in the existing SNK device.

In the code hwo can I attach the same SBC configuration for both of the device?

Anyway, these are very small slices of the “game” and I know this is not a small rewrite. I just really need some help and advice which functions shall be rewrited.

Any advice are welcomed!

Rob

UPDATE 2018.06.22

I modified the btc_av.c , btc_avrc.c and the main API state handler to handle the multiple connections.

Basically I modified two main things:

In the btc_av.c the following:

typedef struct {
    int service_id[BT_NUM_OF_DEVICES];
    tBTA_AV_HNDL bta_handle[BT_NUM_OF_DEVICES];
    uint8_t peer_bda[BT_NUM_OF_DEVICES][BD_ADDR_LEN];
    btc_sm_handle_t sm_handle[BT_NUM_OF_DEVICES];
    UINT8 flags[BT_NUM_OF_DEVICES];
    tBTA_AV_EDR edr[BT_NUM_OF_DEVICES];
    UINT8   peer_sep[BT_NUM_OF_DEVICES];  /* sep type of peer device */
	UINT8	connected_dev_num; //< count how much device connected
	UINT8	active_dev_idx; //< index number of the activated device
	UINT8	conn_slot; //< how much device is already connected
	UINT8   media_ctrl_pending;  //< flag for indication of the media control is pending
} btc_av_cb_t;

And in the btc_avrc.c:

typedef struct {
    BOOLEAN                     rc_connected[BT_NUM_OF_DEVICES];
    UINT8                       rc_handle[BT_NUM_OF_DEVICES];
    tBTA_AV_FEAT                rc_features[BT_NUM_OF_DEVICES];
    uint8_t                     rc_addr[BT_NUM_OF_DEVICES][BD_ADDR_LEN];
    UINT16                      rc_pending_play[BT_NUM_OF_DEVICES];
    btc_rc_cmd_ctxt_t           rc_pdu_info[MAX_CMD_QUEUE_LEN]; //todo: this is not prepared fow two sink
    btc_rc_reg_notifications_t  rc_notif[MAX_RC_NOTIFICATIONS]; //todo: this is not prepared fow two sink
    unsigned int                rc_volume[BT_NUM_OF_DEVICES];
    uint8_t                     rc_vol_label[BT_NUM_OF_DEVICES];
	uint8_t						active_dev_idx; //< index number of the activated device
	uint8_t						conn_slot; //< index number of the activated device
} btc_rc_cb_t;

And I modified all of the functions whose are using these variables. But I run into an error when the second device tries to connec: av scb not available for avdt connection

This came from the bta_av_sig_chg() function in the bt/bluedroid/bta/av/bta_av_act.c file:

           /* check if we found something */
            if (xx == BTA_AV_NUM_LINKS) {
                /* We do not have scb for this avdt connection.     */
                /* Silently close the connection.                   */
                APPL_TRACE_ERROR("av scb not available for avdt connection");
                AVDT_DisconnectReq (p_data->str_msg.bd_addr, NULL);
                return;
}

Any advice what can be the problem?

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 5
  • Comments: 16

Most upvoted comments

Sorry, the BLE audio chip is not ready, still in R&D stage.