a2dp sink: cleanup api, add minimal docu, update tests and examples

This commit is contained in:
Milanka Ringwald 2017-08-29 14:34:08 +02:00
parent d851289b95
commit fd58c90006
8 changed files with 90 additions and 88 deletions

View File

@ -474,9 +474,8 @@ static void media_processing_close(void){
#endif
}
static void handle_l2cap_media_data_packet(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size){
UNUSED(stream_endpoint);
static void handle_l2cap_media_data_packet(uint8_t seid, uint8_t *packet, uint16_t size){
UNUSED(seid);
int pos = 0;
avdtp_media_packet_header_t media_header;
@ -954,12 +953,11 @@ int btstack_main(int argc, const char * argv[]){
a2dp_sink_register_packet_handler(&packet_handler);
a2dp_sink_register_media_handler(&handle_l2cap_media_data_packet);
avdtp_stream_endpoint_t * local_stream_endpoint = a2dp_sink_create_stream_endpoint(AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities), media_sbc_codec_configuration, sizeof(media_sbc_codec_configuration));
if (!local_stream_endpoint){
uint8_t status = a2dp_sink_create_stream_endpoint(AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities), media_sbc_codec_configuration, sizeof(media_sbc_codec_configuration), &local_seid);
if (status != ERROR_CODE_SUCCESS){
printf("A2DP Sink: not enough memory to create local stream endpoint\n");
return 1;
}
local_seid = avdtp_local_seid(local_stream_endpoint);
// Initialize AVRCP COntroller
avrcp_controller_init();
avrcp_controller_register_packet_handler(&avrcp_controller_packet_handler);

View File

@ -148,7 +148,7 @@ void a2dp_sink_register_packet_handler(btstack_packet_handler_t callback){
a2dp_sink_context.a2dp_callback = callback;
}
void a2dp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size)){
void a2dp_sink_register_media_handler(void (*callback)(uint8_t local_seid, uint8_t *packet, uint16_t size)){
if (callback == NULL){
log_error("a2dp_sink_register_media_handler called with NULL callback");
return;
@ -161,20 +161,21 @@ void a2dp_sink_init(void){
l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0);
}
avdtp_stream_endpoint_t * a2dp_sink_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type,
uint8_t a2dp_sink_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type,
uint8_t * codec_capabilities, uint16_t codec_capabilities_len,
uint8_t * media_codec_info, uint16_t media_codec_info_len){
uint8_t * media_codec_info, uint16_t media_codec_info_len, uint8_t * local_seid){
*local_seid = 0;
avdtp_stream_endpoint_t * local_stream_endpoint = avdtp_sink_create_stream_endpoint(AVDTP_SINK, media_type);
if (!local_stream_endpoint){
return NULL;
return BTSTACK_MEMORY_ALLOC_FAILED;
}
*local_seid = avdtp_local_seid(local_stream_endpoint);
avdtp_sink_register_media_transport_category(avdtp_stream_endpoint_seid(local_stream_endpoint));
avdtp_sink_register_media_codec_category(avdtp_stream_endpoint_seid(local_stream_endpoint), media_type, media_codec_type,
codec_capabilities, codec_capabilities_len);
local_stream_endpoint->remote_configuration.media_codec.media_codec_information = media_codec_info;
local_stream_endpoint->remote_configuration.media_codec.media_codec_information_len = media_codec_info_len;
return local_stream_endpoint;
return ERROR_CODE_SUCCESS;
}
uint8_t a2dp_sink_establish_stream(bd_addr_t bd_addr, uint8_t local_seid, uint16_t * avdtp_cid){

View File

@ -55,65 +55,69 @@ extern "C" {
/* API_START */
/**
* @brief A2DP Sink service record.
* @brief Create A2DP Sink service record.
* @param service
* @param service_record_handle
* @param supported_features 16-bit bitmap, see a2dp_SINK_SF_* values in avdtp.h
* @param supported_features 16-bit bitmap, see AVDTP_SINK_SF_* values in avdtp.h
* @param service_name
* @param service_provider_name
*/
void a2dp_sink_create_sdp_record(uint8_t * service, uint32_t service_record_handle, uint16_t supported_features, const char * service_name, const char * service_provider_name);
/**
* @brief Set up A2DP Sink device.
* @brief Initialize up A2DP Sink device.
*/
void a2dp_sink_init(void);
avdtp_stream_endpoint_t * a2dp_sink_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type,
/**
* @brief Create a stream endpoint of type SINK, and register media codec by specifying its capabilities and the default configuration.
* @param media_type see avdtp_media_type_t values in avdtp.h (audio, video or multimedia)
* @param media_codec_type see avdtp_media_codec_type_t values in avdtp.h
* @param codec_capabilities media codec capabilities as defined in A2DP spec, section 4 - Audio Codec Interoperability Requirements.
* @param codec_capabilities_len media codec capabilities length
* @param codec_configuration default media codec configuration
* @param codec_configuration_len media codec configuration length
* @return status
*/
uint8_t a2dp_sink_create_stream_endpoint(avdtp_media_type_t media_type, avdtp_media_codec_type_t media_codec_type,
uint8_t * codec_capabilities, uint16_t codec_capabilities_len,
uint8_t * codec_configuration, uint16_t codec_configuration_len);
uint8_t * codec_configuration, uint16_t codec_configuration_len, uint8_t * local_seid);
/**
* @brief Register callback for the A2DP Sink client.
* @brief Register callback for the A2DP Sink client. It will receive following subevents of HCI_EVENT_A2DP_META HCI event type:
* - A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION: indicates from remote chosen SBC media codec configuration
* - A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION: indicates from remote chosen other then SBC media codec configuration
* - A2DP_SUBEVENT_STREAM_ESTABLISHED: received when stream to a remote device is established
* - A2DP_SUBEVENT_STREAM_STARTED: received when stream is started
* - A2DP_SUBEVENT_STREAM_SUSPENDED: received when stream is paused
* - A2DP_SUBEVENT_STREAM_RELEASED: received when stream is released
*
* @param callback
*/
void a2dp_sink_register_packet_handler(btstack_packet_handler_t callback);
/**
* @brief Register media handler for the A2DP Sink client.
* @param callback
* @param packet
* @param size
*/
void a2dp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size));
void a2dp_sink_register_media_handler(void (*callback)(uint8_t local_seid, uint8_t *packet, uint16_t size));
/**
* @brief Open stream
* @param bd_addr
* @param local_seid
* @param avdtp_cid
* @brief Establish stream.
* @param remote
* @param local_seid ID assigned to a local stream endpoint
* @param a2dp_cid
*/
uint8_t a2dp_sink_establish_stream(bd_addr_t bd_addr, uint8_t local_seid, uint16_t * avdtp_cid);
uint8_t a2dp_sink_establish_stream(bd_addr_t remote, uint8_t local_seid, uint16_t * a2dp_cid);
/**
* @brief Start stream
* @param local_seid
* @brief Release stream.
* @param a2dp_cid
*/
void a2dp_sink_start_stream(uint8_t local_seid);
/**
* @brief Suspend stream
* @param local_seid
*/
void a2dp_sink_pause(uint8_t local_seid);
/**
* @brief Abort stream
* @param local_seid
*/
void a2dp_sink_stop_stream(uint8_t local_seid);
void a2dp_sink_disconnect(uint16_t a2dp_cid);
/* API_END */

