a2dp_sbc.cc revision 5ce0116fbf5b530d5b93f11312096eade1021c1e
15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * 35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project * Copyright (C) 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> 35f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov#include "a2dp_int.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 */ 53f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov} tA2DP_SBC_CIE; 54b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 5579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* SBC SRC codec capabilities */ 56397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovstatic const tA2DP_SBC_CIE a2dp_sbc_caps = { 57397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */ 58397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_CH_MD_JOINT, /* ch_mode */ 59397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_BLOCKS_16, /* block_len */ 60397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ 61397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ 62397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 63397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_MAX_BITPOOL /* max_bitpool */ 6479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 6579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 6679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* SBC SINK codec capabilities */ 67397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovstatic const tA2DP_SBC_CIE a2dp_sbc_sink_caps = { 68397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_SAMP_FREQ_48 | A2DP_SBC_IE_SAMP_FREQ_44), /* samp_freq */ 69f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov (A2DP_SBC_IE_CH_MD_MONO | A2DP_SBC_IE_CH_MD_STEREO | 70397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_CH_MD_JOINT | A2DP_SBC_IE_CH_MD_DUAL), /* ch_mode */ 71397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_BLOCKS_16 | A2DP_SBC_IE_BLOCKS_12 | A2DP_SBC_IE_BLOCKS_8 | 72397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_BLOCKS_4), /* block_len */ 73397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_SUBBAND_4 | A2DP_SBC_IE_SUBBAND_8), /* num_subbands */ 74397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_ALLOC_MD_L | A2DP_SBC_IE_ALLOC_MD_S), /* alloc_method */ 75397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 76d37436670d9d1c0be257c4da41f36a0933ee1418Andre Eisenbach A2DP_SBC_MAX_BITPOOL /* max_bitpool */ 7779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 7879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 7979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* Default SBC codec configuration */ 80397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst tA2DP_SBC_CIE a2dp_sbc_default_config = { 81397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */ 82397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_CH_MD_JOINT, /* ch_mode */ 83397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_BLOCKS_16, /* block_len */ 84397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ 85397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ 86397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 87397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_MAX_BITPOOL /* max_bitpool */ 8879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 890df29ac95d057a1bf74b003fa6dd6459743bcf54Mike J. Chen 90f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic const tA2DP_ENCODER_INTERFACE a2dp_encoder_interface_sbc = { 91cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov a2dp_sbc_encoder_init, a2dp_sbc_encoder_cleanup, 92cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov a2dp_sbc_feeding_init, a2dp_sbc_feeding_reset, 93cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov a2dp_sbc_feeding_flush, a2dp_sbc_get_encoder_interval_ms, 94cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov a2dp_sbc_send_frames, a2dp_sbc_debug_codec_dump}; 951394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 96f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic tA2DP_STATUS A2DP_CodecInfoMatchesCapabilitySbc( 97397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const tA2DP_SBC_CIE* p_cap, const uint8_t* p_codec_info, 985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov bool is_capability); 99feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovstatic void A2DP_ParseMplHeaderSbc(uint8_t* p_src, bool* p_frag, bool* p_start, 100feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov bool* p_last, uint8_t* p_num); 101b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 102b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Builds the SBC Media Codec Capabilities byte sequence beginning from the 103b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// LOSC octet. |media_type| is the media type |AVDT_MEDIA_TYPE_*|. 104b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// |p_ie| is a pointer to the SBC Codec Information Element information. 105f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov// The result is stored in |p_result|. Returns A2DP_SUCCESS on success, 106b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// otherwise the corresponding A2DP error status code. 107feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovstatic tA2DP_STATUS A2DP_BuildInfoSbc(uint8_t media_type, 108feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov const tA2DP_SBC_CIE* p_ie, 109feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov uint8_t* p_result) { 110397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS status; 111397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 112397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie == NULL || p_result == NULL || 113397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->samp_freq & ~A2DP_SBC_IE_SAMP_FREQ_MSK) || 114397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->ch_mode & ~A2DP_SBC_IE_CH_MD_MSK) || 115397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->block_len & ~A2DP_SBC_IE_BLOCKS_MSK) || 116397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->num_subbands & ~A2DP_SBC_IE_SUBBAND_MSK) || 117397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->alloc_method & ~A2DP_SBC_IE_ALLOC_MD_MSK) || 118397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->min_bitpool > p_ie->max_bitpool) || 119397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->min_bitpool < A2DP_SBC_IE_MIN_BITPOOL) || 120397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->min_bitpool > A2DP_SBC_IE_MAX_BITPOOL) || 121397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->max_bitpool < A2DP_SBC_IE_MIN_BITPOOL) || 122397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->max_bitpool > A2DP_SBC_IE_MAX_BITPOOL)) { 123397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* if any unused bit is set */ 124397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_INVALID_PARAMS; 125397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else { 126397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_SUCCESS; 127397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = A2DP_SBC_INFO_LEN; 128397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = (media_type << 4); 129397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = A2DP_MEDIA_CT_SBC; 130397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 131397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Media Codec Specific Information Element */ 132397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = p_ie->samp_freq | p_ie->ch_mode; 133397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 134397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = p_ie->block_len | p_ie->num_subbands | p_ie->alloc_method; 135397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 136397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = p_ie->min_bitpool; 137397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result = p_ie->max_bitpool; 138397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 139397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return status; 1405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 142b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Parses the SBC Media Codec Capabilities byte sequence beginning from the 143b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// LOSC octet. The result is stored in |p_ie|. The byte sequence to parse is 1445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |p_codec_info|. If |is_capability| is true, the byte sequence contains 1455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// codec capability. 146feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov// Returns A2DP_SUCCESS on success, otherwise the corresponding A2DP error 147feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov// status code. 148feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovstatic tA2DP_STATUS A2DP_ParseInfoSbc(tA2DP_SBC_CIE* p_ie, 149feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov const uint8_t* p_codec_info, 1505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov bool is_capability) { 151397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS status = A2DP_SUCCESS; 152397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t losc; 153397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t media_type; 154397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type; 155397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 156397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie == NULL || p_codec_info == NULL) return A2DP_INVALID_PARAMS; 157397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 158397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the codec capability length 159397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov losc = *p_codec_info++; 160397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (losc != A2DP_SBC_INFO_LEN) return A2DP_WRONG_CODEC; 161397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 162397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov media_type = (*p_codec_info++) >> 4; 163397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov codec_type = *p_codec_info++; 164397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Check the Media Type and Media Codec Type */ 165397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (media_type != AVDT_MEDIA_TYPE_AUDIO || codec_type != A2DP_MEDIA_CT_SBC) { 166397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_WRONG_CODEC; 167397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 168397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 169397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->samp_freq = *p_codec_info & A2DP_SBC_IE_SAMP_FREQ_MSK; 170397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->ch_mode = *p_codec_info & A2DP_SBC_IE_CH_MD_MSK; 171397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_codec_info++; 172397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->block_len = *p_codec_info & A2DP_SBC_IE_BLOCKS_MSK; 173397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->num_subbands = *p_codec_info & A2DP_SBC_IE_SUBBAND_MSK; 174397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->alloc_method = *p_codec_info & A2DP_SBC_IE_ALLOC_MD_MSK; 175397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_codec_info++; 176397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->min_bitpool = *p_codec_info++; 177397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->max_bitpool = *p_codec_info; 178397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie->min_bitpool < A2DP_SBC_IE_MIN_BITPOOL || 179397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->min_bitpool > A2DP_SBC_IE_MAX_BITPOOL) { 180397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_MIN_BITPOOL; 181397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 182397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 183397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie->max_bitpool < A2DP_SBC_IE_MIN_BITPOOL || 184397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->max_bitpool > A2DP_SBC_IE_MAX_BITPOOL || 185397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->max_bitpool < p_ie->min_bitpool) { 186397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_MAX_BITPOOL; 187397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 188397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 1895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (is_capability) return status; 190397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 191397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->samp_freq) != A2DP_SET_ONE_BIT) 192397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_SAMP_FREQ; 193397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->ch_mode) != A2DP_SET_ONE_BIT) 194397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_CH_MODE; 195397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->block_len) != A2DP_SET_ONE_BIT) 196397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_BLOCK_LEN; 197397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->num_subbands) != A2DP_SET_ONE_BIT) 198397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_SUBBANDS; 199397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->alloc_method) != A2DP_SET_ONE_BIT) 200397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_ALLOC_METHOD; 201397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 202397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return status; 2035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 205cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// Build the SBC Media Payload Header. 206cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// |p_dst| points to the location where the header should be written to. 207cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// If |frag| is true, the media payload frame is fragmented. 208cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// |start| is true for the first packet of a fragmented frame. 209cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// |last| is true for the last packet of a fragmented frame. 210cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// If |frag| is false, |num| is the number of number of frames in the packet, 211cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// otherwise is the number of remaining fragments (including this one). 212cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic void A2DP_BuildMediaPayloadHeaderSbc(uint8_t* p_dst, bool frag, 213cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov bool start, bool last, 214cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov uint8_t num) { 215397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_dst == NULL) return; 216397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 217397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_dst = 0; 218397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (frag) *p_dst |= A2DP_SBC_HDR_F_MSK; 219397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (start) *p_dst |= A2DP_SBC_HDR_S_MSK; 220397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (last) *p_dst |= A2DP_SBC_HDR_L_MSK; 221397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_dst |= (A2DP_SBC_HDR_NUM_MSK & num); 2225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 225ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 226ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function A2DP_ParseMplHeaderSbc 227ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 228ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called by an application to parse 229ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * the SBC Media Payload header. 230ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Input Parameters: 231ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_src: the byte sequence to parse.. 232ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 233ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Output Parameters: 234ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * frag: 1, if fragmented. 0, otherwise. 235ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 236ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * start: 1, if the starting packet of a fragmented frame. 237ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 238ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * last: 1, if the last packet of a fragmented frame. 239ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 240ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * num: If frag is 1, this is the number of remaining 241ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * fragments 242ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * (including this fragment) of this frame. 243ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * If frag is 0, this is the number of frames in 244ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * this packet. 245ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 246ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void. 247ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *****************************************************************************/ 248feee26c3dae12b53773b31f57cf2533a3d993979Pavlin RadoslavovUNUSED_ATTR static void A2DP_ParseMplHeaderSbc(uint8_t* p_src, bool* p_frag, 249feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov bool* p_start, bool* p_last, 250feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov uint8_t* p_num) { 251397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_src && p_frag && p_start && p_last && p_num) { 252397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_frag = (*p_src & A2DP_SBC_HDR_F_MSK) ? true : false; 253397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_start = (*p_src & A2DP_SBC_HDR_S_MSK) ? true : false; 254397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_last = (*p_src & A2DP_SBC_HDR_L_MSK) ? true : false; 255397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_num = (*p_src & A2DP_SBC_HDR_NUM_MSK); 256397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 2575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 259397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst char* A2DP_CodecNameSbc(UNUSED_ATTR const uint8_t* p_codec_info) { 260397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return "SBC"; 261b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 262b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 263397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSourceCodecValidSbc(const uint8_t* p_codec_info) { 264397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 265a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 266397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 267feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 268feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 269a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 270a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 271397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSinkCodecValidSbc(const uint8_t* p_codec_info) { 272397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 273a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 274397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 275feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 276feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 277a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 278a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 279397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSourceCodecValidSbc(const uint8_t* p_codec_info) { 280397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 281a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 282397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 283feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 284feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 285a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 286a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 287397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSinkCodecValidSbc(const uint8_t* p_codec_info) { 288397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 289b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 290397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 291feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 292feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 293b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 294b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 295397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSinkCodecSupportedSbc(const uint8_t* p_codec_info) { 296397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (A2DP_CodecInfoMatchesCapabilitySbc(&a2dp_sbc_sink_caps, p_codec_info, 297397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov false) == A2DP_SUCCESS); 29879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 29979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 300397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSourceCodecSupportedSbc(const uint8_t* p_codec_info) { 301397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (A2DP_CodecInfoMatchesCapabilitySbc(&a2dp_sbc_sink_caps, p_codec_info, 302397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov true) == A2DP_SUCCESS); 30379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 30479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 305397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovvoid A2DP_InitDefaultCodecSbc(uint8_t* p_codec_info) { 306feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_default_config, 307feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov p_codec_info) != A2DP_SUCCESS) { 308feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: A2DP_BuildInfoSbc failed", __func__); 309397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 31079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 31179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 312b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Checks whether A2DP SBC codec configuration matches with a device's codec 313b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// capabilities. |p_cap| is the SBC codec configuration. |p_codec_info| is 3145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// the device's codec capabilities. |is_capability| is true if 3155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |p_codec_info| contains A2DP codec capability. 316f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov// Returns A2DP_SUCCESS if the codec configuration matches with capabilities, 317b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// otherwise the corresponding A2DP error status code. 318f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic tA2DP_STATUS A2DP_CodecInfoMatchesCapabilitySbc( 319397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const tA2DP_SBC_CIE* p_cap, const uint8_t* p_codec_info, 3205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov bool is_capability) { 321397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS status; 322397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 323397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 324397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* parse configuration */ 3255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov status = A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, is_capability); 326397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (status != A2DP_SUCCESS) { 327397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: parsing failed %d", __func__, status); 328397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return status; 329397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 330397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 331397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* verify that each parameter is in range */ 332397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 333397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "FREQ peer: 0x%x, capability 0x%x", cfg_cie.samp_freq, 334397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_cap->samp_freq); 335397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "CH_MODE peer: 0x%x, capability 0x%x", cfg_cie.ch_mode, 336397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_cap->ch_mode); 337397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "BLOCK_LEN peer: 0x%x, capability 0x%x", cfg_cie.block_len, 338397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_cap->block_len); 339397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "SUB_BAND peer: 0x%x, capability 0x%x", 340397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.num_subbands, p_cap->num_subbands); 341397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "ALLOC_METHOD peer: 0x%x, capability 0x%x", 342397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.alloc_method, p_cap->alloc_method); 343397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "MIN_BitPool peer: 0x%x, capability 0x%x", 344397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.min_bitpool, p_cap->min_bitpool); 345397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "MAX_BitPool peer: 0x%x, capability 0x%x", 346397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.max_bitpool, p_cap->max_bitpool); 347397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 348397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* sampling frequency */ 349397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0) return A2DP_NS_SAMP_FREQ; 350397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 351397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* channel mode */ 352397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.ch_mode & p_cap->ch_mode) == 0) return A2DP_NS_CH_MODE; 353397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 354397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* block length */ 355397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.block_len & p_cap->block_len) == 0) return A2DP_BAD_BLOCK_LEN; 356397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 357397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* subbands */ 358397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.num_subbands & p_cap->num_subbands) == 0) 359397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_NS_SUBBANDS; 360397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 361397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* allocation method */ 362397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.alloc_method & p_cap->alloc_method) == 0) 363397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_NS_ALLOC_METHOD; 364397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 365397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* min bitpool */ 366d37436670d9d1c0be257c4da41f36a0933ee1418Andre Eisenbach if (cfg_cie.min_bitpool > p_cap->max_bitpool) return A2DP_NS_MIN_BITPOOL; 367397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 368397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* max bitpool */ 369d37436670d9d1c0be257c4da41f36a0933ee1418Andre Eisenbach if (cfg_cie.max_bitpool < p_cap->min_bitpool) return A2DP_NS_MAX_BITPOOL; 370397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 371397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_SUCCESS; 37279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 37379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 374397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin RadoslavovtA2DP_STATUS A2DP_BuildSrc2SinkConfigSbc(const uint8_t* p_src_cap, 375397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t* p_pref_cfg) { 376397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE src_cap; 377397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE pref_cap; 378397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 379397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* initialize it to default SBC configuration */ 380feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_default_config, 381feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov p_pref_cfg); 382397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 383397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* now try to build a preferred one */ 384397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* parse configuration */ 385feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS status = A2DP_ParseInfoSbc(&src_cap, p_src_cap, true); 386397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (status != A2DP_SUCCESS) { 387397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: can't parse src cap ret = %d", __func__, status); 388397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_FAIL; 389397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 390397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 391397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) 392397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 393397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) 394397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 395397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 396397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) 397397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 398397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) 399397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 400397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) 401397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 402397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_MONO) 403397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_MONO; 404397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 405397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_16) 406397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_16; 407397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_12) 408397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_12; 409397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_8) 410397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_8; 411397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_4) 412397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_4; 413397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 414397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.num_subbands & A2DP_SBC_IE_SUBBAND_8) 415397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.num_subbands = A2DP_SBC_IE_SUBBAND_8; 416397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.num_subbands & A2DP_SBC_IE_SUBBAND_4) 417397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.num_subbands = A2DP_SBC_IE_SUBBAND_4; 418397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 419397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.alloc_method & A2DP_SBC_IE_ALLOC_MD_L) 420397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.alloc_method = A2DP_SBC_IE_ALLOC_MD_L; 421397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.alloc_method & A2DP_SBC_IE_ALLOC_MD_S) 422397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.alloc_method = A2DP_SBC_IE_ALLOC_MD_S; 423397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 424397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.min_bitpool = src_cap.min_bitpool; 425397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.max_bitpool = src_cap.max_bitpool; 426397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 427feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &pref_cap, p_pref_cfg); 428397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 429397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_SUCCESS; 43079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 43179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 432397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_CodecTypeEqualsSbc(const uint8_t* p_codec_info_a, 433397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info_b) { 434397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_a; 435397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_b; 436397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 437397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check whether the codec info contains valid data 438397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status = 4395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_ParseInfoSbc(&sbc_cie_a, p_codec_info_a, true); 440397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 441397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 442397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 443397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 444397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 4455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie_b, p_codec_info_b, true); 446397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 447397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 448397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 449397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 450397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 451397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 452397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a); 453397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b); 454397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 455397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (codec_type_a == codec_type_b) && (codec_type_a == A2DP_MEDIA_CT_SBC); 45679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 45779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 458397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_CodecEqualsSbc(const uint8_t* p_codec_info_a, 459397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info_b) { 460397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_a; 461397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_b; 462397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 463397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check whether the codec info contains valid data 464397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status = 4655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_ParseInfoSbc(&sbc_cie_a, p_codec_info_a, true); 466397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 467397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 468397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 469397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 470397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 4715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie_b, p_codec_info_b, true); 472397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 473397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 474397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 475397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 476397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 477397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 478397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a); 479397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b); 480397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 481397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((codec_type_a != codec_type_b) || (codec_type_a != A2DP_MEDIA_CT_SBC)) 482397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 483397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 484397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (sbc_cie_a.samp_freq == sbc_cie_b.samp_freq) && 485397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.ch_mode == sbc_cie_b.ch_mode) && 486397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.block_len == sbc_cie_b.block_len) && 487397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.num_subbands == sbc_cie_b.num_subbands) && 488397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.alloc_method == sbc_cie_b.alloc_method) && 489397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.min_bitpool == sbc_cie_b.min_bitpool) && 490397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.max_bitpool == sbc_cie_b.max_bitpool); 491c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov} 492c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov 493cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovint A2DP_GetTrackSampleRateSbc(const uint8_t* p_codec_info) { 494397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 495d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 496feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 497397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 498397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 499397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 500397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 501397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 502d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 503397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.samp_freq) { 504f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_16: 505397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 16000; 506f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_32: 507397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 32000; 508f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_44: 509397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 44100; 510f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_48: 511397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 48000; 512d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 513397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 514397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 515d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 516397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 517d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 518d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 5195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovint A2DP_GetTrackBitsPerSampleSbc(const uint8_t* p_codec_info) { 5205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 5215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 5225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 5235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 5245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 5255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_status); 5265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return -1; 5275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 5285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 5295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return 16; // For SBC we always use 16 bits per audio sample 5305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 5315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 532397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetTrackChannelCountSbc(const uint8_t* p_codec_info) { 533397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 534d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 535feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 536397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 537397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 538397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 539397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 540397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 541d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 542397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 543f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 544397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 1; 545f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 546f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 547f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 548397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 2; 549d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 550397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 551397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 552d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 553397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 554d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 555d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 556397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetNumberOfSubbandsSbc(const uint8_t* p_codec_info) { 557397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 558d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 559feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 560397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 561397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 562397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 563397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 564397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 565d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 566397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.num_subbands) { 567f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_4: 568397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 4; 569f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_8: 570397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 8; 571d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 572397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 573397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 574d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 575397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 576d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 577d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 578397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetNumberOfBlocksSbc(const uint8_t* p_codec_info) { 579397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 580d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 581feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 582397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 583397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 584397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 585397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 586397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 587d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 588397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.block_len) { 589f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_4: 590397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 4; 591f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_8: 592397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 8; 593f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_12: 594397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 12; 595f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_16: 596397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 16; 597d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 598397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 599397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 600d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 601397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 602d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 603d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 604397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetAllocationMethodCodeSbc(const uint8_t* p_codec_info) { 605397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 606d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 607feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 608397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 609397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 610397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 611397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 612397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 613d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 614397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.alloc_method) { 615f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_S: 616397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_SNR; 617f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_L: 618397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_LOUDNESS; 619d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 620397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 621397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 622d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 623397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 624d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 625d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 626397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetChannelModeCodeSbc(const uint8_t* p_codec_info) { 627397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 628d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 629feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 630397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 631397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 632397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 633397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 634397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 635d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 636397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 637f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 638397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_MONO; 639f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 640397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_DUAL; 641f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 642397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_STEREO; 643f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 644397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_JOINT_STEREO; 645d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 646397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 647397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 648d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 649397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 650d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 651d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 652397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetSamplingFrequencyCodeSbc(const uint8_t* p_codec_info) { 653397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 654d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 655feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 656397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 657397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 658397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 659397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 660397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 661d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 662397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.samp_freq) { 663f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_16: 664397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf16000; 665f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_32: 666397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf32000; 667f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_44: 668397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf44100; 669f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_48: 670397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf48000; 671d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 672397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 673397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 674d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 675397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 676d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 677d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 678397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetMinBitpoolSbc(const uint8_t* p_codec_info) { 679397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 680b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 6815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, true); 682397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 683397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 684397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 685397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 686397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 687b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 688397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return sbc_cie.min_bitpool; 689b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 690b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 691397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetMaxBitpoolSbc(const uint8_t* p_codec_info) { 692397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 693b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 6945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, true); 695397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 696397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 697397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 698397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 699397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 700b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 701397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return sbc_cie.max_bitpool; 702b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 703b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 704397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetSinkTrackChannelTypeSbc(const uint8_t* p_codec_info) { 705397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 706d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 707feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 708397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 709397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 710397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 711397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 712397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 713d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 714397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 715f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 716397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 1; 717f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 718f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 719f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 720397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 3; 721d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 722397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 723397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 724d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 725397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 726d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 727d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 728f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovint A2DP_GetSinkFramesCountToProcessSbc(uint64_t time_interval_ms, 729397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info) { 730397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 731397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint32_t freq_multiple; 732397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint32_t num_blocks; 733397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint32_t num_subbands; 734397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov int frames_to_process; 735397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 736feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 737397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 738397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 739397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 740397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 741397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 742397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 743397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the sample frequency 744397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.samp_freq) { 745f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_16: 746397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (16000)", __func__, 747397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 748397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = 16 * time_interval_ms; 749397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 750f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_32: 751397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (32000)", __func__, 752397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 753397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = 32 * time_interval_ms; 754397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 755f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_44: 756397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (44100)", __func__, 757397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 758397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = (441 * time_interval_ms) / 10; 759397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 760f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_48: 761397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (48000)", __func__, 762d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.samp_freq); 763397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = 48 * time_interval_ms; 764397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 765397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 766397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown frequency: %d", __func__, 767397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 768397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 769397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 770d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 771397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the channel mode 772397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 773f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 774397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (Mono)", __func__, sbc_cie.ch_mode); 775397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 776f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 777397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (DUAL)", __func__, sbc_cie.ch_mode); 778397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 779f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 780397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (STEREO)", __func__, 781397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.ch_mode); 782397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 783f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 784397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (JOINT)", __func__, sbc_cie.ch_mode); 785397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 786d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 787397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown channel mode: %d", __func__, 788397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.ch_mode); 789397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 790397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 791d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 792397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the block length 793397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.block_len) { 794f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_4: 795397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (4)", __func__, sbc_cie.block_len); 796397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 4; 797397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 798f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_8: 799397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (8)", __func__, sbc_cie.block_len); 800397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 8; 801397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 802f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_12: 803397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (12)", __func__, 804397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.block_len); 805397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 12; 806397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 807f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_16: 808397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (16)", __func__, 809d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.block_len); 810397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 16; 811397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 812397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 813397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown block length: %d", __func__, 814397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.block_len); 815397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 816397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 817d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 818397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the number of sub-bands 819397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.num_subbands) { 820f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_4: 821397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: num_subbands:%d (4)", __func__, 822397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.num_subbands); 823397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_subbands = 4; 824397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 825f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_8: 826397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: num_subbands:%d (8)", __func__, 827d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.num_subbands); 828397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_subbands = 8; 829397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 830397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 831397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown number of subbands: %d", __func__, 832397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.num_subbands); 833397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 834397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 835d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 836397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the allocation method 837397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.alloc_method) { 838f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_S: 839397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: alloc_method:%d (SNR)", __func__, 840397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.alloc_method); 841397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 842f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_L: 843397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: alloc_method:%d (Loudness)", __func__, 844d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.alloc_method); 845397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 846397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 847397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown allocation method: %d", __func__, 848397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.alloc_method); 849397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 850397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 851d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 852397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: Bit pool Min:%d Max:%d", __func__, 853397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.min_bitpool, sbc_cie.max_bitpool); 854d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 855397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov frames_to_process = ((freq_multiple) / (num_blocks * num_subbands)) + 1; 856d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 857397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return frames_to_process; 8587aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov} 8597aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov 860feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovbool A2DP_GetPacketTimestampSbc(UNUSED_ATTR const uint8_t* p_codec_info, 861397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_data, uint32_t* p_timestamp) { 862397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_timestamp = *(const uint32_t*)p_data; 863397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 864b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 865b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 866397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_BuildCodecHeaderSbc(UNUSED_ATTR const uint8_t* p_codec_info, 867397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov BT_HDR* p_buf, uint16_t frames_per_packet) { 868397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t* p; 869b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 870397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_buf->offset -= A2DP_SBC_MPL_HDR_LEN; 871397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p = (uint8_t*)(p_buf + 1) + p_buf->offset; 872397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_buf->len += A2DP_SBC_MPL_HDR_LEN; 873cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov A2DP_BuildMediaPayloadHeaderSbc(p, false, false, false, 874cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov (uint8_t)frames_per_packet); 875b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 876397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 877b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 878b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 879397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovvoid A2DP_DumpCodecInfoSbc(const uint8_t* p_codec_info) { 880397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status; 881397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 882397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 883397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s", __func__); 884397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 8855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, true); 886397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 887feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: A2DP_ParseInfoSbc fail:%d", __func__, a2dp_status); 888397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return; 889397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 890397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 8915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq: 0x%x", sbc_cie.samp_freq); 8925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_16) { 8935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq: (16000)"); 8945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 8955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_32) { 8965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq: (32000)"); 8975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 8985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 8995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq: (44100)"); 9005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 9025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq: (48000)"); 903397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 904397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 9055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode: 0x%x", sbc_cie.ch_mode); 9065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 9075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode: (Mono)"); 9085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 9105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode: (Dual)"); 9115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 9135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode: (Stereo)"); 9145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 9165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode: (Joint)"); 917397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 918397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 9195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len: 0x%x", sbc_cie.block_len); 9205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_4) { 9215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len: (4)"); 9225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_8) { 9245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len: (8)"); 9255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_12) { 9275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len: (12)"); 9285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_16) { 9305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len: (16)"); 931397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 932397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 9335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tnum_subbands: 0x%x", sbc_cie.num_subbands); 9345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.num_subbands & A2DP_SBC_IE_SUBBAND_4) { 9355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tnum_subbands: (4)"); 9365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.num_subbands & A2DP_SBC_IE_SUBBAND_8) { 9385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tnum_subbands: (8)"); 939397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 940397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 9415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\talloc_method: 0x%x)", sbc_cie.alloc_method); 9425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.alloc_method & A2DP_SBC_IE_ALLOC_MD_S) { 9435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\talloc_method: (SNR)"); 9445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.alloc_method & A2DP_SBC_IE_ALLOC_MD_L) { 9465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\talloc_method: (Loundess)"); 947397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 948397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 949397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tBit pool Min:%d Max:%d", sbc_cie.min_bitpool, 950397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.max_bitpool); 9517aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov} 9521394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 953397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterfaceSbc( 954397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info) { 955397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (!A2DP_IsSourceCodecValidSbc(p_codec_info)) return NULL; 9561394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 957397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return &a2dp_encoder_interface_sbc; 9581394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov} 959b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 960b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavovbool A2DP_AdjustCodecSbc(uint8_t* p_codec_info) { 961b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 962b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 9635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) != A2DP_SUCCESS) 964b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov return false; 965b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 966b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov // Updated the max bitpool 967b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov if (cfg_cie.max_bitpool > A2DP_SBC_MAX_BITPOOL) { 968b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov LOG_WARN(LOG_TAG, "Updated the SBC codec max bitpool from %d to %d", 969b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov cfg_cie.max_bitpool, A2DP_SBC_MAX_BITPOOL); 970b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov cfg_cie.max_bitpool = A2DP_SBC_MAX_BITPOOL; 971b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov } 972b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 973feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &cfg_cie, p_codec_info) == 974feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_SUCCESS); 975b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov} 9765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbtav_a2dp_codec_index_t A2DP_SourceCodecIndexSbc( 9785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR const uint8_t* p_codec_info) { 9795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return BTAV_A2DP_CODEC_INDEX_SOURCE_SBC; 9805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 9815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovconst char* A2DP_CodecIndexStrSbc(void) { return "SBC"; } 9835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovconst char* A2DP_CodecIndexStrSbcSink(void) { return "SBC SINK"; } 9855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2DP_InitCodecConfigSbc(tAVDT_CFG* p_cfg) { 9875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_caps, 9885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_cfg->codec_info) != A2DP_SUCCESS) { 9895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 9905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#if (BTA_AV_CO_CP_SCMS_T == TRUE) 9935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov /* Content protection info - support SCMS-T */ 9945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t* p = p_cfg->protect_info; 9955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov *p++ = AVDT_CP_LOSC; 9965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UINT16_TO_STREAM(p, AVDT_CP_SCMS_T_ID); 9975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_cfg->num_protect = 1; 9985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#endif 9995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2DP_InitCodecConfigSbcSink(tAVDT_CFG* p_cfg) { 10045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_sink_caps, 10055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_cfg->codec_info) != A2DP_SUCCESS) { 10065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 10075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovUNUSED_ATTR static void build_codec_config(const tA2DP_SBC_CIE& config_cie, 10135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* result) { 10145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) 10155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 10165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) 10175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 10185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; 10205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO) 10225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 10235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.ch_mode & (A2DP_SBC_IE_CH_MD_STEREO | A2DP_SBC_IE_CH_MD_JOINT | 10255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_SBC_IE_CH_MD_DUAL)) { 10265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 10275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovA2dpCodecConfigSbc::A2dpCodecConfigSbc() 10315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC") {} 10325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovA2dpCodecConfigSbc::~A2dpCodecConfigSbc() {} 10345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbc::init() { 10365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (!isValid()) return false; 10375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Load the encoder 10395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (!A2DP_LoadEncoderSbc()) { 10405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot load the encoder", __func__); 10415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 10425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 10485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the best sample rate from |samp_freq|. 10495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 10505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 10515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 10525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_best_sample_rate(uint8_t samp_freq, tA2DP_SBC_CIE* p_result, 10535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 10545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 10555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 10565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 10575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 10605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 10615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 10625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 10655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 10685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the audio sample rate from |p_codec_audio_config|. 10695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |samp_freq| contains the capability. 10705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 10715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 10725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 10735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_audio_sample_rate( 10745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov const btav_a2dp_codec_config_t* p_codec_audio_config, uint8_t samp_freq, 10755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE* p_result, btav_a2dp_codec_config_t* p_codec_config) { 10765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (p_codec_audio_config->sample_rate) { 10775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_44100: 10785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 10795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 10805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 10815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 10845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_48000: 10855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 10865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 10875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 10885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 10915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_88200: 10925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_96000: 10935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_176400: 10945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_192000: 10955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE: 10965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 10975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 11005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 11015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the best bits per sample. 11045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_codec_config|. 11055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 11065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_best_bits_per_sample( 11085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 11095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; 11105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 11125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the audio bits per sample from |p_codec_audio_config|. 11155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_codec_config|. 11165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 11175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_audio_bits_per_sample( 11195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov const btav_a2dp_codec_config_t* p_codec_audio_config, 11205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 11215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (p_codec_audio_config->bits_per_sample) { 11225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16: 11235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; 11245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24: 11265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32: 11275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE: 11285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 11315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 11325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the best channel mode from |ch_mode|. 11355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 11365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 11375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_best_channel_mode(uint8_t ch_mode, tA2DP_SBC_CIE* p_result, 11395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 11405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 11415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 11425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 11465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 11475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 11515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 11525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 11565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_MONO; 11575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 11585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 11615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 11625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the audio channel mode from |p_codec_audio_config|. 11655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |ch_mode| contains the capability. 11665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 11675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 11685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_audio_channel_mode( 11705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov const btav_a2dp_codec_config_t* p_codec_audio_config, uint8_t ch_mode, 11715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE* p_result, btav_a2dp_codec_config_t* p_codec_config) { 11725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (p_codec_audio_config->channel_mode) { 11735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO: 11745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 11755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_MONO; 11765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 11775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO: 11815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 11825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 11835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 11875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 11885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 11925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 11935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE: 11985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 12025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 12035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info, 12055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov bool is_capability, 12065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t* p_result_codec_config) { 12075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov std::lock_guard<std::recursive_mutex> lock(codec_mutex_); 12085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE sink_info_cie; 12095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE result_config_cie; 12105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t samp_freq; 12115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t ch_mode; 12125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t block_len; 12135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t num_subbands; 12145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t alloc_method; 12155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Save the internal state 12175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_config = codec_config_; 12185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_capability = codec_capability_; 12195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_; 12205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_; 12215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE]; 12225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t saved_ota_codec_peer_capability[AVDT_CODEC_SIZE]; 12235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t saved_ota_codec_peer_config[AVDT_CODEC_SIZE]; 12245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(saved_ota_codec_config, ota_codec_config_, sizeof(ota_codec_config_)); 12255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(saved_ota_codec_peer_capability, ota_codec_peer_capability_, 12265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_capability_)); 12275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(saved_ota_codec_peer_config, ota_codec_peer_config_, 12285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_config_)); 12295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_STATUS status = 12315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_ParseInfoSbc(&sink_info_cie, p_peer_codec_info, is_capability); 12325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (status != A2DP_SUCCESS) { 12335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: can't parse peer's Sink capabilities: error = %d", 12345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, status); 12355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 12365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 12395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Build the preferred configuration 12405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 12415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memset(&result_config_cie, 0, sizeof(result_config_cie)); 12425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 12445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the sample frequency 12455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 12465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov samp_freq = a2dp_sbc_caps.samp_freq & sink_info_cie.samp_freq; 12475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE; 12485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (codec_user_config_.sample_rate) { 12495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_44100: 12505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 12515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 12525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate = codec_user_config_.sample_rate; 12535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = codec_user_config_.sample_rate; 12545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_48000: 12575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 12585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 12595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate = codec_user_config_.sample_rate; 12605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = codec_user_config_.sample_rate; 12615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_88200: 12645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_96000: 12655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_176400: 12665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_192000: 12675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE: 12685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE; 12695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE; 12705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the sample frequency if there is no user preference 12745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov do { 12755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break; 12765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Compute the common capability 12785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) 12795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 12805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) 12815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 12825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the codec audio config 12845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_audio_sample_rate(&codec_audio_config_, samp_freq, 12855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 12865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the default config 12905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_sample_rate( 12915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_sbc_default_config.samp_freq & sink_info_cie.samp_freq, 12925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 12935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the best match 12975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_sample_rate(samp_freq, &result_config_cie, 12985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &codec_config_)) { 12995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } while (false); 13025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) { 13035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 13045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match sample frequency: source caps = 0x%x " 13055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "sink info = 0x%x", 13065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.samp_freq, sink_info_cie.samp_freq); 13075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 13085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the bits per sample 13125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // NOTE: this information is NOT included in the SBC A2DP codec description 13145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // that is sent OTA. 13155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE; 13165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (codec_user_config_.bits_per_sample) { 13175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16: 13185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.bits_per_sample = codec_user_config_.bits_per_sample; 13195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.bits_per_sample = codec_user_config_.bits_per_sample; 13205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24: 13225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32: 13235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE: 13245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE; 13255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE; 13265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the bits per sample if there is no user preference 13305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov do { 13315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) 13325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Compute the common capability 13355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; 13365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the codec audio config 13385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_audio_bits_per_sample(&codec_audio_config_, &codec_config_)) { 13395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the default config 13435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_bits_per_sample(&codec_config_)) { 13445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the best match 13485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // TODO: no-op - temporary kept here for consistency 13495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_bits_per_sample(&codec_config_)) { 13505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } while (false); 13535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) { 13545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 13555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match bits per sample: user preference = 0x%x", 13565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, codec_user_config_.bits_per_sample); 13575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 13585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the channel mode 13625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov ch_mode = a2dp_sbc_caps.ch_mode & sink_info_cie.ch_mode; 13645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE; 13655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (codec_user_config_.channel_mode) { 13665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO: 13675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 13685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_MONO; 13695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 13705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 13715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO: 13745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 13755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 13765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 13775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 13785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 13815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 13825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 13835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 13845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 13875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 13885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 13895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 13905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE: 13945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE; 13955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE; 13965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the channel mode if there is no user preference 14005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov do { 14015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break; 14025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Compute the common capability 14045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) 14055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 14065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & (A2DP_SBC_IE_CH_MD_JOINT | A2DP_SBC_IE_CH_MD_STEREO | 14075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_SBC_IE_CH_MD_DUAL)) { 14085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 14095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the codec audio config 14125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_audio_channel_mode(&codec_audio_config_, ch_mode, 14135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 14145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 14155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the default config 14185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_channel_mode( 14195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_sbc_default_config.ch_mode & sink_info_cie.ch_mode, 14205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 14215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 14225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the best match 14255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_channel_mode(ch_mode, &result_config_cie, &codec_config_)) { 14265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 14275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } while (false); 14295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) { 14305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 14315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match channel mode: source caps = 0x%x " 14325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "sink info = 0x%x", 14335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.ch_mode, sink_info_cie.ch_mode); 14345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 14355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the block length 14395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov block_len = a2dp_sbc_caps.block_len & sink_info_cie.block_len; 14415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (block_len & A2DP_SBC_IE_BLOCKS_16) { 14425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_16; 14435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (block_len & A2DP_SBC_IE_BLOCKS_12) { 14445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_12; 14455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (block_len & A2DP_SBC_IE_BLOCKS_8) { 14465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_8; 14475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (block_len & A2DP_SBC_IE_BLOCKS_4) { 14485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_4; 14495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 14505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 14515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match block length: source caps = 0x%x " 14525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "sink info = 0x%x", 14535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.block_len, sink_info_cie.block_len); 14545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 14555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the number of sub-bands 14595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov num_subbands = a2dp_sbc_caps.num_subbands & sink_info_cie.num_subbands; 14615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (num_subbands & A2DP_SBC_IE_SUBBAND_8) { 14625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.num_subbands = A2DP_SBC_IE_SUBBAND_8; 14635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (num_subbands & A2DP_SBC_IE_SUBBAND_4) { 14645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.num_subbands = A2DP_SBC_IE_SUBBAND_4; 14655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 14665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 14675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match number of sub-bands: source caps = 0x%x " 14685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "sink info = 0x%x", 14695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.num_subbands, sink_info_cie.num_subbands); 14705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 14715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the allocation method 14755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov alloc_method = a2dp_sbc_caps.alloc_method & sink_info_cie.alloc_method; 14775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (alloc_method & A2DP_SBC_IE_ALLOC_MD_L) { 14785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.alloc_method = A2DP_SBC_IE_ALLOC_MD_L; 14795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (alloc_method & A2DP_SBC_IE_ALLOC_MD_S) { 14805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.alloc_method = A2DP_SBC_IE_ALLOC_MD_S; 14815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 14825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 14835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match allocation method: source caps = 0x%x " 14845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "sink info = 0x%x", 14855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.alloc_method, sink_info_cie.alloc_method); 14865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 14875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the min/max bitpool 14915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.min_bitpool = a2dp_sbc_caps.min_bitpool; 14935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (result_config_cie.min_bitpool < sink_info_cie.min_bitpool) 14945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.min_bitpool = sink_info_cie.min_bitpool; 14955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.max_bitpool = a2dp_sbc_caps.max_bitpool; 14965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (result_config_cie.max_bitpool > sink_info_cie.max_bitpool) 14975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.max_bitpool = sink_info_cie.max_bitpool; 14985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (result_config_cie.min_bitpool > result_config_cie.max_bitpool) { 14995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 15005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match min/max bitpool: " 15015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "source caps min/max = 0x%x/0x%x sink info min/max = 0x%x/0x%x", 15025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.min_bitpool, a2dp_sbc_caps.max_bitpool, 15035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sink_info_cie.min_bitpool, sink_info_cie.max_bitpool); 15045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 15055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 15065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &result_config_cie, 15085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result_codec_config) != A2DP_SUCCESS) { 15095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 15105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 15115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 15135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Copy the codec-specific fields if they are not zero 15145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 15155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_1 != 0) 15165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_1 = codec_user_config_.codec_specific_1; 15175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_2 != 0) 15185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_2 = codec_user_config_.codec_specific_2; 15195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_3 != 0) 15205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_3 = codec_user_config_.codec_specific_3; 15215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_4 != 0) 15225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_4 = codec_user_config_.codec_specific_4; 15235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Create a local copy of the peer codec capability/config, and the 15255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // result codec config. 15265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (is_capability) { 15275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie, 15285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov ota_codec_peer_capability_); 15295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 15305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie, 15315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov ota_codec_peer_config_); 15325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 15335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov CHECK(status == A2DP_SUCCESS); 15345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &result_config_cie, 15355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov ota_codec_config_); 15365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov CHECK(status == A2DP_SUCCESS); 15375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 15385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovfail: 15405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Restore the internal state 15415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_ = saved_codec_config; 15425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_ = saved_codec_capability; 15435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_user_config_ = saved_codec_user_config; 15445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_audio_config_ = saved_codec_audio_config; 15455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_)); 15465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(ota_codec_peer_capability_, saved_ota_codec_peer_capability, 15475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_capability_)); 15485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(ota_codec_peer_config_, saved_ota_codec_peer_config, 15495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_config_)); 15505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 15515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 15525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovA2dpCodecConfigSbcSink::A2dpCodecConfigSbcSink() 15545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SINK_SBC, "SBC(Sink)") {} 15555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovA2dpCodecConfigSbcSink::~A2dpCodecConfigSbcSink() {} 15575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbcSink::init() { 15595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (!isValid()) return false; 15605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 15625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 15635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbcSink::setCodecConfig( 15655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR const uint8_t* p_peer_codec_info, 15665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR bool is_capability, 15675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR uint8_t* p_result_codec_config) { 15685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // TODO: This method applies only to Source codecs 15695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 15705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 15715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbcSink::updateEncoderUserConfig( 15735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params, 15745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR bool* p_restart_input, UNUSED_ATTR bool* p_restart_output, 15755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR bool* p_config_updated) { 15765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // TODO: This method applies only to Source codecs 15775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 15785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 1579