15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 35b790feeeb211c42bf78ca3ae9c26aa30e516765Jakub Pawlowski * Copyright 2002-2012 Broadcom Corporation 45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * you may not use this file except in compliance with the License. 75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * You may obtain a copy of the License at: 85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * See the License for the specific language governing permissions and 155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * limitations under the License. 165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/ 185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Utility functions to help build and parse SBC Codec Information Element 225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * and Media Payload. 235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/ 255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 26f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov#define LOG_TAG "a2dp_sbc" 2779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_target.h" 2924ff5af9e40aaebc236bb6a16849c63bff0f23baSharvil Nanavati 305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#include "a2dp_sbc.h" 315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h> 335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#include <base/logging.h> 357e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest#include "a2dp_sbc_decoder.h" 36f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov#include "a2dp_sbc_encoder.h" 370df29ac95d057a1bf74b003fa6dd6459743bcf54Mike J. Chen#include "bt_utils.h" 38d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov#include "embdrv/sbc/encoder/include/sbc_encoder.h" 3979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov#include "osi/include/log.h" 40b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov#include "osi/include/osi.h" 4179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 42397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov#define A2DP_SBC_MAX_BITPOOL 53 4379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 44feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov/* data type for the SBC Codec Information Element */ 45397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovtypedef struct { 46397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t samp_freq; /* Sampling frequency */ 47397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t ch_mode; /* Channel mode */ 48397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t block_len; /* Block length */ 49397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t num_subbands; /* Number of subbands */ 50397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t alloc_method; /* Allocation method */ 51397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t min_bitpool; /* Minimum bitpool */ 52397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t max_bitpool; /* Maximum bitpool */ 53494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov btav_a2dp_codec_bits_per_sample_t bits_per_sample; 54f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov} tA2DP_SBC_CIE; 55b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 56cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov/* SBC Source codec capabilities */ 57cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavovstatic const tA2DP_SBC_CIE a2dp_sbc_source_caps = { 584ed1875cc00071c841068e8bdee07fdcefe5fdf3Sunny Kapdi (A2DP_SBC_IE_SAMP_FREQ_44), /* samp_freq */ 59444ea2c15a24cabaae87c8806b5d50e6ecb9a24dkoh.changseok (A2DP_SBC_IE_CH_MD_MONO | A2DP_SBC_IE_CH_MD_JOINT), /* ch_mode */ 60444ea2c15a24cabaae87c8806b5d50e6ecb9a24dkoh.changseok (A2DP_SBC_IE_BLOCKS_16 | A2DP_SBC_IE_BLOCKS_12 | A2DP_SBC_IE_BLOCKS_8 | 61444ea2c15a24cabaae87c8806b5d50e6ecb9a24dkoh.changseok A2DP_SBC_IE_BLOCKS_4), /* block_len */ 62494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ 63494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ 64494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 65494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_MAX_BITPOOL, /* max_bitpool */ 66494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */ 6779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 6879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 69cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov/* SBC Sink codec capabilities */ 70397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovstatic const tA2DP_SBC_CIE a2dp_sbc_sink_caps = { 71397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_SAMP_FREQ_48 | A2DP_SBC_IE_SAMP_FREQ_44), /* samp_freq */ 72f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov (A2DP_SBC_IE_CH_MD_MONO | A2DP_SBC_IE_CH_MD_STEREO | 73397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_CH_MD_JOINT | A2DP_SBC_IE_CH_MD_DUAL), /* ch_mode */ 74397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_BLOCKS_16 | A2DP_SBC_IE_BLOCKS_12 | A2DP_SBC_IE_BLOCKS_8 | 75397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_BLOCKS_4), /* block_len */ 76397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_SUBBAND_4 | A2DP_SBC_IE_SUBBAND_8), /* num_subbands */ 77397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_ALLOC_MD_L | A2DP_SBC_IE_ALLOC_MD_S), /* alloc_method */ 78397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 79494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_MAX_BITPOOL, /* max_bitpool */ 80494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */ 8179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 8279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 8379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* Default SBC codec configuration */ 84397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst tA2DP_SBC_CIE a2dp_sbc_default_config = { 85494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */ 86494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_IE_CH_MD_JOINT, /* ch_mode */ 87494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_IE_BLOCKS_16, /* block_len */ 88494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ 89494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ 90494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 91494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov A2DP_SBC_MAX_BITPOOL, /* max_bitpool */ 92494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */ 9379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 940df29ac95d057a1bf74b003fa6dd6459743bcf54Mike J. Chen 95f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic const tA2DP_ENCODER_INTERFACE a2dp_encoder_interface_sbc = { 96f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_encoder_init, 97f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_encoder_cleanup, 98f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_feeding_reset, 99f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_feeding_flush, 100f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_get_encoder_interval_ms, 101f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_send_frames, 102302113d4e44f06e90f90a5903e33ae830edb58a3Pavlin Radoslavov nullptr // set_transmit_queue_length 103302113d4e44f06e90f90a5903e33ae830edb58a3Pavlin Radoslavov}; 1041394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 1057e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forreststatic const tA2DP_DECODER_INTERFACE a2dp_decoder_interface_sbc = { 1067e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest a2dp_sbc_decoder_init, a2dp_sbc_decoder_cleanup, 1077e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest a2dp_sbc_decoder_decode_packet, 1087e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest}; 1097e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest 110f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic tA2DP_STATUS A2DP_CodecInfoMatchesCapabilitySbc( 111397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const tA2DP_SBC_CIE* p_cap, const uint8_t* p_codec_info, 1125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov bool is_capability); 113feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovstatic void A2DP_ParseMplHeaderSbc(uint8_t* p_src, bool* p_frag, bool* p_start, 114feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov bool* p_last, uint8_t* p_num); 115b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 116b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Builds the SBC Media Codec Capabilities byte sequence beginning from the 117b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// LOSC octet. |media_type| is the media type |AVDT_MEDIA_TYPE_*|. 118b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// |p_ie| is a pointer to the SBC Codec Information Element information. 119f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov// The result is stored in |p_result|. Returns A2DP_SUCCESS on success, 120b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// otherwise the corresponding A2DP error status code. 121feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovstatic tA2DP_STATUS A2DP_BuildInfoSbc(uint8_t media_type, 122feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov const tA2DP_SBC_CIE* p_ie, 123feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov uint8_t* p_result) { 124397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie == NULL || p_result == NULL || 125397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->samp_freq & ~A2DP_SBC_IE_SAMP_FREQ_MSK) || 126397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->ch_mode & ~A2DP_SBC_IE_CH_MD_MSK) || 127397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->block_len & ~A2DP_SBC_IE_BLOCKS_MSK) || 128397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->num_subbands & ~A2DP_SBC_IE_SUBBAND_MSK) || 129397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->alloc_method & ~A2DP_SBC_IE_ALLOC_MD_MSK) || 130397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->min_bitpool > p_ie->max_bitpool) || 131397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->min_bitpool < A2DP_SBC_IE_MIN_BITPOOL) || 132397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->min_bitpool > A2DP_SBC_IE_MAX_BITPOOL) || 133397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->max_bitpool < A2DP_SBC_IE_MIN_BITPOOL) || 134397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->max_bitpool > A2DP_SBC_IE_MAX_BITPOOL)) { 135397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* if any unused bit is set */ 136d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_INVALID_PARAMS; 137d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov } 138397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 139d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = A2DP_SBC_INFO_LEN; 140d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = (media_type << 4); 141d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = A2DP_MEDIA_CT_SBC; 142397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 143d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov /* Media Codec Specific Information Element */ 144d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = p_ie->samp_freq | p_ie->ch_mode; 145397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 146d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = p_ie->block_len | p_ie->num_subbands | p_ie->alloc_method; 147d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov 148d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = p_ie->min_bitpool; 149d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result = p_ie->max_bitpool; 150d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov 151d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_SUCCESS; 1525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 154b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Parses the SBC Media Codec Capabilities byte sequence beginning from the 155b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// LOSC octet. The result is stored in |p_ie|. The byte sequence to parse is 1565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |p_codec_info|. If |is_capability| is true, the byte sequence contains 1575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// codec capability. 158feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov// Returns A2DP_SUCCESS on success, otherwise the corresponding A2DP error 159feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov// status code. 160feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovstatic tA2DP_STATUS A2DP_ParseInfoSbc(tA2DP_SBC_CIE* p_ie, 161feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov const uint8_t* p_codec_info, 1625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov bool is_capability) { 163397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t losc; 164397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t media_type; 165397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type; 166397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 167397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie == NULL || p_codec_info == NULL) return A2DP_INVALID_PARAMS; 168397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 169397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the codec capability length 170397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov losc = *p_codec_info++; 171397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (losc != A2DP_SBC_INFO_LEN) return A2DP_WRONG_CODEC; 172397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 173397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov media_type = (*p_codec_info++) >> 4; 174397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov codec_type = *p_codec_info++; 175397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Check the Media Type and Media Codec Type */ 176397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (media_type != AVDT_MEDIA_TYPE_AUDIO || codec_type != A2DP_MEDIA_CT_SBC) { 177397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_WRONG_CODEC; 178397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 179397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 180397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->samp_freq = *p_codec_info & A2DP_SBC_IE_SAMP_FREQ_MSK; 181397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->ch_mode = *p_codec_info & A2DP_SBC_IE_CH_MD_MSK; 182397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_codec_info++; 183397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->block_len = *p_codec_info & A2DP_SBC_IE_BLOCKS_MSK; 184397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->num_subbands = *p_codec_info & A2DP_SBC_IE_SUBBAND_MSK; 185397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->alloc_method = *p_codec_info & A2DP_SBC_IE_ALLOC_MD_MSK; 186397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_codec_info++; 187397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->min_bitpool = *p_codec_info++; 188d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov p_ie->max_bitpool = *p_codec_info++; 189397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie->min_bitpool < A2DP_SBC_IE_MIN_BITPOOL || 190397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->min_bitpool > A2DP_SBC_IE_MAX_BITPOOL) { 191d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_MIN_BITPOOL; 192397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 193397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 194397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie->max_bitpool < A2DP_SBC_IE_MIN_BITPOOL || 195397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->max_bitpool > A2DP_SBC_IE_MAX_BITPOOL || 196397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->max_bitpool < p_ie->min_bitpool) { 197d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_MAX_BITPOOL; 198397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 199397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 200d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov if (is_capability) return A2DP_SUCCESS; 201397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 202397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->samp_freq) != A2DP_SET_ONE_BIT) 203d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_SAMP_FREQ; 204d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov if (A2DP_BitsSet(p_ie->ch_mode) != A2DP_SET_ONE_BIT) return A2DP_BAD_CH_MODE; 205397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->block_len) != A2DP_SET_ONE_BIT) 206d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_BLOCK_LEN; 207397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->num_subbands) != A2DP_SET_ONE_BIT) 208d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_SUBBANDS; 209397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->alloc_method) != A2DP_SET_ONE_BIT) 210d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_ALLOC_METHOD; 211397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 212d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_SUCCESS; 2135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 215cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// Build the SBC Media Payload Header. 216cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// |p_dst| points to the location where the header should be written to. 217cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// If |frag| is true, the media payload frame is fragmented. 218cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// |start| is true for the first packet of a fragmented frame. 219cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// |last| is true for the last packet of a fragmented frame. 220cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// If |frag| is false, |num| is the number of number of frames in the packet, 221cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// otherwise is the number of remaining fragments (including this one). 222cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic void A2DP_BuildMediaPayloadHeaderSbc(uint8_t* p_dst, bool frag, 223cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov bool start, bool last, 224cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov uint8_t num) { 225397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_dst == NULL) return; 226397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 227397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_dst = 0; 228397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (frag) *p_dst |= A2DP_SBC_HDR_F_MSK; 229397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (start) *p_dst |= A2DP_SBC_HDR_S_MSK; 230397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (last) *p_dst |= A2DP_SBC_HDR_L_MSK; 231397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_dst |= (A2DP_SBC_HDR_NUM_MSK & num); 2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 235ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 236ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function A2DP_ParseMplHeaderSbc 237ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 238ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called by an application to parse 239ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * the SBC Media Payload header. 240ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Input Parameters: 241ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_src: the byte sequence to parse.. 242ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 243ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Output Parameters: 244ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * frag: 1, if fragmented. 0, otherwise. 245ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 246ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * start: 1, if the starting packet of a fragmented frame. 247ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 248ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * last: 1, if the last packet of a fragmented frame. 249ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 250ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * num: If frag is 1, this is the number of remaining 251ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * fragments 252ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * (including this fragment) of this frame. 253ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * If frag is 0, this is the number of frames in 254ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * this packet. 255ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 256ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void. 257ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *****************************************************************************/ 258feee26c3dae12b53773b31f57cf2533a3d993979Pavlin RadoslavovUNUSED_ATTR static void A2DP_ParseMplHeaderSbc(uint8_t* p_src, bool* p_frag, 259feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov bool* p_start, bool* p_last, 260feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov uint8_t* p_num) { 261397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_src && p_frag && p_start && p_last && p_num) { 262397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_frag = (*p_src & A2DP_SBC_HDR_F_MSK) ? true : false; 263397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_start = (*p_src & A2DP_SBC_HDR_S_MSK) ? true : false; 264397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_last = (*p_src & A2DP_SBC_HDR_L_MSK) ? true : false; 265397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_num = (*p_src & A2DP_SBC_HDR_NUM_MSK); 266397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 2675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 269397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst char* A2DP_CodecNameSbc(UNUSED_ATTR const uint8_t* p_codec_info) { 270397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return "SBC"; 271b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 272b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 273397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSourceCodecValidSbc(const uint8_t* p_codec_info) { 274397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 275a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 276397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 277feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 278feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 279a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 280a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 281397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSinkCodecValidSbc(const uint8_t* p_codec_info) { 282397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 283a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 284397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 285feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 286feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 287a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 288a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 289397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSourceCodecValidSbc(const uint8_t* p_codec_info) { 290397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 291a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 292397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 293feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 294feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 295a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 296a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 297397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSinkCodecValidSbc(const uint8_t* p_codec_info) { 298397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 299b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 300397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 301feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 302feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 303b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 304b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 305397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSinkCodecSupportedSbc(const uint8_t* p_codec_info) { 306397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (A2DP_CodecInfoMatchesCapabilitySbc(&a2dp_sbc_sink_caps, p_codec_info, 307397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov false) == A2DP_SUCCESS); 30879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 30979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 310397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSourceCodecSupportedSbc(const uint8_t* p_codec_info) { 311397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (A2DP_CodecInfoMatchesCapabilitySbc(&a2dp_sbc_sink_caps, p_codec_info, 312397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov true) == A2DP_SUCCESS); 31379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 31479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 315397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovvoid A2DP_InitDefaultCodecSbc(uint8_t* p_codec_info) { 316feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_default_config, 317feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov p_codec_info) != A2DP_SUCCESS) { 318feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: A2DP_BuildInfoSbc failed", __func__); 319397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 32079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 32179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 322b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Checks whether A2DP SBC codec configuration matches with a device's codec 323b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// capabilities. |p_cap| is the SBC codec configuration. |p_codec_info| is 3245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// the device's codec capabilities. |is_capability| is true if 3255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |p_codec_info| contains A2DP codec capability. 326f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov// Returns A2DP_SUCCESS if the codec configuration matches with capabilities, 327b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// otherwise the corresponding A2DP error status code. 328f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic tA2DP_STATUS A2DP_CodecInfoMatchesCapabilitySbc( 329397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const tA2DP_SBC_CIE* p_cap, const uint8_t* p_codec_info, 3305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov bool is_capability) { 331397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS status; 332397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 333397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 334397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* parse configuration */ 3355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov status = A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, is_capability); 336397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (status != A2DP_SUCCESS) { 337397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: parsing failed %d", __func__, status); 338397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return status; 339397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 340397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 341397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* verify that each parameter is in range */ 342397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 34380bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: FREQ peer: 0x%x, capability 0x%x", __func__, 34480bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov cfg_cie.samp_freq, p_cap->samp_freq); 34580bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: CH_MODE peer: 0x%x, capability 0x%x", __func__, 34680bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov cfg_cie.ch_mode, p_cap->ch_mode); 34780bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: BLOCK_LEN peer: 0x%x, capability 0x%x", __func__, 34880bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov cfg_cie.block_len, p_cap->block_len); 34980bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: SUB_BAND peer: 0x%x, capability 0x%x", __func__, 35080bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov cfg_cie.num_subbands, p_cap->num_subbands); 35180bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ALLOC_METHOD peer: 0x%x, capability 0x%x", __func__, 35280bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov cfg_cie.alloc_method, p_cap->alloc_method); 35380bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: MIN_BitPool peer: 0x%x, capability 0x%x", __func__, 35480bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov cfg_cie.min_bitpool, p_cap->min_bitpool); 35580bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: MAX_BitPool peer: 0x%x, capability 0x%x", __func__, 35680bfc5f8e939247e05b7411c38a7b8d31bfe0ec8Pavlin Radoslavov cfg_cie.max_bitpool, p_cap->max_bitpool); 357397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 358397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* sampling frequency */ 359397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0) return A2DP_NS_SAMP_FREQ; 360397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 361397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* channel mode */ 362397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.ch_mode & p_cap->ch_mode) == 0) return A2DP_NS_CH_MODE; 363397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 364397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* block length */ 365397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.block_len & p_cap->block_len) == 0) return A2DP_BAD_BLOCK_LEN; 366397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 367397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* subbands */ 368397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.num_subbands & p_cap->num_subbands) == 0) 369397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_NS_SUBBANDS; 370397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 371397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* allocation method */ 372397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.alloc_method & p_cap->alloc_method) == 0) 373397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_NS_ALLOC_METHOD; 374397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 375397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* min bitpool */ 376d37436670d9d1c0be257c4da41f36a0933ee1418Andre Eisenbach if (cfg_cie.min_bitpool > p_cap->max_bitpool) return A2DP_NS_MIN_BITPOOL; 377397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 378397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* max bitpool */ 379d37436670d9d1c0be257c4da41f36a0933ee1418Andre Eisenbach if (cfg_cie.max_bitpool < p_cap->min_bitpool) return A2DP_NS_MAX_BITPOOL; 380397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 381397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_SUCCESS; 38279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 38379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 384397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_CodecTypeEqualsSbc(const uint8_t* p_codec_info_a, 385397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info_b) { 386397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_a; 387397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_b; 388397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 389397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check whether the codec info contains valid data 390397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status = 3915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_ParseInfoSbc(&sbc_cie_a, p_codec_info_a, true); 392397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 393397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 394397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 395397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 396397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 3975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie_b, p_codec_info_b, true); 398397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 399397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 400397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 401397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 402397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 403397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 404397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a); 405397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b); 406397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 407397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (codec_type_a == codec_type_b) && (codec_type_a == A2DP_MEDIA_CT_SBC); 40879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 40979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 410397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_CodecEqualsSbc(const uint8_t* p_codec_info_a, 411397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info_b) { 412397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_a; 413397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_b; 414397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 415397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check whether the codec info contains valid data 416397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status = 4175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_ParseInfoSbc(&sbc_cie_a, p_codec_info_a, true); 418397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 419397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 420397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 421397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 422397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 4235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie_b, p_codec_info_b, true); 424397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 425397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 426397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 427397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 428397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 429397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 430397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a); 431397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b); 432397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 433397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((codec_type_a != codec_type_b) || (codec_type_a != A2DP_MEDIA_CT_SBC)) 434397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 435397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 436397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (sbc_cie_a.samp_freq == sbc_cie_b.samp_freq) && 437397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.ch_mode == sbc_cie_b.ch_mode) && 438397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.block_len == sbc_cie_b.block_len) && 439397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.num_subbands == sbc_cie_b.num_subbands) && 440397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.alloc_method == sbc_cie_b.alloc_method) && 441397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.min_bitpool == sbc_cie_b.min_bitpool) && 442397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.max_bitpool == sbc_cie_b.max_bitpool); 443c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov} 444c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov 445cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovint A2DP_GetTrackSampleRateSbc(const uint8_t* p_codec_info) { 446397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 447d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 448feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 449397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 450397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 451397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 452397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 453397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 454d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 455397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.samp_freq) { 456f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_16: 457397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 16000; 458f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_32: 459397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 32000; 460f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_44: 461397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 44100; 462f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_48: 463397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 48000; 464d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 465397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 466397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 467d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 468397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 469d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 470d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 471397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetTrackChannelCountSbc(const uint8_t* p_codec_info) { 472397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 473d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 474feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 475397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 476397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 477397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 478397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 479397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 480d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 481397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 482f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 483397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 1; 484f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 485f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 486f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 487397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 2; 488d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 489397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 490397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 491d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 492397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 493d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 494d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 495397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetNumberOfSubbandsSbc(const uint8_t* p_codec_info) { 496397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 497d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 498feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 499397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 500397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 501397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 502397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 503397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 504d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 505397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.num_subbands) { 506f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_4: 507397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 4; 508f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_8: 509397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 8; 510d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 511397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 512397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 513d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 514397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 515d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 516d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 517397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetNumberOfBlocksSbc(const uint8_t* p_codec_info) { 518397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 519d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 520feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 521397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 522397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 523397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 524397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 525397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 526d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 527397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.block_len) { 528f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_4: 529397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 4; 530f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_8: 531397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 8; 532f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_12: 533397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 12; 534f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_16: 535397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 16; 536d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 537397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 538397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 539d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 540397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 541d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 542d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 543397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetAllocationMethodCodeSbc(const uint8_t* p_codec_info) { 544397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 545d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 546feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 547397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 548397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 549397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 550397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 551397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 552d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 553397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.alloc_method) { 554f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_S: 555397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_SNR; 556f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_L: 557397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_LOUDNESS; 558d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 559397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 560397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 561d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 562397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 563d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 564d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 565397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetChannelModeCodeSbc(const uint8_t* p_codec_info) { 566397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 567d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 568feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 569397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 570397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 571397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 572397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 573397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 574d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 575397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 576f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 577397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_MONO; 578f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 579397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_DUAL; 580f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 581397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_STEREO; 582f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 583397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_JOINT_STEREO; 584d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 585397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 586397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 587d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 588397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 589d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 590d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 591397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetSamplingFrequencyCodeSbc(const uint8_t* p_codec_info) { 592397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 593d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 594feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 595397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 596397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 597397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 598397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 599397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 600d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 601397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.samp_freq) { 602f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_16: 603397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf16000; 604f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_32: 605397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf32000; 606f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_44: 607397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf44100; 608f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_48: 609397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf48000; 610d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 611397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 612397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 613d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 614397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 615d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 616d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 617397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetMinBitpoolSbc(const uint8_t* p_codec_info) { 618397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 619b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 6205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, true); 621397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 622397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 623397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 624397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 625397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 626b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 627397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return sbc_cie.min_bitpool; 628b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 629b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 630397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetMaxBitpoolSbc(const uint8_t* p_codec_info) { 631397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 632b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 6335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, true); 634397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 635397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 636397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 637397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 638397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 639b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 640397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return sbc_cie.max_bitpool; 641b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 642b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 6434ed1875cc00071c841068e8bdee07fdcefe5fdf3Sunny Kapdiuint32_t A2DP_GetBitrateSbc() { return a2dp_sbc_get_bitrate(); } 644397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetSinkTrackChannelTypeSbc(const uint8_t* p_codec_info) { 645397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 646d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 647feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 648397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 649397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 650397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 651397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 652397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 653d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 654397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 655f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 656397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 1; 657f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 658f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 659f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 660397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 3; 661d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 662397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 663397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 664d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 665397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 666d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 667d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 668feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovbool A2DP_GetPacketTimestampSbc(UNUSED_ATTR const uint8_t* p_codec_info, 669397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_data, uint32_t* p_timestamp) { 670397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_timestamp = *(const uint32_t*)p_data; 671397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 672b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 673b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 674397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_BuildCodecHeaderSbc(UNUSED_ATTR const uint8_t* p_codec_info, 675397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov BT_HDR* p_buf, uint16_t frames_per_packet) { 676397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t* p; 677b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 678397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_buf->offset -= A2DP_SBC_MPL_HDR_LEN; 679397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p = (uint8_t*)(p_buf + 1) + p_buf->offset; 680397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_buf->len += A2DP_SBC_MPL_HDR_LEN; 681cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov A2DP_BuildMediaPayloadHeaderSbc(p, false, false, false, 682cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov (uint8_t)frames_per_packet); 683b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 684397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 685b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 686b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 6873e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavovstd::string A2DP_CodecInfoStringSbc(const uint8_t* p_codec_info) { 6883e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov std::stringstream res; 6893e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov std::string field; 690397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status; 691397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 692397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 6935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, true); 694397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 6953e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov res << "A2DP_ParseInfoSbc fail: " << loghex(a2dp_status); 6963e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov return res.str(); 6973e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov } 6983e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov 6993e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov res << "\tname: SBC\n"; 7003e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov 7013e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov // Sample frequency 7023e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov field.clear(); 7033e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.samp_freq == 0), "NONE"); 7043e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_16), "16000"); 7053e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_32), "32000"); 7063e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44), "44100"); 7073e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48), "48000"); 7083e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov res << "\tsamp_freq: " << field << " (" << loghex(sbc_cie.samp_freq) << ")\n"; 7093e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov 7103e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov // Channel mode 7113e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov field.clear(); 7123e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.ch_mode == 0), "NONE"); 7133e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO), "Mono"); 7143e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_DUAL), "Dual"); 7153e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_STEREO), "Stereo"); 7163e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_JOINT), "Joint"); 7173e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov res << "\tch_mode: " << field << " (" << loghex(sbc_cie.ch_mode) << ")\n"; 7183e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov 7193e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov // Block length 7203e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov field.clear(); 7213e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.block_len == 0), "NONE"); 7223e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_4), "4"); 7233e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_8), "8"); 7243e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_12), "12"); 7253e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_16), "16"); 7263e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov res << "\tblock_len: " << field << " (" << loghex(sbc_cie.block_len) << ")\n"; 7273e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov 7283e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov // Number of subbands 7293e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov field.clear(); 7303e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.num_subbands == 0), "NONE"); 7313e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.num_subbands & A2DP_SBC_IE_SUBBAND_4), "4"); 7323e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.num_subbands & A2DP_SBC_IE_SUBBAND_8), "8"); 7333e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov res << "\tnum_subbands: " << field << " (" << loghex(sbc_cie.num_subbands) 7343e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov << ")\n"; 7353e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov 7363e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov // Allocation method 7373e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov field.clear(); 7383e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.alloc_method == 0), "NONE"); 7393e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.alloc_method & A2DP_SBC_IE_ALLOC_MD_S), "SNR"); 7403e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov AppendField(&field, (sbc_cie.alloc_method & A2DP_SBC_IE_ALLOC_MD_L), 7413e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov "Loundess"); 7423e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov res << "\talloc_method: " << field << " (" << loghex(sbc_cie.alloc_method) 7433e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov << ")\n"; 7443e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov 7453e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov // Min/max bitloop 7463e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov res << "\tBit pool Min: " << std::to_string(sbc_cie.min_bitpool) 7473e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov << " Max: " << std::to_string(sbc_cie.max_bitpool); 7483e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov 7493e01e01305f0adfd49571499d884514d966a9049Pavlin Radoslavov return res.str(); 7507aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov} 7511394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 752397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterfaceSbc( 753397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info) { 754397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (!A2DP_IsSourceCodecValidSbc(p_codec_info)) return NULL; 7551394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 756397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return &a2dp_encoder_interface_sbc; 7571394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov} 758b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 7597e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrestconst tA2DP_DECODER_INTERFACE* A2DP_GetDecoderInterfaceSbc( 7607e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest const uint8_t* p_codec_info) { 7617e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest if (!A2DP_IsSinkCodecValidSbc(p_codec_info)) return NULL; 7627e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest 7637e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest return &a2dp_decoder_interface_sbc; 7647e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest} 7657e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest 766b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavovbool A2DP_AdjustCodecSbc(uint8_t* p_codec_info) { 767b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 768b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 7695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) != A2DP_SUCCESS) 770b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov return false; 771b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 772b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov // Updated the max bitpool 773b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov if (cfg_cie.max_bitpool > A2DP_SBC_MAX_BITPOOL) { 774d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov LOG_WARN(LOG_TAG, "%s: Updated the SBC codec max bitpool from %d to %d", 775d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov __func__, cfg_cie.max_bitpool, A2DP_SBC_MAX_BITPOOL); 776b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov cfg_cie.max_bitpool = A2DP_SBC_MAX_BITPOOL; 777b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov } 778b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 779feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &cfg_cie, p_codec_info) == 780feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_SUCCESS); 781b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov} 7825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 7835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbtav_a2dp_codec_index_t A2DP_SourceCodecIndexSbc( 7845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR const uint8_t* p_codec_info) { 7855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return BTAV_A2DP_CODEC_INDEX_SOURCE_SBC; 7865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 7875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 788cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavovbtav_a2dp_codec_index_t A2DP_SinkCodecIndexSbc( 789cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov UNUSED_ATTR const uint8_t* p_codec_info) { 790cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov return BTAV_A2DP_CODEC_INDEX_SINK_SBC; 791cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov} 792cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov 7935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovconst char* A2DP_CodecIndexStrSbc(void) { return "SBC"; } 7945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 7955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovconst char* A2DP_CodecIndexStrSbcSink(void) { return "SBC SINK"; } 7965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 797d752229b61663d1d68ec302c8d2074ef5086b973Pavlin Radoslavovbool A2DP_InitCodecConfigSbc(AvdtpSepConfig* p_cfg) { 798cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_source_caps, 7995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_cfg->codec_info) != A2DP_SUCCESS) { 8005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 8015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 8025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 8035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#if (BTA_AV_CO_CP_SCMS_T == TRUE) 8045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov /* Content protection info - support SCMS-T */ 8055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t* p = p_cfg->protect_info; 8065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov *p++ = AVDT_CP_LOSC; 8075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UINT16_TO_STREAM(p, AVDT_CP_SCMS_T_ID); 8085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_cfg->num_protect = 1; 8095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#endif 8105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 8115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 8125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 8135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 814d752229b61663d1d68ec302c8d2074ef5086b973Pavlin Radoslavovbool A2DP_InitCodecConfigSbcSink(AvdtpSepConfig* p_cfg) { 8155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_sink_caps, 8165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_cfg->codec_info) != A2DP_SUCCESS) { 8175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 8185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 8195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 8205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 8215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 8225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 8235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovUNUSED_ATTR static void build_codec_config(const tA2DP_SBC_CIE& config_cie, 8245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* result) { 8255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) 8265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 8275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) 8285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 8295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 830494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov result->bits_per_sample = config_cie.bits_per_sample; 8315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 8325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO) 8335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 8345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 8355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.ch_mode & (A2DP_SBC_IE_CH_MD_STEREO | A2DP_SBC_IE_CH_MD_JOINT | 8365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_SBC_IE_CH_MD_DUAL)) { 8375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 8385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 8395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 8405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 841cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin RadoslavovA2dpCodecConfigSbcSource::A2dpCodecConfigSbcSource( 842a6ba5aca4e8c1a200b8cc29fb60d390a7196416aPavlin Radoslavov btav_a2dp_codec_priority_t codec_priority) 843cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov : A2dpCodecConfigSbcBase(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC", 844cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov codec_priority, true) { 845494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov // Compute the local capability 846cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (a2dp_sbc_source_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 847494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 848494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 849cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (a2dp_sbc_source_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 850494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 851494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 852cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov codec_local_capability_.bits_per_sample = 853cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov a2dp_sbc_source_caps.bits_per_sample; 854cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (a2dp_sbc_source_caps.ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 855494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 856494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 857cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (a2dp_sbc_source_caps.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 858494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 859494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 860cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (a2dp_sbc_source_caps.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 861494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 862494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 863cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (a2dp_sbc_source_caps.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 864494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 865494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 866494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov} 8675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 868cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin RadoslavovA2dpCodecConfigSbcSource::~A2dpCodecConfigSbcSource() {} 8695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 870cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavovbool A2dpCodecConfigSbcSource::init() { 8715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (!isValid()) return false; 8725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 8735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Load the encoder 8745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (!A2DP_LoadEncoderSbc()) { 8755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot load the encoder", __func__); 8765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 8775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 8785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 8795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 8805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 8815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 882cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavovbool A2dpCodecConfigSbcSource::useRtpHeaderMarkerBit() const { return false; } 8833b8391cd47dd0ea3e399f99a888f029de8c7d8c8Pavlin Radoslavov 8845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 8855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the best sample rate from |samp_freq|. 8865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 8875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 8885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 8895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_best_sample_rate(uint8_t samp_freq, tA2DP_SBC_CIE* p_result, 8905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 8915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 8925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 8935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 8945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 8955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 8965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 8975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 8985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 8995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 9005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 9025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 9035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 9055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the audio sample rate from |p_codec_audio_config|. 9065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |samp_freq| contains the capability. 9075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 9085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 9095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 9105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_audio_sample_rate( 9115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov const btav_a2dp_codec_config_t* p_codec_audio_config, uint8_t samp_freq, 9125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE* p_result, btav_a2dp_codec_config_t* p_codec_config) { 9135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (p_codec_audio_config->sample_rate) { 9145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_44100: 9155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 9165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 9175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 9185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 9195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 9215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_48000: 9225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 9235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 9245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 9255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 9265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 9285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_88200: 9295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_96000: 9305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_176400: 9315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_192000: 932fd7a9847733932d20282d3cd7c7177469935d2e8Jakub Pawlowski case BTAV_A2DP_CODEC_SAMPLE_RATE_16000: 933bd39c6ee08b45b5c16925eaa215ca8dec51395d7Jakub Pawlowski case BTAV_A2DP_CODEC_SAMPLE_RATE_24000: 9345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE: 9355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 9365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 9395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 9405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 9425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the best bits per sample. 9435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_codec_config|. 9445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 9455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 9465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_best_bits_per_sample( 9475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 9485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; 9495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 9505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 9515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 9535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the audio bits per sample from |p_codec_audio_config|. 9545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_codec_config|. 9555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 9565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 9575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_audio_bits_per_sample( 9585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov const btav_a2dp_codec_config_t* p_codec_audio_config, 9595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 9605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (p_codec_audio_config->bits_per_sample) { 9615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16: 9625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; 9635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 9645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24: 9655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32: 9665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE: 9675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 9685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 9705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 9715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 9735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the best channel mode from |ch_mode|. 9745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 9755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 9765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 9775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_best_channel_mode(uint8_t ch_mode, tA2DP_SBC_CIE* p_result, 9785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 9795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 9805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 9815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 9825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 9835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 9855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 9865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 9875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 9885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 9905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 9915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 9925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 9935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 9955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_MONO; 9965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 9975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 9985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 10005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 10035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the audio channel mode from |p_codec_audio_config|. 10045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |ch_mode| contains the capability. 10055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 10065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 10075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 10085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_audio_channel_mode( 10095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov const btav_a2dp_codec_config_t* p_codec_audio_config, uint8_t ch_mode, 10105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE* p_result, btav_a2dp_codec_config_t* p_codec_config) { 10115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (p_codec_audio_config->channel_mode) { 10125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO: 10135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 10145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_MONO; 10155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 10165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 10195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO: 10205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 10215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 10225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 10235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 10265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 10275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 10285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 10315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 10325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 10335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 10365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE: 10375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 10385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 10415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 1043cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavovbool A2dpCodecConfigSbcBase::setCodecConfig(const uint8_t* p_peer_codec_info, 1044cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov bool is_capability, 1045cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov uint8_t* p_result_codec_config) { 10465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov std::lock_guard<std::recursive_mutex> lock(codec_mutex_); 1047cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov tA2DP_SBC_CIE peer_info_cie; 10485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE result_config_cie; 10495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t samp_freq; 10505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t ch_mode; 10515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t block_len; 10525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t num_subbands; 10535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t alloc_method; 1054cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov const tA2DP_SBC_CIE* p_a2dp_sbc_caps = 1055cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov (is_source_) ? &a2dp_sbc_source_caps : &a2dp_sbc_sink_caps; 10565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Save the internal state 10585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_config = codec_config_; 10595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_capability = codec_capability_; 1060494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov btav_a2dp_codec_config_t saved_codec_selectable_capability = 1061494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_selectable_capability_; 10625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_; 10635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_; 10645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE]; 10655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t saved_ota_codec_peer_capability[AVDT_CODEC_SIZE]; 10665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t saved_ota_codec_peer_config[AVDT_CODEC_SIZE]; 10675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(saved_ota_codec_config, ota_codec_config_, sizeof(ota_codec_config_)); 10685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(saved_ota_codec_peer_capability, ota_codec_peer_capability_, 10695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_capability_)); 10705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(saved_ota_codec_peer_config, ota_codec_peer_config_, 10715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_config_)); 10725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_STATUS status = 1074cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov A2DP_ParseInfoSbc(&peer_info_cie, p_peer_codec_info, is_capability); 10755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (status != A2DP_SUCCESS) { 1076cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d", 10775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, status); 10785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 10795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 1080d62e522131e8646830f846fdcb292870d7fb9d7bPavlin Radoslavov // Try using the prefered peer codec config (if valid), instead of the peer 1081d62e522131e8646830f846fdcb292870d7fb9d7bPavlin Radoslavov // capability. 1082cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (is_capability) { 1083cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (is_source_) { 1084cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (A2DP_IsPeerSinkCodecValidSbc(ota_codec_peer_config_)) { 1085cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov status = 1086cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov A2DP_ParseInfoSbc(&peer_info_cie, ota_codec_peer_config_, false); 1087cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov } 1088cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov } else { 1089cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (A2DP_IsPeerSourceCodecValidSbc(ota_codec_peer_config_)) { 1090cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov status = 1091cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov A2DP_ParseInfoSbc(&peer_info_cie, ota_codec_peer_config_, false); 1092cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov } 1093cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov } 1094d62e522131e8646830f846fdcb292870d7fb9d7bPavlin Radoslavov if (status != A2DP_SUCCESS) { 1095d62e522131e8646830f846fdcb292870d7fb9d7bPavlin Radoslavov // Use the peer codec capability 1096d62e522131e8646830f846fdcb292870d7fb9d7bPavlin Radoslavov status = 1097cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov A2DP_ParseInfoSbc(&peer_info_cie, p_peer_codec_info, is_capability); 1098d62e522131e8646830f846fdcb292870d7fb9d7bPavlin Radoslavov CHECK(status == A2DP_SUCCESS); 1099d62e522131e8646830f846fdcb292870d7fb9d7bPavlin Radoslavov } 1100d62e522131e8646830f846fdcb292870d7fb9d7bPavlin Radoslavov } 11015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 11035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Build the preferred configuration 11045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 11055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memset(&result_config_cie, 0, sizeof(result_config_cie)); 11065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 11085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the sample frequency 11095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 1110cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov samp_freq = p_a2dp_sbc_caps->samp_freq & peer_info_cie.samp_freq; 11115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE; 11125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (codec_user_config_.sample_rate) { 11135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_44100: 11145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 11155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 11165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate = codec_user_config_.sample_rate; 11175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = codec_user_config_.sample_rate; 11185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_48000: 11215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 11225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 11235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate = codec_user_config_.sample_rate; 11245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = codec_user_config_.sample_rate; 11255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_88200: 11285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_96000: 11295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_176400: 11305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_192000: 1131fd7a9847733932d20282d3cd7c7177469935d2e8Jakub Pawlowski case BTAV_A2DP_CODEC_SAMPLE_RATE_16000: 1132bd39c6ee08b45b5c16925eaa215ca8dec51395d7Jakub Pawlowski case BTAV_A2DP_CODEC_SAMPLE_RATE_24000: 11335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE: 11345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE; 11355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE; 11365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the sample frequency if there is no user preference 11405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov do { 1141494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov // Compute the selectable capability 1142494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 1143494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_selectable_capability_.sample_rate |= 1144494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 1145494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 1146494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 1147494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_selectable_capability_.sample_rate |= 1148494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 1149494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 1150494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov 11515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break; 11525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Compute the common capability 11545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) 11555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 11565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) 11575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 11585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the codec audio config 11605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_audio_sample_rate(&codec_audio_config_, samp_freq, 11615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 11625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the default config 11665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_sample_rate( 1167cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov a2dp_sbc_default_config.samp_freq & peer_info_cie.samp_freq, 11685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 11695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the best match 11735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_sample_rate(samp_freq, &result_config_cie, 11745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &codec_config_)) { 11755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } while (false); 11785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) { 11795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 1180cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov "%s: cannot match sample frequency: local caps = 0x%x " 1181cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov "peer info = 0x%x", 1182cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov __func__, p_a2dp_sbc_caps->samp_freq, peer_info_cie.samp_freq); 11835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 11845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 11875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the bits per sample 11885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 11895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // NOTE: this information is NOT included in the SBC A2DP codec description 11905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // that is sent OTA. 11915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE; 11925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (codec_user_config_.bits_per_sample) { 11935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16: 11945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.bits_per_sample = codec_user_config_.bits_per_sample; 11955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.bits_per_sample = codec_user_config_.bits_per_sample; 11965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24: 11985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32: 11995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE: 12005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE; 12015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE; 12025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the bits per sample if there is no user preference 12065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov do { 1207494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov // Compute the selectable capability 1208494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_selectable_capability_.bits_per_sample = 1209cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov p_a2dp_sbc_caps->bits_per_sample; 1210494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov 12115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) 12125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Compute the common capability 12155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; 12165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the codec audio config 12185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_audio_bits_per_sample(&codec_audio_config_, &codec_config_)) { 12195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the default config 12235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_bits_per_sample(&codec_config_)) { 12245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the best match 12285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // TODO: no-op - temporary kept here for consistency 12295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_bits_per_sample(&codec_config_)) { 12305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } while (false); 12335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) { 12345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 12355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match bits per sample: user preference = 0x%x", 12365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, codec_user_config_.bits_per_sample); 12375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 12385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 12415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the channel mode 12425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 1243cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov ch_mode = p_a2dp_sbc_caps->ch_mode & peer_info_cie.ch_mode; 12445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE; 12455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (codec_user_config_.channel_mode) { 12465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO: 12475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 12485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_MONO; 12495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 12505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 12515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO: 12545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 12555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 12565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 12575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 12585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 12615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 12625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 12635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 12645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 12675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 12685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 12695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 12705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE: 12745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE; 12755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE; 12765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the channel mode if there is no user preference 12805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov do { 1281494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov // Compute the selectable capability 1282494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 1283494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_selectable_capability_.channel_mode |= 1284494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 1285494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 1286494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 1287494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_selectable_capability_.channel_mode |= 1288494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 1289494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 1290494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 1291494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_selectable_capability_.channel_mode |= 1292494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 1293494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 1294494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 1295494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_selectable_capability_.channel_mode |= 1296494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 1297494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov } 1298494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov 12995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break; 13005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Compute the common capability 13025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) 13035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 13045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & (A2DP_SBC_IE_CH_MD_JOINT | A2DP_SBC_IE_CH_MD_STEREO | 13055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_SBC_IE_CH_MD_DUAL)) { 13065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 13075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the codec audio config 13105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_audio_channel_mode(&codec_audio_config_, ch_mode, 13115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 13125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the default config 13165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_channel_mode( 1317cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov a2dp_sbc_default_config.ch_mode & peer_info_cie.ch_mode, 13185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 13195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the best match 13235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_channel_mode(ch_mode, &result_config_cie, &codec_config_)) { 13245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } while (false); 13275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) { 13285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 1329cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov "%s: cannot match channel mode: local caps = 0x%x " 1330cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov "peer info = 0x%x", 1331cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov __func__, p_a2dp_sbc_caps->ch_mode, peer_info_cie.ch_mode); 13325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 13335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the block length 13375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 1338cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov block_len = p_a2dp_sbc_caps->block_len & peer_info_cie.block_len; 13395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (block_len & A2DP_SBC_IE_BLOCKS_16) { 13405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_16; 13415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (block_len & A2DP_SBC_IE_BLOCKS_12) { 13425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_12; 13435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (block_len & A2DP_SBC_IE_BLOCKS_8) { 13445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_8; 13455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (block_len & A2DP_SBC_IE_BLOCKS_4) { 13465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_4; 13475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 13485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 1349cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov "%s: cannot match block length: local caps = 0x%x " 1350cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov "peer info = 0x%x", 1351cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov __func__, p_a2dp_sbc_caps->block_len, peer_info_cie.block_len); 13525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 13535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the number of sub-bands 13575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 1358cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov num_subbands = p_a2dp_sbc_caps->num_subbands & peer_info_cie.num_subbands; 13595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (num_subbands & A2DP_SBC_IE_SUBBAND_8) { 13605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.num_subbands = A2DP_SBC_IE_SUBBAND_8; 13615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (num_subbands & A2DP_SBC_IE_SUBBAND_4) { 13625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.num_subbands = A2DP_SBC_IE_SUBBAND_4; 13635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 13645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 1365cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov "%s: cannot match number of sub-bands: local caps = 0x%x " 1366cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov "peer info = 0x%x", 1367cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov __func__, p_a2dp_sbc_caps->num_subbands, 1368cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov peer_info_cie.num_subbands); 13695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 13705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the allocation method 13745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 1375cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov alloc_method = p_a2dp_sbc_caps->alloc_method & peer_info_cie.alloc_method; 13765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (alloc_method & A2DP_SBC_IE_ALLOC_MD_L) { 13775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.alloc_method = A2DP_SBC_IE_ALLOC_MD_L; 13785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (alloc_method & A2DP_SBC_IE_ALLOC_MD_S) { 13795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.alloc_method = A2DP_SBC_IE_ALLOC_MD_S; 13805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 13815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 1382cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov "%s: cannot match allocation method: local caps = 0x%x " 1383cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov "peer info = 0x%x", 1384cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov __func__, p_a2dp_sbc_caps->alloc_method, 1385cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov peer_info_cie.alloc_method); 13865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 13875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the min/max bitpool 13915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 1392cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov result_config_cie.min_bitpool = p_a2dp_sbc_caps->min_bitpool; 1393cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (result_config_cie.min_bitpool < peer_info_cie.min_bitpool) 1394cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov result_config_cie.min_bitpool = peer_info_cie.min_bitpool; 1395cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov result_config_cie.max_bitpool = p_a2dp_sbc_caps->max_bitpool; 1396cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov if (result_config_cie.max_bitpool > peer_info_cie.max_bitpool) 1397cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov result_config_cie.max_bitpool = peer_info_cie.max_bitpool; 13985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (result_config_cie.min_bitpool > result_config_cie.max_bitpool) { 13995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 14005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match min/max bitpool: " 1401cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov "local caps min/max = 0x%x/0x%x peer info min/max = 0x%x/0x%x", 1402cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov __func__, p_a2dp_sbc_caps->min_bitpool, 1403cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov p_a2dp_sbc_caps->max_bitpool, peer_info_cie.min_bitpool, 1404cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov peer_info_cie.max_bitpool); 14055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 14065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &result_config_cie, 14095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result_codec_config) != A2DP_SUCCESS) { 14105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 14115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Copy the codec-specific fields if they are not zero 14155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_1 != 0) 14175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_1 = codec_user_config_.codec_specific_1; 14185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_2 != 0) 14195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_2 = codec_user_config_.codec_specific_2; 14205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_3 != 0) 14215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_3 = codec_user_config_.codec_specific_3; 14225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_4 != 0) 14235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_4 = codec_user_config_.codec_specific_4; 14245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Create a local copy of the peer codec capability/config, and the 14265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // result codec config. 14275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (is_capability) { 1428b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie, 1429b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov ota_codec_peer_capability_); 14305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 1431b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie, 1432b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov ota_codec_peer_config_); 14335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 1434b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov CHECK(status == A2DP_SUCCESS); 14355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &result_config_cie, 14365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov ota_codec_config_); 14375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov CHECK(status == A2DP_SUCCESS); 14385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 14395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovfail: 14415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Restore the internal state 14425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_ = saved_codec_config; 14435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_ = saved_codec_capability; 1444494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov codec_selectable_capability_ = saved_codec_selectable_capability; 14455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_user_config_ = saved_codec_user_config; 14465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_audio_config_ = saved_codec_audio_config; 14475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_)); 14485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(ota_codec_peer_capability_, saved_ota_codec_peer_capability, 14495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_capability_)); 14505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(ota_codec_peer_config_, saved_ota_codec_peer_config, 14515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_config_)); 14525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 14535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 14545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 1455b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavovbool A2dpCodecConfigSbcBase::setPeerCodecCapabilities( 1456b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov const uint8_t* p_peer_codec_capabilities) { 1457b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov std::lock_guard<std::recursive_mutex> lock(codec_mutex_); 1458b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov tA2DP_SBC_CIE peer_info_cie; 1459b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov uint8_t samp_freq; 1460b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov uint8_t ch_mode; 1461b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov const tA2DP_SBC_CIE* p_a2dp_sbc_caps = 1462b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov (is_source_) ? &a2dp_sbc_source_caps : &a2dp_sbc_sink_caps; 1463b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov 1464b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov // Save the internal state 1465b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov btav_a2dp_codec_config_t saved_codec_selectable_capability = 1466b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov codec_selectable_capability_; 1467b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov uint8_t saved_ota_codec_peer_capability[AVDT_CODEC_SIZE]; 1468b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov memcpy(saved_ota_codec_peer_capability, ota_codec_peer_capability_, 1469b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov sizeof(ota_codec_peer_capability_)); 1470b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov 1471b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov tA2DP_STATUS status = 1472b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov A2DP_ParseInfoSbc(&peer_info_cie, p_peer_codec_capabilities, true); 1473b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov if (status != A2DP_SUCCESS) { 1474b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: can't parse peer's capabilities: error = %d", 1475b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov __func__, status); 1476b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov goto fail; 1477b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov } 1478b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov 1479b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov // Compute the selectable capability - sample rate 1480b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov samp_freq = p_a2dp_sbc_caps->samp_freq & peer_info_cie.samp_freq; 1481b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 1482b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov codec_selectable_capability_.sample_rate |= 1483b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 1484b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov } 1485b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 1486b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov codec_selectable_capability_.sample_rate |= 1487b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 1488b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov } 1489b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov 1490b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov // Compute the selectable capability - bits per sample 1491b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov codec_selectable_capability_.bits_per_sample = 1492b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov p_a2dp_sbc_caps->bits_per_sample; 1493b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov 1494b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov // Compute the selectable capability - channel mode 1495b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov ch_mode = p_a2dp_sbc_caps->ch_mode & peer_info_cie.ch_mode; 1496b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 1497b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov codec_selectable_capability_.channel_mode |= 1498b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 1499b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov } 1500b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 1501b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov codec_selectable_capability_.channel_mode |= 1502b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 1503b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov } 1504b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 1505b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov codec_selectable_capability_.channel_mode |= 1506b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 1507b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov } 1508b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 1509b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov codec_selectable_capability_.channel_mode |= 1510b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 1511b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov } 1512b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov 1513b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &peer_info_cie, 1514b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov ota_codec_peer_capability_); 1515b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov CHECK(status == A2DP_SUCCESS); 1516b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov return true; 1517b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov 1518b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavovfail: 1519b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov // Restore the internal state 1520b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov codec_selectable_capability_ = saved_codec_selectable_capability; 1521b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov memcpy(ota_codec_peer_capability_, saved_ota_codec_peer_capability, 1522b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov sizeof(ota_codec_peer_capability_)); 1523b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov return false; 1524b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov} 1525b3a5e61353203e05a17861c5b3d4721d8819ff8fPavlin Radoslavov 1526a6ba5aca4e8c1a200b8cc29fb60d390a7196416aPavlin RadoslavovA2dpCodecConfigSbcSink::A2dpCodecConfigSbcSink( 1527a6ba5aca4e8c1a200b8cc29fb60d390a7196416aPavlin Radoslavov btav_a2dp_codec_priority_t codec_priority) 1528cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov : A2dpCodecConfigSbcBase(BTAV_A2DP_CODEC_INDEX_SINK_SBC, "SBC(Sink)", 1529cc9836b0295bbe5d63723cb45eddffbf01d532f4Pavlin Radoslavov codec_priority, false) {} 15305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovA2dpCodecConfigSbcSink::~A2dpCodecConfigSbcSink() {} 15325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbcSink::init() { 15345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (!isValid()) return false; 15355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15367e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest // Load the decoder 15377e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest if (!A2DP_LoadDecoderSbc()) { 15387e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest LOG_ERROR(LOG_TAG, "%s: cannot load the decoder", __func__); 15397e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest return false; 15407e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest } 15417e2ab6967351ee8b24006d3036c072f428ab69ebBailey Forrest 15425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 15435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 15445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15453b8391cd47dd0ea3e399f99a888f029de8c7d8c8Pavlin Radoslavovbool A2dpCodecConfigSbcSink::useRtpHeaderMarkerBit() const { 15463b8391cd47dd0ea3e399f99a888f029de8c7d8c8Pavlin Radoslavov // TODO: This method applies only to Source codecs 15473b8391cd47dd0ea3e399f99a888f029de8c7d8c8Pavlin Radoslavov return false; 15483b8391cd47dd0ea3e399f99a888f029de8c7d8c8Pavlin Radoslavov} 15493b8391cd47dd0ea3e399f99a888f029de8c7d8c8Pavlin Radoslavov 15505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbcSink::updateEncoderUserConfig( 15515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params, 15525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR bool* p_restart_input, UNUSED_ATTR bool* p_restart_output, 15535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR bool* p_config_updated) { 15545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // TODO: This method applies only to Source codecs 15555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 15565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 1557302113d4e44f06e90f90a5903e33ae830edb58a3Pavlin Radoslavov 1558302113d4e44f06e90f90a5903e33ae830edb58a3Pavlin Radoslavovperiod_ms_t A2dpCodecConfigSbcSink::encoderIntervalMs() const { 1559302113d4e44f06e90f90a5903e33ae830edb58a3Pavlin Radoslavov // TODO: This method applies only to Source codecs 1560302113d4e44f06e90f90a5903e33ae830edb58a3Pavlin Radoslavov return 0; 1561302113d4e44f06e90f90a5903e33ae830edb58a3Pavlin Radoslavov} 156265157e904abd9d692b5d2acebf1464f73b5b61faPavlin Radoslavov 156365157e904abd9d692b5d2acebf1464f73b5b61faPavlin Radoslavovint A2dpCodecConfigSbcSink::getEffectiveMtu() const { 156465157e904abd9d692b5d2acebf1464f73b5b61faPavlin Radoslavov // TODO: This method applies only to Source codecs 156565157e904abd9d692b5d2acebf1464f73b5b61faPavlin Radoslavov return 0; 156665157e904abd9d692b5d2acebf1464f73b5b61faPavlin Radoslavov} 1567