mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-25 18:35:17 +00:00
fix sink demo, fix source demo sending audio
This commit is contained in:
parent
60ec20d049
commit
5cfe7f4cc8
@ -559,16 +559,31 @@ void a2dp_source_stream_endpoint_request_can_send_now(uint8_t local_seid){
|
||||
avdtp_request_can_send_now_initiator(stream_endpoint->connection, stream_endpoint->l2cap_media_cid);
|
||||
}
|
||||
|
||||
void a2dp_source_stream_send_media_payload(uint8_t int_seid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker){
|
||||
int a2dp_max_media_payload_size(uint8_t int_seid){
|
||||
avdtp_stream_endpoint_t * stream_endpoint = avdtp_stream_endpoint_for_seid(int_seid, &a2dp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
printf("no stream_endpoint found for seid %d", int_seid);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream_endpoint->l2cap_media_cid == 0){
|
||||
printf("no media cid found for seid %d", int_seid);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
int sbc_header_size = 12;
|
||||
return l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid) - sbc_header_size;
|
||||
}
|
||||
|
||||
int a2dp_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, &a2dp_source_context);
|
||||
if (!stream_endpoint) {
|
||||
printf("no stream_endpoint found for seid %d", int_seid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream_endpoint->l2cap_media_cid == 0){
|
||||
printf("no media cid found for seid %d", int_seid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int size = l2cap_get_remote_mtu_for_local_cid(stream_endpoint->l2cap_media_cid);
|
||||
@ -581,4 +596,5 @@ void a2dp_source_stream_send_media_payload(uint8_t int_seid, btstack_ring_buffer
|
||||
a2dp_source_copy_media_payload(media_packet, size, &offset, sbc_ring_buffer);
|
||||
stream_endpoint->sequence_number++;
|
||||
l2cap_send_prepared(stream_endpoint->l2cap_media_cid, offset);
|
||||
return size;
|
||||
}
|
||||
|
@ -109,7 +109,9 @@ void a2dp_source_disconnect(uint16_t avdtp_cid);
|
||||
|
||||
uint8_t a2dp_source_stream_endpoint_ready(uint8_t local_seid);
|
||||
void a2dp_source_stream_endpoint_request_can_send_now(uint8_t local_seid);
|
||||
void a2dp_source_stream_send_media_payload(uint8_t int_seid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker);
|
||||
int a2dp_source_stream_send_media_payload(uint8_t int_seid, btstack_ring_buffer_t * sbc_ring_buffer, uint8_t marker);
|
||||
int a2dp_max_media_payload_size(uint8_t int_seid);
|
||||
|
||||
/* API_END */
|
||||
|
||||
#if defined __cplusplus
|
||||
|
@ -489,11 +489,13 @@ void avdtp_start_stream(uint8_t int_seid, avdtp_context_t * context){
|
||||
}
|
||||
avdtp_connection_t * connection = stream_endpoint->connection;
|
||||
if (!connection){
|
||||
printf("avdtp_stop_stream: no connection for seid %d found\n",stream_endpoint->sep.seid);
|
||||
printf("avdtp_start_stream: no connection for seid %d found\n",stream_endpoint->sep.seid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->start_stream) return;
|
||||
stream_endpoint->start_stream = 1;
|
||||
connection->int_seid = int_seid;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
@ -510,6 +512,7 @@ void avdtp_stop_stream(uint8_t int_seid, avdtp_context_t * context){
|
||||
}
|
||||
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->stop_stream) return;
|
||||
stream_endpoint->stop_stream = 1;
|
||||
connection->int_seid = int_seid;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
@ -542,6 +545,7 @@ void avdtp_suspend_stream(uint8_t int_seid, avdtp_context_t * context){
|
||||
}
|
||||
if (stream_endpoint->remote_sep_index == 0xFF || stream_endpoint->suspend_stream) return;
|
||||
stream_endpoint->suspend_stream = 1;
|
||||
connection->int_seid = int_seid;
|
||||
avdtp_request_can_send_now_initiator(connection, connection->l2cap_signaling_cid);
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
printf(" ACP: AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION \n");
|
||||
stream_endpoint->acceptor_config_state = AVDTP_ACCEPTOR_W2_ANSWER_SET_CONFIGURATION;
|
||||
connection->reject_service_category = 0;
|
||||
|
||||
stream_endpoint->connection = connection;
|
||||
avdtp_sep_t sep;
|
||||
sep.seid = connection->signaling_packet.command[offset++] >> 2;
|
||||
sep.configured_service_categories = avdtp_unpack_service_capabilities(connection, &sep.configuration, connection->signaling_packet.command+offset, packet_size-offset);
|
||||
@ -238,10 +238,10 @@ void avdtp_acceptor_stream_config_subsm(avdtp_connection_t * connection, uint8_t
|
||||
} else {
|
||||
// add new
|
||||
printf(" ACP: seid %d not found in %p\n", sep.seid, stream_endpoint);
|
||||
stream_endpoint->remote_sep_index = stream_endpoint->connection->remote_seps_num;
|
||||
stream_endpoint->connection->remote_seps_num++;
|
||||
stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
printf(" ACP: add seid %d, to %p\n", stream_endpoint->connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
stream_endpoint->remote_sep_index = connection->remote_seps_num;
|
||||
connection->remote_seps_num++;
|
||||
connection->remote_seps[stream_endpoint->remote_sep_index] = sep;
|
||||
printf(" ACP: add seid %d, to %p\n", connection->remote_seps[stream_endpoint->remote_sep_index].seid, stream_endpoint);
|
||||
}
|
||||
if (get_bit16(sep.configured_service_categories, AVDTP_MEDIA_CODEC)){
|
||||
switch (sep.configuration.media_codec.media_codec_type){
|
||||
|
@ -206,6 +206,7 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
|
||||
log_error("AVDTP_SI_START in wrong stream endpoint state");
|
||||
return;
|
||||
}
|
||||
printf("AVDTP_STREAM_ENDPOINT_STREAMING\n");
|
||||
stream_endpoint->state = AVDTP_STREAM_ENDPOINT_STREAMING;
|
||||
break;
|
||||
case AVDTP_SI_SUSPEND:
|
||||
@ -247,7 +248,6 @@ void avdtp_initiator_stream_config_subsm(avdtp_connection_t * connection, uint8_
|
||||
|
||||
void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, avdtp_context_t * context){
|
||||
int sent = 1;
|
||||
|
||||
switch (connection->initiator_connection_state){
|
||||
case AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS:
|
||||
printf(" INT: AVDTP_SIGNALING_CONNECTION_INITIATOR_W2_DISCOVER_SEPS\n");
|
||||
@ -276,15 +276,16 @@ void avdtp_initiator_stream_config_subsm_run(avdtp_connection_t * connection, av
|
||||
|
||||
if (sent) return;
|
||||
sent = 1;
|
||||
avdtp_stream_endpoint_t * stream_endpoint = NULL;
|
||||
printf("avdtp_initiator_stream_config_subsm_run, acp seid %d\n", connection->acp_seid);
|
||||
|
||||
// printf(" run int seid %d, acp seid %d\n", connection->int_seid, connection->acp_seid);
|
||||
avdtp_stream_endpoint_t * stream_endpoint = NULL;
|
||||
|
||||
stream_endpoint = avdtp_stream_endpoint_associated_with_acp_seid(connection->acp_seid, context);
|
||||
if (!stream_endpoint){
|
||||
stream_endpoint = avdtp_stream_endpoint_with_seid(connection->int_seid, context);
|
||||
}
|
||||
if (!stream_endpoint) return;
|
||||
printf(" avdtp_initiator_stream_config_subsm_run 1\n");
|
||||
|
||||
avdtp_initiator_stream_endpoint_state_t stream_endpoint_state = stream_endpoint->initiator_config_state;
|
||||
stream_endpoint->initiator_config_state = AVDTP_INITIATOR_W4_ANSWER;
|
||||
|
@ -134,9 +134,9 @@ typedef struct {
|
||||
} avdtp_media_codec_configuration_sbc_t;
|
||||
|
||||
// mac 2011: static bd_addr_t remote = {0x04, 0x0C, 0xCE, 0xE4, 0x85, 0xD3};
|
||||
// pts:
|
||||
static bd_addr_t remote = {0x00, 0x1B, 0xDC, 0x08, 0x0A, 0xA5};
|
||||
// mac 2013: static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
|
||||
// pts: static bd_addr_t remote = {0x00, 0x1B, 0xDC, 0x08, 0x0A, 0xA5};
|
||||
// mac 2013:
|
||||
static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xd1, 0x15};
|
||||
|
||||
// bt dongle: -u 02-02 static bd_addr_t remote = {0x00, 0x02, 0x72, 0xDC, 0x31, 0xC1};
|
||||
|
||||
@ -489,6 +489,9 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED:
|
||||
// printf("AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED, local seid %d, remote seid index %d \n", local_stream_endpoint->sep.seid, );
|
||||
break;
|
||||
case AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY:
|
||||
printf(" received non SBC codec. not implemented\n");
|
||||
break;
|
||||
@ -604,6 +607,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
|
||||
avdtp_sink_open_stream(avdtp_cid, local_stream_endpoint->sep.seid, sep.seid);
|
||||
break;
|
||||
case 'm':
|
||||
printf("AVDTP_APPLICATION_W2_START_STREAM_WITH_SEID \n");
|
||||
app_state = AVDTP_APPLICATION_W2_START_STREAM_WITH_SEID;
|
||||
avdtp_sink_start_stream(local_stream_endpoint->sep.seid);
|
||||
break;
|
||||
|
@ -105,7 +105,7 @@ static bd_addr_t remote = {0x00, 0x21, 0x3c, 0xac, 0xf7, 0x38};
|
||||
|
||||
static uint8_t sdp_avdtp_source_service_buffer[150];
|
||||
static uint8_t media_sbc_codec_configuration[4];
|
||||
static uint8_t sbc_storage[44100*4];
|
||||
static uint8_t sbc_storage[2000*4];
|
||||
|
||||
typedef struct {
|
||||
uint16_t a2dp_cid;
|
||||
@ -119,6 +119,7 @@ typedef struct {
|
||||
uint32_t paused_at_ms;
|
||||
uint8_t paused;
|
||||
|
||||
int max_media_payload_size;
|
||||
btstack_ring_buffer_t sbc_ring_buffer;
|
||||
} a2dp_media_sending_context_t;
|
||||
|
||||
@ -163,14 +164,13 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
printf(" --- application --- A2DP_SUBEVENT_STREAM_START_ACCEPTED, local seid %d\n", media_tracker.local_seid);
|
||||
break;
|
||||
|
||||
case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
|
||||
case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
|
||||
if (local_seid != media_tracker.local_seid) break;
|
||||
a2dp_source_stream_send_media_payload(media_tracker.local_seid, &media_tracker.sbc_ring_buffer, 0);
|
||||
if (btstack_ring_buffer_bytes_available(&media_tracker.sbc_ring_buffer)){
|
||||
a2dp_source_stream_endpoint_request_can_send_now(media_tracker.local_seid);
|
||||
}
|
||||
break;
|
||||
|
||||
case A2DP_SUBEVENT_STREAM_SUSPENDED:
|
||||
printf(" --- application --- A2DP_SUBEVENT_STREAM_SUSPENDED, local seid %d\n", media_tracker.local_seid);
|
||||
a2dp_fill_audio_ring_buffer_timer_pause(&media_tracker);
|
||||
@ -262,14 +262,13 @@ static int fill_sbc_ring_buffer(a2dp_media_sending_context_t * context){
|
||||
|
||||
total_num_bytes_read += num_audio_samples_per_sbc_buffer;
|
||||
|
||||
if (btstack_ring_buffer_bytes_free(&context->sbc_ring_buffer) >= sbc_frame_size ){
|
||||
uint8_t size_buffer = sbc_frame_size;
|
||||
btstack_ring_buffer_write(&context->sbc_ring_buffer, &size_buffer, 1);
|
||||
btstack_ring_buffer_write(&context->sbc_ring_buffer, sbc_frame, sbc_frame_size);
|
||||
} else {
|
||||
printf("No space in sbc buffer\n");
|
||||
}
|
||||
uint8_t size_buffer = sbc_frame_size;
|
||||
btstack_ring_buffer_write(&context->sbc_ring_buffer, &size_buffer, 1);
|
||||
btstack_ring_buffer_write(&context->sbc_ring_buffer, sbc_frame, sbc_frame_size);
|
||||
|
||||
context->samples_ready -= num_audio_samples_per_sbc_buffer;
|
||||
}
|
||||
|
||||
return total_num_bytes_read;
|
||||
}
|
||||
|
||||
@ -290,25 +289,29 @@ static void avdtp_fill_audio_ring_buffer_timeout_handler(btstack_timer_source_t
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t num_samples = (update_period_ms * 44100) / 1000;
|
||||
context->acc_num_missed_samples += (update_period_ms * 44100) % 1000;
|
||||
|
||||
if (context->acc_num_missed_samples >= 1000){
|
||||
uint32_t num_samples = (update_period_ms * SAMPLE_RATE) / 1000;
|
||||
context->acc_num_missed_samples += (update_period_ms * SAMPLE_RATE) % 1000;
|
||||
printf("acc_num_missed_samples: %d\n", context->acc_num_missed_samples);
|
||||
|
||||
while (context->acc_num_missed_samples >= 1000){
|
||||
num_samples++;
|
||||
context->acc_num_missed_samples -= 1000;
|
||||
}
|
||||
|
||||
context->time_audio_data_sent = now;
|
||||
context->samples_ready += num_samples;
|
||||
|
||||
int total_num_bytes_read = fill_sbc_ring_buffer(context);
|
||||
// schedule sending
|
||||
if (total_num_bytes_read != 0){
|
||||
// schedule sending
|
||||
printf("samples ready: %d, total bytes read %d\n", context->samples_ready, total_num_bytes_read);
|
||||
|
||||
if (btstack_ring_buffer_bytes_available(&context->sbc_ring_buffer) > context->max_media_payload_size){
|
||||
log_info("Request can send now AUDIO");
|
||||
a2dp_source_stream_endpoint_request_can_send_now(context->local_seid);
|
||||
}
|
||||
}
|
||||
|
||||
static void a2dp_fill_audio_ring_buffer_timer_start(a2dp_media_sending_context_t * context){
|
||||
context->max_media_payload_size = a2dp_max_media_payload_size(context->local_seid);
|
||||
btstack_run_loop_remove_timer(&context->fill_audio_ring_buffer_timer);
|
||||
btstack_run_loop_set_timer_handler(&context->fill_audio_ring_buffer_timer, avdtp_fill_audio_ring_buffer_timeout_handler);
|
||||
btstack_run_loop_set_timer_context(&context->fill_audio_ring_buffer_timer, context);
|
||||
@ -319,19 +322,21 @@ static void a2dp_fill_audio_ring_buffer_timer_start(a2dp_media_sending_context_t
|
||||
static void a2dp_fill_audio_ring_buffer_timer_stop(a2dp_media_sending_context_t * context){
|
||||
context->paused_at_ms = 0;
|
||||
context->time_audio_data_sent = 0;
|
||||
context->acc_num_missed_samples = 0;
|
||||
context->samples_ready = 0;
|
||||
btstack_run_loop_remove_timer(&context->fill_audio_ring_buffer_timer);
|
||||
}
|
||||
|
||||
static void a2dp_fill_audio_ring_buffer_timer_pause(a2dp_media_sending_context_t * context){
|
||||
context->paused_at_ms = btstack_run_loop_get_time_ms();
|
||||
context->time_audio_data_sent = 0;
|
||||
// context->time_audio_data_sent = 0;
|
||||
btstack_run_loop_remove_timer(&context->fill_audio_ring_buffer_timer);
|
||||
}
|
||||
|
||||
static void a2dp_init_media_tracker(a2dp_media_sending_context_t * context, uint8_t * storage, int size){
|
||||
memset(storage, 0, size);
|
||||
btstack_ring_buffer_init(&context->sbc_ring_buffer, storage, size);
|
||||
context->fill_audio_ring_buffer_timeout_ms = 50;
|
||||
context->fill_audio_ring_buffer_timeout_ms = 10;
|
||||
}
|
||||
|
||||
|
||||
@ -406,7 +411,7 @@ int btstack_main(int argc, const char * argv[]){
|
||||
|
||||
hxcmod_initialized = hxcmod_init(&mod_context);
|
||||
if (hxcmod_initialized){
|
||||
hxcmod_setcfg(&mod_context, 44100, 16, 1, 1, 1);
|
||||
hxcmod_setcfg(&mod_context, SAMPLE_RATE, 16, 1, 1, 1);
|
||||
hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
|
||||
printf("loaded mod '%s', size %u\n", mod_name, mod_len);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user