View File

@ -67,7 +67,7 @@ static const unsigned int attribute_value_buffer_size = sizeof(attribute_value);
static avdtp_context_t * sdp_query_context;
static uint16_t avdtp_cid_counter = 0;
static void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size);
static void (*handle_media_data)(uint8_t local_seid, uint8_t *packet, uint16_t size);
static void avdtp_handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
static uint16_t avdtp_get_next_initiator_transaction_label(avdtp_context_t * context){
@ -562,7 +562,7 @@ void avdtp_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
if (channel == stream_endpoint->l2cap_media_cid){
if (handle_media_data){
(*handle_media_data)(stream_endpoint, packet, size);
(*handle_media_data)(avdtp_local_seid(stream_endpoint), packet, size);
}
break;
}

View File

@ -500,7 +500,7 @@ typedef struct {
uint16_t initiator_transaction_id_counter;
btstack_packet_handler_t avdtp_callback;
btstack_packet_handler_t a2dp_callback;
void (*handle_media_data)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size);
void (*handle_media_data)(uint8_t local_seid, uint8_t *packet, uint16_t size);
btstack_packet_handler_t packet_handler;
avdtp_sep_type_t query_role;

View File

@ -125,7 +125,7 @@ avdtp_stream_endpoint_t * avdtp_sink_create_stream_endpoint(avdtp_sep_type_t sep
return avdtp_create_stream_endpoint(sep_type, media_type, avdtp_sink_context);
}
void avdtp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size)){
void avdtp_sink_register_media_handler(void (*callback)(uint8_t local_seid, uint8_t *packet, uint16_t size)){
if (callback == NULL){
log_error("avdtp_sink_register_media_handler called with NULL callback");
return;

View File

@ -87,7 +87,7 @@ void avdtp_sink_register_packet_handler(btstack_packet_handler_t callback);
*/
uint8_t avdtp_sink_connect(bd_addr_t bd_addr, uint16_t * avdtp_cid);
void avdtp_sink_register_media_handler(void (*callback)(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size));
void avdtp_sink_register_media_handler(void (*callback)(uint8_t local_seid, uint8_t *packet, uint16_t size));
/**
* @brief Disconnect from device with connection handle.
* @param avdtp_cid

View File

@ -132,11 +132,12 @@ static bd_addr_t device_addr;
static uint16_t avdtp_cid = 0;
static uint8_t sdp_avdtp_sink_service_buffer[150];
static avdtp_sep_t sep;
static adtvp_media_codec_information_sbc_t sbc_capability;
static avdtp_media_codec_configuration_sbc_t sbc_configuration;
static avdtp_stream_endpoint_t * local_stream_endpoint;
static uint8_t local_seid;
static uint8_t remote_seid;
// static avdtp_sep_t sep;
static uint16_t remote_configuration_bitmap;
static avdtp_capabilities_t remote_configuration;
@ -309,9 +310,8 @@ static void close_media_processing(void){
#endif
}
static void handle_l2cap_media_data_packet(avdtp_stream_endpoint_t * stream_endpoint, uint8_t *packet, uint16_t size){
UNUSED(stream_endpoint);
static void handle_l2cap_media_data_packet(uint8_t seid, uint8_t *packet, uint16_t size){
UNUSED(seid);
int pos = 0;
@ -413,11 +413,10 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
printf("AVDTP connection released: avdtp_cid 0x%02x.\n", avdtp_cid);
break;
case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND:
sep.seid = avdtp_subevent_signaling_sep_found_get_remote_seid(packet);
sep.in_use = avdtp_subevent_signaling_sep_found_get_in_use(packet);
sep.media_type = avdtp_subevent_signaling_sep_found_get_media_type(packet);
sep.type = avdtp_subevent_signaling_sep_found_get_sep_type(packet);
printf("Found sep: seid %u, in_use %d, media type %d, sep type %d (1-SNK)\n", sep.seid, sep.in_use, sep.media_type, sep.type);
remote_seid = avdtp_subevent_signaling_sep_found_get_remote_seid(packet);
printf("Found sep: seid %u, in_use %d, media type %d, sep type %d (1-SNK)\n",
remote_seid, avdtp_subevent_signaling_sep_found_get_in_use(packet),
avdtp_subevent_signaling_sep_found_get_media_type(packet), avdtp_subevent_signaling_sep_found_get_sep_type(packet));
break;
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY:
printf("Received MEDIA_CODEC_SBC_CAPABILITY\n");
@ -495,19 +494,19 @@ static void show_usage(void){
printf("a - get all capabilities\n");
printf("s - set configuration\n");
printf("f - get configuration\n");
printf("R - reconfigure stream with %d\n", sep.seid);
printf("o - establish stream with seid %d\n", sep.seid);
printf("m - start stream with %d\n", sep.seid);
printf("A - abort stream with %d\n", sep.seid);
printf("P - suspend (pause) stream with %d\n", sep.seid);
printf("S - stop (release) stream with %d\n", sep.seid);
printf("R - reconfigure stream with %d\n", remote_seid);
printf("o - establish stream with seid %d\n", remote_seid);
printf("m - start stream with %d\n", remote_seid);
printf("A - abort stream with %d\n", remote_seid);
printf("P - suspend (pause) stream with %d\n", remote_seid);
printf("S - stop (release) stream with %d\n", remote_seid);
printf("C - disconnect\n");
printf("Ctrl-c - exit\n");
printf("---\n");
}
static void stdin_process(char cmd){
sep.seid = 1;
remote_seid = 1;
switch (cmd){
case 'c':
printf("Establish AVDTP Sink connection to %s\n", device_addr_string);
@ -522,54 +521,54 @@ static void stdin_process(char cmd){
avdtp_sink_discover_stream_endpoints(avdtp_cid);
break;
case 'g':
printf("Get capabilities of stream endpoint with seid %d\n", sep.seid);
avdtp_sink_get_capabilities(avdtp_cid, sep.seid);
printf("Get capabilities of stream endpoint with seid %d\n", remote_seid);
avdtp_sink_get_capabilities(avdtp_cid, remote_seid);
break;
case 'a':
printf("Get all capabilities of stream endpoint with seid %d\n", sep.seid);
avdtp_sink_get_all_capabilities(avdtp_cid, sep.seid);
printf("Get all capabilities of stream endpoint with seid %d\n", remote_seid);
avdtp_sink_get_all_capabilities(avdtp_cid, remote_seid);
break;
case 'f':
printf("Get configuration of stream endpoint with seid %d\n", sep.seid);
avdtp_sink_get_configuration(avdtp_cid, sep.seid);
printf("Get configuration of stream endpoint with seid %d\n", remote_seid);
avdtp_sink_get_configuration(avdtp_cid, remote_seid);
break;
case 's':
printf("Set configuration of stream endpoint with seid %d\n", sep.seid);
printf("Set configuration of stream endpoint with seid %d\n", remote_seid);
remote_configuration_bitmap = store_bit16(remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
remote_configuration.media_codec.media_type = AVDTP_AUDIO;
remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
remote_configuration.media_codec.media_codec_information_len = sizeof(media_sbc_codec_configuration);
remote_configuration.media_codec.media_codec_information = media_sbc_codec_configuration;
avdtp_sink_set_configuration(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid, remote_configuration_bitmap, remote_configuration);
avdtp_sink_set_configuration(avdtp_cid, local_seid, remote_seid, remote_configuration_bitmap, remote_configuration);
break;
case 'R':
printf("Reconfigure stream endpoint with seid %d\n", sep.seid);
printf("Reconfigure stream endpoint with seid %d\n", remote_seid);
remote_configuration_bitmap = store_bit16(remote_configuration_bitmap, AVDTP_MEDIA_CODEC, 1);
remote_configuration.media_codec.media_type = AVDTP_AUDIO;
remote_configuration.media_codec.media_codec_type = AVDTP_CODEC_SBC;
remote_configuration.media_codec.media_codec_information_len = sizeof(media_sbc_codec_reconfiguration);
remote_configuration.media_codec.media_codec_information = media_sbc_codec_reconfiguration;
avdtp_sink_reconfigure(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid, remote_configuration_bitmap, remote_configuration);
avdtp_sink_reconfigure(avdtp_cid, local_seid, remote_seid, remote_configuration_bitmap, remote_configuration);
break;
case 'o':
printf("Establish stream between local %d and remote %d seid\n", avdtp_local_seid(local_stream_endpoint), sep.seid);
avdtp_sink_open_stream(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid);
printf("Establish stream between local %d and remote %d seid\n", local_seid, remote_seid);
avdtp_sink_open_stream(avdtp_cid, local_seid, remote_seid);
break;
case 'm':
printf("Start stream between local %d and remote %d seid\n", avdtp_local_seid(local_stream_endpoint), avdtp_remote_seid(local_stream_endpoint));
avdtp_sink_start_stream(avdtp_cid, avdtp_local_seid(local_stream_endpoint));
printf("Start stream between local %d and remote %d seid\n", local_seid, remote_seid);
avdtp_sink_start_stream(avdtp_cid, local_seid);
break;
case 'A':
printf("Abort stream between local %d and remote %d seid\n", avdtp_local_seid(local_stream_endpoint), avdtp_remote_seid(local_stream_endpoint));
avdtp_sink_abort_stream(avdtp_cid, avdtp_local_seid(local_stream_endpoint));
printf("Abort stream between local %d and remote %d seid\n", local_seid, remote_seid);
avdtp_sink_abort_stream(avdtp_cid, local_seid);
break;
case 'S':
printf("Release stream between local %d and remote %d seid\n", avdtp_local_seid(local_stream_endpoint), avdtp_remote_seid(local_stream_endpoint));
avdtp_sink_stop_stream(avdtp_cid, avdtp_local_seid(local_stream_endpoint));
printf("Release stream between local %d and remote %d seid\n", local_seid, remote_seid);
avdtp_sink_stop_stream(avdtp_cid, local_seid);
break;
case 'P':
printf("Susspend stream between local %d and remote %d seid\n", avdtp_local_seid(local_stream_endpoint), avdtp_remote_seid(local_stream_endpoint));
avdtp_sink_suspend(avdtp_cid, avdtp_local_seid(local_stream_endpoint));
printf("Susspend stream between local %d and remote %d seid\n", local_seid, remote_seid);
avdtp_sink_suspend(avdtp_cid, local_seid);
break;
case '\n':
@ -598,14 +597,14 @@ int btstack_main(int argc, const char * argv[]){
avdtp_sink_init(&a2dp_sink_context);
avdtp_sink_register_packet_handler(&packet_handler);
local_stream_endpoint = avdtp_sink_create_stream_endpoint(AVDTP_SINK, AVDTP_AUDIO);
avdtp_stream_endpoint_t * local_stream_endpoint = avdtp_sink_create_stream_endpoint(AVDTP_SINK, AVDTP_AUDIO);
if (!local_stream_endpoint) {
printf("AVDTP Sink: not enough memory to create local_stream_endpoint\n");
return 1;
}
avdtp_sink_register_media_transport_category(local_stream_endpoint->sep.seid);
avdtp_sink_register_media_codec_category(local_stream_endpoint->sep.seid, AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities));
local_seid = avdtp_local_seid(local_stream_endpoint);
avdtp_sink_register_media_transport_category(local_seid);
avdtp_sink_register_media_codec_category(local_seid, AVDTP_AUDIO, AVDTP_CODEC_SBC, media_sbc_codec_capabilities, sizeof(media_sbc_codec_capabilities));
avdtp_sink_register_media_handler(&handle_l2cap_media_data_packet);
// Initialize SDP