diff --git a/src/btstack_defines.h b/src/btstack_defines.h index 840487ec8..5fbc6ebf7 100644 --- a/src/btstack_defines.h +++ b/src/btstack_defines.h @@ -1349,9 +1349,11 @@ typedef uint8_t sm_key_t[16]; #define AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION 0x0A /** - * @format 1H1 + * @format 1H111 * @param subevent_code * @param avdtp_cid + * @param int_seid + * @param acp_seid * @param status 0 == OK */ #define AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED 0x0B diff --git a/src/btstack_event.h b/src/btstack_event.h index 099ab5a01..53f07d1b6 100644 --- a/src/btstack_event.h +++ b/src/btstack_event.h @@ -4412,6 +4412,24 @@ static inline const uint8_t * avdtp_subevent_signaling_media_codec_other_configu static inline hci_con_handle_t avdtp_subevent_streaming_connection_established_get_avdtp_cid(const uint8_t * event){ return little_endian_read_16(event, 3); } +/** + * @brief Get field int_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED + * @param event packet + * @return int_seid + * @note: btstack_type 1 + */ +static inline uint8_t avdtp_subevent_streaming_connection_established_get_int_seid(const uint8_t * event){ + return event[5]; +} +/** + * @brief Get field acp_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED + * @param event packet + * @return acp_seid + * @note: btstack_type 1 + */ +static inline uint8_t avdtp_subevent_streaming_connection_established_get_acp_seid(const uint8_t * event){ + return event[6]; +} /** * @brief Get field status from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED * @param event packet @@ -4419,7 +4437,7 @@ static inline hci_con_handle_t avdtp_subevent_streaming_connection_established_g * @note: btstack_type 1 */ static inline uint8_t avdtp_subevent_streaming_connection_established_get_status(const uint8_t * event){ - return event[5]; + return event[7]; } /** diff --git a/src/classic/a2dp_source.c b/src/classic/a2dp_source.c index 951e107b7..2bfdc5345 100644 --- a/src/classic/a2dp_source.c +++ b/src/classic/a2dp_source.c @@ -172,7 +172,8 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe uint8_t signal_identifier; uint8_t status; avdtp_sep_t sep; - // + uint8_t int_seid; + uint8_t acp_seid; switch (packet_type) { @@ -206,12 +207,17 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED: status = avdtp_subevent_streaming_connection_established_get_status(packet); + avdtp_cid = avdtp_subevent_streaming_connection_established_get_avdtp_cid(packet); + int_seid = avdtp_subevent_streaming_connection_established_get_int_seid(packet); + acp_seid = avdtp_subevent_streaming_connection_established_get_acp_seid(packet); + if (status != 0){ printf(" --- a2dp source --- AVDTP_SUBEVENT_STREAMING_CONNECTION could not be established, status %d ---\n", status); break; } app_state = A2DP_STREAMING_OPENED; - printf(" --- a2dp source --- AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED ---\n"); + avdtp_streaming_emit_connection_established(a2dp_source_context.a2dp_callback, avdtp_cid, int_seid, acp_seid, 0); + printf(" --- a2dp source --- AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED --- avdtp_cid 0x%02x, local seid %d, remote seid %d\n", avdtp_cid, int_seid, acp_seid); break; case AVDTP_SUBEVENT_SIGNALING_SEP_FOUND: @@ -268,6 +274,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe // TODO: deal with reconfigure: avdtp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(packet); break; } + case AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: + avdtp_streaming_emit_can_send_media_packet_now(a2dp_source_context.a2dp_callback, avdtp_cid, 0, 0); + break; case AVDTP_SUBEVENT_SIGNALING_ACCEPT: signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet); @@ -314,6 +323,8 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe case A2DP_STREAMING_OPENED: switch (signal_identifier){ case AVDTP_SI_START: + printf(" AVDTP_SI_START successful\n"); + avdtp_signaling_emit_accept(a2dp_source_context.a2dp_callback, avdtp_cid, 0, signal_identifier, 0); break; case AVDTP_SI_CLOSE: break; @@ -396,3 +407,11 @@ void a2dp_source_disconnect(uint16_t con_handle){ avdtp_disconnect(con_handle, &a2dp_source_context); } +void a2dp_source_start_stream(uint16_t cid, uint8_t int_seid, uint8_t acp_seid){ + avdtp_start_stream(cid, int_seid, acp_seid, &a2dp_source_context); +} + +void a2dp_source_stop_stream(uint16_t cid, uint8_t int_seid, uint8_t acp_seid){ + avdtp_stop_stream(cid, int_seid, acp_seid, &a2dp_source_context); +} + diff --git a/src/classic/avdtp.c b/src/classic/avdtp.c index e1f2a7ce7..95914bcbe 100644 --- a/src/classic/avdtp.c +++ b/src/classic/avdtp.c @@ -236,7 +236,7 @@ static void stream_endpoint_state_machine(avdtp_connection_t * connection, avdtp stream_endpoint->l2cap_media_cid = l2cap_event_channel_opened_get_local_cid(packet); stream_endpoint->media_con_handle = l2cap_event_channel_opened_get_handle(packet); printf(" -> AVDTP_STREAM_ENDPOINT_OPENED, media con handle 0x%02x, l2cap_media_cid 0x%02x\n", stream_endpoint->media_con_handle, stream_endpoint->l2cap_media_cid); - avdtp_streaming_emit_connection_established(context->avdtp_callback, stream_endpoint->l2cap_media_cid, 0); + avdtp_streaming_emit_connection_established(context->avdtp_callback, connection->l2cap_signaling_cid, stream_endpoint->sep.seid, connection->remote_seps[stream_endpoint->remote_sep_index].seid, 0); break; } break; diff --git a/src/classic/avdtp_source.c b/src/classic/avdtp_source.c index 5ff161648..e614de45a 100644 --- a/src/classic/avdtp_source.c +++ b/src/classic/avdtp_source.c @@ -183,7 +183,8 @@ void avdtp_source_init(avdtp_context_t * avdtp_context){ l2cap_register_service(&packet_handler, BLUETOOTH_PROTOCOL_AVDTP, 0xffff, LEVEL_0); } -int avdtp_source_stream_endpoint_ready(avdtp_stream_endpoint_t * stream_endpoint){ +int avdtp_source_stream_endpoint_ready(uint8_t local_seid){ + avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, avdtp_source_context); if (!stream_endpoint) { printf("no stream_endpoint"); return 0; @@ -191,7 +192,8 @@ int avdtp_source_stream_endpoint_ready(avdtp_stream_endpoint_t * stream_endpoint return (stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING || stream_endpoint->state == AVDTP_STREAM_ENDPOINT_STREAMING_W2_SEND); } -void avdtp_source_stream_endpoint_request_can_send_now(avdtp_stream_endpoint_t * stream_endpoint){ +void avdtp_source_stream_endpoint_request_can_send_now(uint8_t local_seid){ + avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(local_seid, avdtp_source_context); if (!stream_endpoint) { printf("no stream_endpoint"); return; @@ -264,23 +266,28 @@ static void avdtp_source_copy_media_payload(uint8_t * media_packet, int size, in *offset = pos; } -void avdtp_source_stream_send_media_payload(uint16_t l2cap_media_cid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker){ - avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_l2cap_cid(l2cap_media_cid, avdtp_source_context); +void avdtp_source_stream_send_media_payload(uint8_t int_seid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker){ + avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, avdtp_source_context); if (!stream_endpoint) { - printf("no stream_endpoint found for 0x%02x", l2cap_media_cid); + printf("no stream_endpoint found for seid %d", int_seid); return; } - int size = l2cap_get_remote_mtu_for_local_cid(l2cap_media_cid); + if (stream_endpoint->l2cap_media_cid == 0){ + printf("no media cid found for seid %d", int_seid); + return; + } + + int size = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid); int offset = 0; l2cap_reserve_packet_buffer(); uint8_t * media_packet = l2cap_get_outgoing_buffer(); - //int size = l2cap_get_remote_mtu_for_local_cid(l2cap_media_cid); + //int size = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid); avdtp_source_setup_media_header(media_packet, size, &offset, marker, stream_endpoint->sequence_number); avdtp_source_copy_media_payload(media_packet, size, &offset, sbc_ring_buffer); stream_endpoint->sequence_number++; - l2cap_send_prepared(l2cap_media_cid, offset); + l2cap_send_prepared(stream_endpoint->l2cap_media_cid, offset); } uint8_t avdtp_source_remote_seps_num(uint16_t avdtp_cid){ diff --git a/src/classic/avdtp_source.h b/src/classic/avdtp_source.h index ba97c79b3..743731f04 100644 --- a/src/classic/avdtp_source.h +++ b/src/classic/avdtp_source.h @@ -154,9 +154,9 @@ void avdtp_source_stop_stream(uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_ avdtp_stream_endpoint_t * avdtp_source_create_stream_endpoint(avdtp_sep_type_t sep_type, avdtp_media_type_t media_type); -void avdtp_source_stream_endpoint_request_can_send_now(avdtp_stream_endpoint_t * stream_endpoint); -int avdtp_source_stream_endpoint_ready(avdtp_stream_endpoint_t * stream_endpoint); -void avdtp_source_stream_send_media_payload(uint16_t l2cap_media_cid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker); +void avdtp_source_stream_endpoint_request_can_send_now(uint8_t local_seid); +int avdtp_source_stream_endpoint_ready(uint8_t local_seid); +void avdtp_source_stream_send_media_payload(uint8_t local_seid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker); uint8_t avdtp_source_remote_seps_num(uint16_t avdtp_cid); avdtp_sep_t * avdtp_source_remote_sep(uint16_t avdtp_cid, uint8_t index); diff --git a/src/classic/avdtp_util.c b/src/classic/avdtp_util.c index 3f74a5071..b05c8ab4c 100644 --- a/src/classic/avdtp_util.c +++ b/src/classic/avdtp_util.c @@ -528,15 +528,17 @@ void avdtp_streaming_emit_can_send_media_packet_now(btstack_packet_handler_t cal (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } -void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t status){ +void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint8_t status){ if (!callback) return; - uint8_t event[6]; + uint8_t event[8]; int pos = 0; event[pos++] = HCI_EVENT_AVDTP_META; event[pos++] = sizeof(event) - 2; event[pos++] = AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED; little_endian_store_16(event, pos, avdtp_cid); pos += 2; + event[pos++] = int_seid; + event[pos++] = acp_seid; event[pos++] = status; (*callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); } diff --git a/src/classic/avdtp_util.h b/src/classic/avdtp_util.h index f5a63eeb7..962d3c919 100644 --- a/src/classic/avdtp_util.h +++ b/src/classic/avdtp_util.h @@ -72,7 +72,7 @@ void avdtp_prepare_capabilities(avdtp_signaling_packet_t * signaling_packet, uin int avdtp_signaling_create_fragment(uint16_t cid, avdtp_signaling_packet_t * signaling_packet, uint8_t * out_buffer); void avdtp_signaling_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, bd_addr_t addr, uint8_t status); -void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t status); +void avdtp_streaming_emit_connection_established(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, uint8_t acp_seid, uint8_t status); void avdtp_signaling_emit_sep(btstack_packet_handler_t callback, uint16_t avdtp_cid, avdtp_sep_t sep); void avdtp_signaling_emit_accept(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t seid, avdtp_signal_identifier_t identifier, uint8_t status); void avdtp_signaling_emit_general_reject(btstack_packet_handler_t callback, uint16_t avdtp_cid, uint8_t int_seid, avdtp_signal_identifier_t identifier); diff --git a/test/avdtp/avdtp_source_demo.c b/test/avdtp/avdtp_source_demo.c index e5da7933a..8fc9f66ee 100644 --- a/test/avdtp/avdtp_source_demo.c +++ b/test/avdtp/avdtp_source_demo.c @@ -73,37 +73,23 @@ #endif #define TABLE_SIZE_441HZ 100 -typedef struct { -// to app - uint32_t fill_audio_ring_buffer_timeout_ms; - uint32_t time_audio_data_sent; // ms - uint32_t acc_num_missed_samples; - uint32_t samples_ready; - btstack_timer_source_t fill_audio_ring_buffer_timer; - btstack_ring_buffer_t sbc_ring_buffer; - btstack_sbc_encoder_state_t sbc_encoder_state; - - int reconfigure; - int num_channels; - int sampling_frequency; - int channel_mode; - int block_length; - int subbands; - int allocation_method; - int min_bitpool_value; - int max_bitpool_value; -} avdtp_stream_endpoint_context_t; -static avdtp_stream_endpoint_context_t sc; - -static uint8_t int_seid; -// static uint8_t acp_seid; - typedef struct { int16_t source[TABLE_SIZE_441HZ]; int left_phase; int right_phase; } paTestData; +typedef enum { + STREAM_SINE, + STREAM_MOD +} stream_data_source_t; + +static uint8_t media_sbc_codec_capabilities[] = { + 0xFF,//(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO, + 0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS, + 2, 53 +}; + static char * device_name = "A2DP Source BTstack"; // mac 2011: static bd_addr_t remote = {0x04, 0x0C, 0xCE, 0xE4, 0x85, 0xD3}; @@ -116,16 +102,17 @@ static bd_addr_t remote = {0x00, 0x21, 0x3c, 0xac, 0xf7, 0x38}; // bt dongle: -u 02-04-01 // static bd_addr_t remote = {0x00, 0x15, 0x83, 0x5F, 0x9D, 0x46}; -static uint16_t avdtp_cid = 0; static uint8_t sdp_avdtp_source_service_buffer[150]; -static avdtp_stream_endpoint_t * local_stream_endpoint; - -static avdtp_sep_t * active_remote_sep = NULL; - static uint8_t media_sbc_codec_configuration[4]; -static uint8_t sbc_samples_storage[44100*4]; +static uint8_t sbc_samples_storage[44100*4]; +static uint32_t fill_audio_ring_buffer_timeout_ms; +static uint32_t time_audio_data_sent; // ms +static uint32_t acc_num_missed_samples; +static uint32_t samples_ready; +static btstack_timer_source_t fill_audio_ring_buffer_timer; +static btstack_ring_buffer_t sbc_ring_buffer; static paTestData sin_data; @@ -133,23 +120,24 @@ static int hxcmod_initialized = 0; static modcontext mod_context; static tracker_buffer_state trkbuf; - -typedef enum { - STREAM_SINE, - STREAM_MOD -} stream_data_source_t; - +static uint8_t int_seid = 0; +static uint8_t acp_seid = 0; +static uint16_t a2dp_cid = 0; +static int start_streaming_timer = 0; a2dp_state_t app_state = A2DP_IDLE; stream_data_source_t data_source = STREAM_SINE; static btstack_packet_callback_registration_t hci_event_callback_registration; +static void avdtp_fill_audio_ring_buffer_timer_start(void); static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ UNUSED(channel); UNUSED(size); bd_addr_t event_addr; + uint8_t signal_identifier; + uint8_t status; switch (packet_type) { @@ -167,13 +155,36 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe break; case HCI_EVENT_AVDTP_META: switch (packet[2]){ - case AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: { - avdtp_source_stream_send_media_payload(local_stream_endpoint->l2cap_media_cid, &sc.sbc_ring_buffer, 0); - if (btstack_ring_buffer_bytes_available(&sc.sbc_ring_buffer)){ - avdtp_source_stream_endpoint_request_can_send_now(local_stream_endpoint); + case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED: + int_seid = avdtp_subevent_streaming_connection_established_get_int_seid(packet); + acp_seid = avdtp_subevent_streaming_connection_established_get_acp_seid(packet); + a2dp_cid = avdtp_subevent_streaming_connection_established_get_avdtp_cid(packet); + printf(" --- application --- AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED --- a2dp_cid 0x%02x, local seid %d, remote seid %d\n", a2dp_cid, int_seid, acp_seid); + break; + case AVDTP_SUBEVENT_SIGNALING_ACCEPT: + signal_identifier = avdtp_subevent_signaling_accept_get_signal_identifier(packet); + status = avdtp_subevent_signaling_accept_get_status(packet); + printf(" --- application --- Accepted %d\n", signal_identifier); + switch (signal_identifier){ + case AVDTP_SI_START: + if (start_streaming_timer){ + if (avdtp_source_stream_endpoint_ready(int_seid)){ + avdtp_fill_audio_ring_buffer_timer_start(); + start_streaming_timer = 0; + } + } + break; + default: + break; } break; - } + case AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: + avdtp_source_stream_send_media_payload(int_seid, &sbc_ring_buffer, 0); + if (btstack_ring_buffer_bytes_available(&sbc_ring_buffer)){ + avdtp_source_stream_endpoint_request_can_send_now(int_seid); + } + break; + default: app_state = A2DP_IDLE; printf(" --- application --- not implemented\n"); @@ -187,7 +198,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe default: // other packet type break; - } + } } static void show_usage(void){ @@ -196,33 +207,15 @@ static void show_usage(void){ printf("\n--- Bluetooth AVDTP SOURCE Test Console %s ---\n", bd_addr_to_str(iut_address)); printf("c - create connection to addr %s\n", bd_addr_to_str(remote)); printf("C - disconnect\n"); - printf("d - discover stream endpoints\n"); - - if (!active_remote_sep){ - printf("Ctrl-c - exit\n"); - printf("---\n"); - return; - } - printf("m - start stream with %d\n", active_remote_sep->seid); printf("x - start streaming sine\n"); if (hxcmod_initialized){ printf("z - start streaming '%s'\n", mod_name); } printf("X - stop streaming\n"); - printf("A - abort stream with %d\n", active_remote_sep->seid); - printf("S - stop stream with %d\n", active_remote_sep->seid); - printf("P - suspend stream with %d\n", active_remote_sep->seid); printf("Ctrl-c - exit\n"); printf("---\n"); } -static uint8_t media_sbc_codec_capabilities[] = { - 0xFF,//(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO, - 0xFF,//(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS, - 2, 53 -}; - - static void produce_sine_audio(int16_t * pcm_buffer, void *user_data, int num_samples_to_write){ paTestData *data = (paTestData*)user_data; int count; @@ -262,8 +255,8 @@ static int fill_sbc_ring_buffer(void){ int num_audio_samples_per_sbc_buffer = btstack_sbc_encoder_num_audio_frames(); // int audio_bytes_to_read = num_audio_samples_per_sbc_buffer * BYTES_PER_AUDIO_SAMPLE; - while (sc.samples_ready >= num_audio_samples_per_sbc_buffer - && btstack_ring_buffer_bytes_free(&sc.sbc_ring_buffer) >= btstack_sbc_encoder_sbc_buffer_length()){ + while (samples_ready >= num_audio_samples_per_sbc_buffer + && btstack_ring_buffer_bytes_free(&sbc_ring_buffer) >= btstack_sbc_encoder_sbc_buffer_length()){ uint8_t pcm_frame[256*BYTES_PER_AUDIO_SAMPLE]; @@ -275,10 +268,10 @@ static int fill_sbc_ring_buffer(void){ total_num_bytes_read += num_audio_samples_per_sbc_buffer; - if (btstack_ring_buffer_bytes_free(&sc.sbc_ring_buffer) >= sbc_frame_size ){ + if (btstack_ring_buffer_bytes_free(&sbc_ring_buffer) >= sbc_frame_size ){ uint8_t size_buffer = sbc_frame_size; - btstack_ring_buffer_write(&sc.sbc_ring_buffer, &size_buffer, 1); - btstack_ring_buffer_write(&sc.sbc_ring_buffer, sbc_frame, sbc_frame_size); + btstack_ring_buffer_write(&sbc_ring_buffer, &size_buffer, 1); + btstack_ring_buffer_write(&sbc_ring_buffer, sbc_frame, sbc_frame_size); } else { printf("No space in sbc buffer\n"); } @@ -288,51 +281,53 @@ static int fill_sbc_ring_buffer(void){ static void avdtp_fill_audio_ring_buffer_timeout_handler(btstack_timer_source_t * timer){ UNUSED(timer); - btstack_run_loop_set_timer(&sc.fill_audio_ring_buffer_timer, sc.fill_audio_ring_buffer_timeout_ms); // 2 seconds timeout - btstack_run_loop_add_timer(&sc.fill_audio_ring_buffer_timer); + btstack_run_loop_set_timer(&fill_audio_ring_buffer_timer, fill_audio_ring_buffer_timeout_ms); // 2 seconds timeout + btstack_run_loop_add_timer(&fill_audio_ring_buffer_timer); uint32_t now = btstack_run_loop_get_time_ms(); - uint32_t update_period_ms = sc.fill_audio_ring_buffer_timeout_ms; - if (sc.time_audio_data_sent > 0){ - update_period_ms = now - sc.time_audio_data_sent; + uint32_t update_period_ms = fill_audio_ring_buffer_timeout_ms; + if (time_audio_data_sent > 0){ + update_period_ms = now - time_audio_data_sent; } uint32_t num_samples = (update_period_ms * 44100) / 1000; - sc.acc_num_missed_samples += (update_period_ms * 44100) % 1000; + acc_num_missed_samples += (update_period_ms * 44100) % 1000; - if (sc.acc_num_missed_samples >= 1000){ + if (acc_num_missed_samples >= 1000){ num_samples++; - sc.acc_num_missed_samples -= 1000; + acc_num_missed_samples -= 1000; } - sc.time_audio_data_sent = now; - sc.samples_ready += num_samples; + time_audio_data_sent = now; + samples_ready += num_samples; int total_num_bytes_read = fill_sbc_ring_buffer(); // schedule sending if (total_num_bytes_read != 0){ - avdtp_source_stream_endpoint_request_can_send_now(local_stream_endpoint); + avdtp_source_stream_endpoint_request_can_send_now(int_seid); } } static void avdtp_fill_audio_ring_buffer_timer_start(void){ - btstack_run_loop_remove_timer(&sc.fill_audio_ring_buffer_timer); - btstack_run_loop_set_timer_handler(&sc.fill_audio_ring_buffer_timer, avdtp_fill_audio_ring_buffer_timeout_handler); - // btstack_run_loop_set_timer_context(&sc.fill_audio_ring_buffer_timer, stream_endpoint); - btstack_run_loop_set_timer(&sc.fill_audio_ring_buffer_timer, sc.fill_audio_ring_buffer_timeout_ms); // 50 ms timeout - btstack_run_loop_add_timer(&sc.fill_audio_ring_buffer_timer); + btstack_run_loop_remove_timer(&fill_audio_ring_buffer_timer); + btstack_run_loop_set_timer_handler(&fill_audio_ring_buffer_timer, avdtp_fill_audio_ring_buffer_timeout_handler); + // btstack_run_loop_set_timer_context(&fill_audio_ring_buffer_timer, stream_endpoint); + btstack_run_loop_set_timer(&fill_audio_ring_buffer_timer, fill_audio_ring_buffer_timeout_ms); // 50 ms timeout + btstack_run_loop_add_timer(&fill_audio_ring_buffer_timer); } static void avdtp_fill_audio_ring_buffer_timer_stop(void){ - btstack_run_loop_remove_timer(&sc.fill_audio_ring_buffer_timer); + btstack_run_loop_remove_timer(&fill_audio_ring_buffer_timer); } static void avdtp_source_stream_data_start(void){ - if (!avdtp_source_stream_endpoint_ready(local_stream_endpoint)) return; - avdtp_fill_audio_ring_buffer_timer_start(); + printf(" --- application --- avdtp_source_stream_data_start --- local seid %d, remote seid %d\n", int_seid, acp_seid); + a2dp_source_start_stream(a2dp_cid, int_seid, acp_seid); + start_streaming_timer = 1; } static void avdtp_source_stream_data_stop(){ - if (!avdtp_source_stream_endpoint_ready(local_stream_endpoint)) return; + a2dp_source_stop_stream(a2dp_cid, int_seid, acp_seid); + if (!avdtp_source_stream_endpoint_ready(int_seid)) return; avdtp_fill_audio_ring_buffer_timer_stop(); } @@ -350,14 +345,15 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac break; case 'C': printf("Disconnect not implemented\n"); - a2dp_source_disconnect(avdtp_cid); + a2dp_source_disconnect(a2dp_cid); break; case 'x': - // a2dp_source_start_stream(avdtp_cid, int_seid, acp_seid); + avdtp_source_stream_data_start(); + break; + case 'z': avdtp_source_stream_data_start(); break; case 'X': - // a2dp_source_stop_stream(avdtp_cid, int_seid, acp_seid); avdtp_source_stream_data_stop(); break; default: @@ -394,8 +390,8 @@ int btstack_main(int argc, const char * argv[]){ gap_set_class_of_device(0x200408); memset(sbc_samples_storage, 0, sizeof(sbc_samples_storage)); - btstack_ring_buffer_init(&sc.sbc_ring_buffer, sbc_samples_storage, sizeof(sbc_samples_storage)); - sc.fill_audio_ring_buffer_timeout_ms = 50; + btstack_ring_buffer_init(&sbc_ring_buffer, sbc_samples_storage, sizeof(sbc_samples_storage)); + fill_audio_ring_buffer_timeout_ms = 50; /* initialise sinusoidal wavetable */ int i;