From 80dc0088566a9de874b4f02188ffe2b21a501361 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Tue, 22 Dec 2020 17:38:17 +0100 Subject: [PATCH] avdtp: use frequency in hz and general channel mode for sbc config --- src/classic/a2dp_source.c | 52 ++++++++++++++++++++++++++++++--------- src/classic/a2dp_source.h | 2 +- src/classic/avdtp.c | 47 +++++++++++++++++------------------ src/classic/avdtp.h | 6 ++--- 4 files changed, 68 insertions(+), 39 deletions(-) diff --git a/src/classic/a2dp_source.c b/src/classic/a2dp_source.c index e4fe8108c..19e2254f9 100644 --- a/src/classic/a2dp_source.c +++ b/src/classic/a2dp_source.c @@ -369,13 +369,13 @@ static void a2dp_source_packet_handler_internal(uint8_t packet_type, uint16_t ch // select SEP if none configured yet if (a2dp_source_have_config == false){ // choose SBC config params - uint8_t sampling_frequency = avdtp_choose_sbc_sampling_frequency(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet)); - uint8_t channel_mode = avdtp_choose_sbc_channel_mode(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet)); - uint8_t block_length = avdtp_choose_sbc_block_length(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet)); - uint8_t subbands = avdtp_choose_sbc_subbands(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(packet)); - uint8_t allocation_method = avdtp_choose_sbc_allocation_method(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(packet)); - uint8_t max_bitpool_value = avdtp_choose_sbc_max_bitpool_value(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet)); - uint8_t min_bitpool_value = avdtp_choose_sbc_min_bitpool_value(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet)); + uint16_t sampling_frequency = avdtp_choose_sbc_sampling_frequency(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(packet)); + avdtp_channel_mode_t channel_mode = avdtp_choose_sbc_channel_mode(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(packet)); + uint8_t block_length = avdtp_choose_sbc_block_length(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(packet)); + uint8_t subbands = avdtp_choose_sbc_subbands(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(packet)); + avdtp_sbc_allocation_method_t allocation_method = avdtp_choose_sbc_allocation_method(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(packet)); + uint8_t max_bitpool_value = avdtp_choose_sbc_max_bitpool_value(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(packet)); + uint8_t min_bitpool_value = avdtp_choose_sbc_min_bitpool_value(sc.local_stream_endpoint, avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(packet)); // and pre-select this (safe) endpoint uint8_t local_seid = avdtp_stream_endpoint_seid(sc.local_stream_endpoint); @@ -810,9 +810,39 @@ uint8_t a2dp_source_stream_send_media_packet(uint16_t a2dp_cid, uint8_t local_se return avdtp_source_stream_send_media_packet(a2dp_cid, local_seid, packet, size); } -static void avdtp_config_sbc_store(uint8_t * config, uint16_t sampling_frequency, avdtp_sbc_channel_mode_t channel_mode, uint8_t block_length, uint8_t subbands, +static void avdtp_config_sbc_store(uint8_t * config, uint16_t sampling_frequency_hz, avdtp_channel_mode_t channel_mode, uint8_t block_length, uint8_t subbands, avdtp_sbc_allocation_method_t allocation_method, uint8_t min_bitpool_value, uint8_t max_bitpool_value) { - config[0] = (sampling_frequency << 4) | channel_mode; + avdtp_sbc_sampling_frequency_t sampling_frequency; + switch (sampling_frequency_hz){ + case 16000: + sampling_frequency = AVDTP_SBC_16000; + break; + case 32000: + sampling_frequency = AVDTP_SBC_32000; + break; + case 48000: + sampling_frequency = AVDTP_SBC_48000; + break; + default: + sampling_frequency = AVDTP_SBC_44100; + break; + } + avdtp_sbc_channel_mode_t sbc_channel_mode; + switch (channel_mode){ + case AVDTP_CHANNEL_MODE_MONO: + sbc_channel_mode = AVDTP_SBC_MONO; + break; + case AVDTP_CHANNEL_MODE_DUAL_CHANNEL: + sbc_channel_mode = AVDTP_SBC_DUAL_CHANNEL; + break; + case AVDTP_CHANNEL_MODE_STEREO: + sbc_channel_mode = AVDTP_SBC_STEREO; + break; + default: + sbc_channel_mode = AVDTP_SBC_JOINT_STEREO; + break; + } + config[0] = (((uint8_t) sampling_frequency) << 4) | ((uint8_t) sbc_channel_mode); config[1] = (block_length << 4) | (subbands << 2) | allocation_method; config[2] = min_bitpool_value; config[3] = max_bitpool_value; @@ -930,8 +960,8 @@ static void a2dp_source_config_init(uint8_t remote_seid, avdtp_media_codec_type_ a2dp_source_have_config = true; } -uint8_t a2dp_source_set_config_sbc(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t sampling_frequency, avdtp_sbc_channel_mode_t channel_mode, - uint8_t block_length, uint8_t subbands, avdtp_sbc_allocation_method_t allocation_method, uint8_t min_bitpool_value, uint8_t max_bitpool_value){ +uint8_t a2dp_source_set_config_sbc(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t sampling_frequency, avdtp_channel_mode_t channel_mode, + uint8_t block_length, uint8_t subbands, avdtp_sbc_allocation_method_t allocation_method, uint8_t min_bitpool_value, uint8_t max_bitpool_value){ UNUSED(local_seid); diff --git a/src/classic/a2dp_source.h b/src/classic/a2dp_source.h index e04986126..b67091ed8 100644 --- a/src/classic/a2dp_source.h +++ b/src/classic/a2dp_source.h @@ -198,7 +198,7 @@ uint8_t a2dp_source_stream_send_media_packet(uint16_t a2dp_cid, uint8_t local_se * @param max_bitpool_value * @return status */ -uint8_t a2dp_source_set_config_sbc(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t sampling_frequency, avdtp_sbc_channel_mode_t channel_mode, +uint8_t a2dp_source_set_config_sbc(uint16_t a2dp_cid, uint8_t local_seid, uint8_t remote_seid, uint16_t sampling_frequency, avdtp_channel_mode_t channel_mode, uint8_t block_length, uint8_t subbands, avdtp_sbc_allocation_method_t allocation_method, uint8_t min_bitpool_value, uint8_t max_bitpool_value); /** diff --git a/src/classic/avdtp.c b/src/classic/avdtp.c index d6393364d..d1054592f 100644 --- a/src/classic/avdtp.c +++ b/src/classic/avdtp.c @@ -1325,41 +1325,40 @@ void avdtp_set_preferred_channel_mode(avdtp_stream_endpoint_t * stream_endpoi } -uint8_t avdtp_choose_sbc_channel_mode(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_channel_mode_bitmap){ +avdtp_channel_mode_t avdtp_choose_sbc_channel_mode(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_channel_mode_bitmap){ uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information; uint8_t channel_mode_bitmap = (media_codec[0] & 0x0F) & remote_channel_mode_bitmap; - - uint8_t channel_mode = AVDTP_SBC_STEREO; + // use preferred channel mode if possible if (stream_endpoint->preferred_channel_mode == AVDTP_SBC_JOINT_STEREO){ - return AVDTP_SBC_JOINT_STEREO; + return AVDTP_CHANNEL_MODE_JOINT_STEREO; } if (stream_endpoint->preferred_channel_mode == AVDTP_SBC_STEREO){ - return AVDTP_SBC_STEREO; + return AVDTP_CHANNEL_MODE_STEREO; } if (stream_endpoint->preferred_channel_mode == AVDTP_SBC_DUAL_CHANNEL){ - return AVDTP_SBC_DUAL_CHANNEL; + return AVDTP_CHANNEL_MODE_DUAL_CHANNEL; } if (stream_endpoint->preferred_channel_mode == AVDTP_SBC_MONO){ - return AVDTP_SBC_MONO; + return AVDTP_CHANNEL_MODE_MONO; } if (channel_mode_bitmap & AVDTP_SBC_JOINT_STEREO){ - channel_mode = AVDTP_SBC_JOINT_STEREO; + return AVDTP_CHANNEL_MODE_JOINT_STEREO; } else if (channel_mode_bitmap & AVDTP_SBC_STEREO){ - channel_mode = AVDTP_SBC_STEREO; + return AVDTP_CHANNEL_MODE_STEREO; } else if (channel_mode_bitmap & AVDTP_SBC_DUAL_CHANNEL){ - channel_mode = AVDTP_SBC_DUAL_CHANNEL; + return AVDTP_CHANNEL_MODE_DUAL_CHANNEL; } else if (channel_mode_bitmap & AVDTP_SBC_MONO){ - channel_mode = AVDTP_SBC_MONO; + return AVDTP_CHANNEL_MODE_MONO; } - return channel_mode; + return AVDTP_CHANNEL_MODE_JOINT_STEREO; } -uint8_t avdtp_choose_sbc_allocation_method(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_allocation_method_bitmap){ +avdtp_sbc_allocation_method_t avdtp_choose_sbc_allocation_method(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_allocation_method_bitmap){ uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information; - uint8_t allocation_method_bitmap = (media_codec[1] & 0x03) & remote_allocation_method_bitmap; + avdtp_sbc_allocation_method_t allocation_method_bitmap = (media_codec[1] & 0x03) & remote_allocation_method_bitmap; uint8_t allocation_method = AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS; if (allocation_method_bitmap & AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS){ @@ -1406,39 +1405,39 @@ uint8_t avdtp_choose_sbc_block_length(avdtp_stream_endpoint_t * stream_endpoint, return block_length; } -uint8_t avdtp_choose_sbc_sampling_frequency(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_sampling_frequency_bitmap){ +uint16_t avdtp_choose_sbc_sampling_frequency(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_sampling_frequency_bitmap){ if (!stream_endpoint) return 0; uint8_t * media_codec = stream_endpoint->sep.capabilities.media_codec.media_codec_information; uint8_t supported_sampling_frequency_bitmap = (media_codec[0] >> 4) & remote_sampling_frequency_bitmap; // use preferred sampling frequency if possible if ((stream_endpoint->preferred_sampling_frequency == 48000) && (supported_sampling_frequency_bitmap & AVDTP_SBC_48000)){ - return AVDTP_SBC_48000; + return stream_endpoint->preferred_sampling_frequency; } if ((stream_endpoint->preferred_sampling_frequency == 44100) && (supported_sampling_frequency_bitmap & AVDTP_SBC_44100)){ - return AVDTP_SBC_44100; + return stream_endpoint->preferred_sampling_frequency; } if ((stream_endpoint->preferred_sampling_frequency == 32000) && (supported_sampling_frequency_bitmap & AVDTP_SBC_32000)){ - return AVDTP_SBC_32000; + return stream_endpoint->preferred_sampling_frequency; } if ((stream_endpoint->preferred_sampling_frequency == 16000) && (supported_sampling_frequency_bitmap & AVDTP_SBC_16000)){ - return AVDTP_SBC_16000; + return stream_endpoint->preferred_sampling_frequency; } // otherwise, use highest available if (supported_sampling_frequency_bitmap & AVDTP_SBC_48000){ - return AVDTP_SBC_48000; + return 48000; } if (supported_sampling_frequency_bitmap & AVDTP_SBC_44100){ - return AVDTP_SBC_44100; + return 44100; } if (supported_sampling_frequency_bitmap & AVDTP_SBC_32000){ - return AVDTP_SBC_32000; + return 32000; } if (supported_sampling_frequency_bitmap & AVDTP_SBC_16000){ - return AVDTP_SBC_16000; + return 16000; } - return AVDTP_SBC_44100; // some default + return 44100; // some default } uint8_t avdtp_choose_sbc_max_bitpool_value(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_max_bitpool_value){ diff --git a/src/classic/avdtp.h b/src/classic/avdtp.h index 778749e84..542cf69ad 100644 --- a/src/classic/avdtp.h +++ b/src/classic/avdtp.h @@ -629,9 +629,9 @@ void avdtp_set_preferred_channel_mode(avdtp_stream_endpoint_t * stream_endpoi void avdtp_set_preferred_sbc_channel_mode(avdtp_stream_endpoint_t * stream_endpoint, uint32_t sampling_frequency); -uint8_t avdtp_choose_sbc_channel_mode(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_channel_mode_bitmap); -uint8_t avdtp_choose_sbc_allocation_method(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_allocation_method_bitmap); -uint8_t avdtp_choose_sbc_sampling_frequency(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_sampling_frequency_bitmap); +avdtp_channel_mode_t avdtp_choose_sbc_channel_mode(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_channel_mode_bitmap); +avdtp_sbc_allocation_method_t avdtp_choose_sbc_allocation_method(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_allocation_method_bitmap); +uint16_t avdtp_choose_sbc_sampling_frequency(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_sampling_frequency_bitmap); uint8_t avdtp_choose_sbc_subbands(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_subbands_bitmap); uint8_t avdtp_choose_sbc_block_length(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_block_length_bitmap); uint8_t avdtp_choose_sbc_max_bitpool_value(avdtp_stream_endpoint_t * stream_endpoint, uint8_t remote_max_bitpool_value);