a2dp_sbc.cc revision f8e2670d12ee55ec48635ef55a86ecfa643cc761
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_sbc_encoder.h" 360df29ac95d057a1bf74b003fa6dd6459743bcf54Mike J. Chen#include "bt_utils.h" 37d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov#include "embdrv/sbc/encoder/include/sbc_encoder.h" 3879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov#include "osi/include/log.h" 39b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov#include "osi/include/osi.h" 4079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 41397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov#define A2DP_SBC_MAX_BITPOOL 53 4279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 43feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov/* data type for the SBC Codec Information Element */ 44397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovtypedef struct { 45397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t samp_freq; /* Sampling frequency */ 46397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t ch_mode; /* Channel mode */ 47397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t block_len; /* Block length */ 48397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t num_subbands; /* Number of subbands */ 49397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t alloc_method; /* Allocation method */ 50397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t min_bitpool; /* Minimum bitpool */ 51397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t max_bitpool; /* Maximum bitpool */ 52f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov} tA2DP_SBC_CIE; 53b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 5479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* SBC SRC codec capabilities */ 55397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovstatic const tA2DP_SBC_CIE a2dp_sbc_caps = { 56397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */ 57397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_CH_MD_JOINT, /* ch_mode */ 58397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_BLOCKS_16, /* block_len */ 59397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ 60397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ 61397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 62397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_MAX_BITPOOL /* max_bitpool */ 6379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 6479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 6579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* SBC SINK codec capabilities */ 66397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovstatic const tA2DP_SBC_CIE a2dp_sbc_sink_caps = { 67397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_SAMP_FREQ_48 | A2DP_SBC_IE_SAMP_FREQ_44), /* samp_freq */ 68f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov (A2DP_SBC_IE_CH_MD_MONO | A2DP_SBC_IE_CH_MD_STEREO | 69397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_CH_MD_JOINT | A2DP_SBC_IE_CH_MD_DUAL), /* ch_mode */ 70397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_BLOCKS_16 | A2DP_SBC_IE_BLOCKS_12 | A2DP_SBC_IE_BLOCKS_8 | 71397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_BLOCKS_4), /* block_len */ 72397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_SUBBAND_4 | A2DP_SBC_IE_SUBBAND_8), /* num_subbands */ 73397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_ALLOC_MD_L | A2DP_SBC_IE_ALLOC_MD_S), /* alloc_method */ 74397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 75d37436670d9d1c0be257c4da41f36a0933ee1418Andre Eisenbach A2DP_SBC_MAX_BITPOOL /* max_bitpool */ 7679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 7779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 7879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* Default SBC codec configuration */ 79397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst tA2DP_SBC_CIE a2dp_sbc_default_config = { 80397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */ 81397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_CH_MD_JOINT, /* ch_mode */ 82397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_BLOCKS_16, /* block_len */ 83397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ 84397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ 85397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 86397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_MAX_BITPOOL /* max_bitpool */ 8779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 880df29ac95d057a1bf74b003fa6dd6459743bcf54Mike J. Chen 89f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic const tA2DP_ENCODER_INTERFACE a2dp_encoder_interface_sbc = { 90f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_encoder_init, 91f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_encoder_cleanup, 92f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_feeding_reset, 93f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_feeding_flush, 94f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_get_encoder_interval_ms, 95f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_send_frames, 96f8e2670d12ee55ec48635ef55a86ecfa643cc761Pavlin Radoslavov a2dp_sbc_debug_codec_dump}; 971394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 98f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic tA2DP_STATUS A2DP_CodecInfoMatchesCapabilitySbc( 99397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const tA2DP_SBC_CIE* p_cap, const uint8_t* p_codec_info, 1005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov bool is_capability); 101feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovstatic void A2DP_ParseMplHeaderSbc(uint8_t* p_src, bool* p_frag, bool* p_start, 102feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov bool* p_last, uint8_t* p_num); 103b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 104b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Builds the SBC Media Codec Capabilities byte sequence beginning from the 105b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// LOSC octet. |media_type| is the media type |AVDT_MEDIA_TYPE_*|. 106b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// |p_ie| is a pointer to the SBC Codec Information Element information. 107f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov// The result is stored in |p_result|. Returns A2DP_SUCCESS on success, 108b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// otherwise the corresponding A2DP error status code. 109feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovstatic tA2DP_STATUS A2DP_BuildInfoSbc(uint8_t media_type, 110feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov const tA2DP_SBC_CIE* p_ie, 111feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov uint8_t* p_result) { 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 */ 124d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_INVALID_PARAMS; 125d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov } 126397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 127d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = A2DP_SBC_INFO_LEN; 128d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = (media_type << 4); 129d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = A2DP_MEDIA_CT_SBC; 130397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 131d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov /* Media Codec Specific Information Element */ 132d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = p_ie->samp_freq | p_ie->ch_mode; 133397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 134d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = p_ie->block_len | p_ie->num_subbands | p_ie->alloc_method; 135d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov 136d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result++ = p_ie->min_bitpool; 137d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov *p_result = p_ie->max_bitpool; 138d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov 139d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_SUCCESS; 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 uint8_t losc; 152397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t media_type; 153397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type; 154397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 155397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie == NULL || p_codec_info == NULL) return A2DP_INVALID_PARAMS; 156397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 157397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the codec capability length 158397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov losc = *p_codec_info++; 159397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (losc != A2DP_SBC_INFO_LEN) return A2DP_WRONG_CODEC; 160397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 161397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov media_type = (*p_codec_info++) >> 4; 162397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov codec_type = *p_codec_info++; 163397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Check the Media Type and Media Codec Type */ 164397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (media_type != AVDT_MEDIA_TYPE_AUDIO || codec_type != A2DP_MEDIA_CT_SBC) { 165397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_WRONG_CODEC; 166397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 167397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 168397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->samp_freq = *p_codec_info & A2DP_SBC_IE_SAMP_FREQ_MSK; 169397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->ch_mode = *p_codec_info & A2DP_SBC_IE_CH_MD_MSK; 170397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_codec_info++; 171397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->block_len = *p_codec_info & A2DP_SBC_IE_BLOCKS_MSK; 172397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->num_subbands = *p_codec_info & A2DP_SBC_IE_SUBBAND_MSK; 173397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->alloc_method = *p_codec_info & A2DP_SBC_IE_ALLOC_MD_MSK; 174397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_codec_info++; 175397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->min_bitpool = *p_codec_info++; 176d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov p_ie->max_bitpool = *p_codec_info++; 177397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie->min_bitpool < A2DP_SBC_IE_MIN_BITPOOL || 178397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->min_bitpool > A2DP_SBC_IE_MAX_BITPOOL) { 179d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_MIN_BITPOOL; 180397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 181397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 182397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie->max_bitpool < A2DP_SBC_IE_MIN_BITPOOL || 183397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->max_bitpool > A2DP_SBC_IE_MAX_BITPOOL || 184397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->max_bitpool < p_ie->min_bitpool) { 185d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_MAX_BITPOOL; 186397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 187397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 188d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov if (is_capability) return A2DP_SUCCESS; 189397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 190397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->samp_freq) != A2DP_SET_ONE_BIT) 191d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_SAMP_FREQ; 192d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov if (A2DP_BitsSet(p_ie->ch_mode) != A2DP_SET_ONE_BIT) return A2DP_BAD_CH_MODE; 193397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->block_len) != A2DP_SET_ONE_BIT) 194d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_BLOCK_LEN; 195397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->num_subbands) != A2DP_SET_ONE_BIT) 196d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_SUBBANDS; 197397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->alloc_method) != A2DP_SET_ONE_BIT) 198d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_BAD_ALLOC_METHOD; 199397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 200d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov return A2DP_SUCCESS; 2015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 203cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// Build the SBC Media Payload Header. 204cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// |p_dst| points to the location where the header should be written to. 205cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// If |frag| is true, the media payload frame is fragmented. 206cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// |start| is true for the first packet of a fragmented frame. 207cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// |last| is true for the last packet of a fragmented frame. 208cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// If |frag| is false, |num| is the number of number of frames in the packet, 209cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// otherwise is the number of remaining fragments (including this one). 210cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic void A2DP_BuildMediaPayloadHeaderSbc(uint8_t* p_dst, bool frag, 211cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov bool start, bool last, 212cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov uint8_t num) { 213397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_dst == NULL) return; 214397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 215397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_dst = 0; 216397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (frag) *p_dst |= A2DP_SBC_HDR_F_MSK; 217397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (start) *p_dst |= A2DP_SBC_HDR_S_MSK; 218397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (last) *p_dst |= A2DP_SBC_HDR_L_MSK; 219397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_dst |= (A2DP_SBC_HDR_NUM_MSK & num); 2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 223ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 224ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function A2DP_ParseMplHeaderSbc 225ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 226ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called by an application to parse 227ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * the SBC Media Payload header. 228ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Input Parameters: 229ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_src: the byte sequence to parse.. 230ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 231ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Output Parameters: 232ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * frag: 1, if fragmented. 0, otherwise. 233ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 234ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * start: 1, if the starting packet of a fragmented frame. 235ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 236ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * last: 1, if the last packet of a fragmented frame. 237ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 238ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * num: If frag is 1, this is the number of remaining 239ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * fragments 240ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * (including this fragment) of this frame. 241ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * If frag is 0, this is the number of frames in 242ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * this packet. 243ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 244ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void. 245ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *****************************************************************************/ 246feee26c3dae12b53773b31f57cf2533a3d993979Pavlin RadoslavovUNUSED_ATTR static void A2DP_ParseMplHeaderSbc(uint8_t* p_src, bool* p_frag, 247feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov bool* p_start, bool* p_last, 248feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov uint8_t* p_num) { 249397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_src && p_frag && p_start && p_last && p_num) { 250397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_frag = (*p_src & A2DP_SBC_HDR_F_MSK) ? true : false; 251397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_start = (*p_src & A2DP_SBC_HDR_S_MSK) ? true : false; 252397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_last = (*p_src & A2DP_SBC_HDR_L_MSK) ? true : false; 253397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_num = (*p_src & A2DP_SBC_HDR_NUM_MSK); 254397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 2555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 257397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst char* A2DP_CodecNameSbc(UNUSED_ATTR const uint8_t* p_codec_info) { 258397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return "SBC"; 259b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 260b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 261397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSourceCodecValidSbc(const uint8_t* p_codec_info) { 262397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 263a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 264397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 265feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 266feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 267a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 268a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 269397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSinkCodecValidSbc(const uint8_t* p_codec_info) { 270397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 271a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 272397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 273feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 274feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 275a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 276a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 277397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSourceCodecValidSbc(const uint8_t* p_codec_info) { 278397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 279a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 280397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 281feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 282feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 283a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 284a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 285397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSinkCodecValidSbc(const uint8_t* p_codec_info) { 286397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 287b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 288397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 289feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 290feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 291b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 292b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 293397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSinkCodecSupportedSbc(const uint8_t* p_codec_info) { 294397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (A2DP_CodecInfoMatchesCapabilitySbc(&a2dp_sbc_sink_caps, p_codec_info, 295397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov false) == A2DP_SUCCESS); 29679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 29779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 298397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSourceCodecSupportedSbc(const uint8_t* p_codec_info) { 299397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (A2DP_CodecInfoMatchesCapabilitySbc(&a2dp_sbc_sink_caps, p_codec_info, 300397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov true) == A2DP_SUCCESS); 30179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 30279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 303397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovvoid A2DP_InitDefaultCodecSbc(uint8_t* p_codec_info) { 304feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_default_config, 305feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov p_codec_info) != A2DP_SUCCESS) { 306feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: A2DP_BuildInfoSbc failed", __func__); 307397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 30879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 30979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 310b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Checks whether A2DP SBC codec configuration matches with a device's codec 311b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// capabilities. |p_cap| is the SBC codec configuration. |p_codec_info| is 3125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// the device's codec capabilities. |is_capability| is true if 3135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |p_codec_info| contains A2DP codec capability. 314f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov// Returns A2DP_SUCCESS if the codec configuration matches with capabilities, 315b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// otherwise the corresponding A2DP error status code. 316f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic tA2DP_STATUS A2DP_CodecInfoMatchesCapabilitySbc( 317397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const tA2DP_SBC_CIE* p_cap, const uint8_t* p_codec_info, 3185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov bool is_capability) { 319397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS status; 320397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 321397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 322397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* parse configuration */ 3235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov status = A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, is_capability); 324397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (status != A2DP_SUCCESS) { 325397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: parsing failed %d", __func__, status); 326397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return status; 327397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 328397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 329397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* verify that each parameter is in range */ 330397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 331d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: FREQ peer: 0x%x, capability 0x%x", __func__, 332d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov cfg_cie.samp_freq, p_cap->samp_freq); 333d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: CH_MODE peer: 0x%x, capability 0x%x", __func__, 334d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov cfg_cie.ch_mode, p_cap->ch_mode); 335d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: BLOCK_LEN peer: 0x%x, capability 0x%x", __func__, 336d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov cfg_cie.block_len, p_cap->block_len); 337d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: SUB_BAND peer: 0x%x, capability 0x%x", __func__, 338397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.num_subbands, p_cap->num_subbands); 339d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: ALLOC_METHOD peer: 0x%x, capability 0x%x", __func__, 340397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.alloc_method, p_cap->alloc_method); 341d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: MIN_BitPool peer: 0x%x, capability 0x%x", __func__, 342397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.min_bitpool, p_cap->min_bitpool); 343d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: MAX_BitPool peer: 0x%x, capability 0x%x", __func__, 344397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.max_bitpool, p_cap->max_bitpool); 345397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 346397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* sampling frequency */ 347397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0) return A2DP_NS_SAMP_FREQ; 348397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 349397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* channel mode */ 350397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.ch_mode & p_cap->ch_mode) == 0) return A2DP_NS_CH_MODE; 351397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 352397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* block length */ 353397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.block_len & p_cap->block_len) == 0) return A2DP_BAD_BLOCK_LEN; 354397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 355397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* subbands */ 356397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.num_subbands & p_cap->num_subbands) == 0) 357397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_NS_SUBBANDS; 358397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 359397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* allocation method */ 360397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.alloc_method & p_cap->alloc_method) == 0) 361397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_NS_ALLOC_METHOD; 362397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 363397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* min bitpool */ 364d37436670d9d1c0be257c4da41f36a0933ee1418Andre Eisenbach if (cfg_cie.min_bitpool > p_cap->max_bitpool) return A2DP_NS_MIN_BITPOOL; 365397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 366397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* max bitpool */ 367d37436670d9d1c0be257c4da41f36a0933ee1418Andre Eisenbach if (cfg_cie.max_bitpool < p_cap->min_bitpool) return A2DP_NS_MAX_BITPOOL; 368397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 369397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_SUCCESS; 37079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 37179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 372397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin RadoslavovtA2DP_STATUS A2DP_BuildSrc2SinkConfigSbc(const uint8_t* p_src_cap, 373397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t* p_pref_cfg) { 374397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE src_cap; 375397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE pref_cap; 376397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 377397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* initialize it to default SBC configuration */ 378feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_default_config, 379feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov p_pref_cfg); 380397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 381397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* now try to build a preferred one */ 382397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* parse configuration */ 383feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS status = A2DP_ParseInfoSbc(&src_cap, p_src_cap, true); 384397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (status != A2DP_SUCCESS) { 385397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: can't parse src cap ret = %d", __func__, status); 386397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_FAIL; 387397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 388397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 389397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) 390397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 391397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) 392397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 393397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 394397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) 395397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 396397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) 397397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 398397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) 399397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 400397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_MONO) 401397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_MONO; 402397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 403397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_16) 404397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_16; 405397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_12) 406397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_12; 407397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_8) 408397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_8; 409397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_4) 410397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_4; 411397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 412397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.num_subbands & A2DP_SBC_IE_SUBBAND_8) 413397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.num_subbands = A2DP_SBC_IE_SUBBAND_8; 414397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.num_subbands & A2DP_SBC_IE_SUBBAND_4) 415397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.num_subbands = A2DP_SBC_IE_SUBBAND_4; 416397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 417397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.alloc_method & A2DP_SBC_IE_ALLOC_MD_L) 418397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.alloc_method = A2DP_SBC_IE_ALLOC_MD_L; 419397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.alloc_method & A2DP_SBC_IE_ALLOC_MD_S) 420397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.alloc_method = A2DP_SBC_IE_ALLOC_MD_S; 421397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 422397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.min_bitpool = src_cap.min_bitpool; 423397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.max_bitpool = src_cap.max_bitpool; 424397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 425feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &pref_cap, p_pref_cfg); 426397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 427397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_SUCCESS; 42879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 42979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 430397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_CodecTypeEqualsSbc(const uint8_t* p_codec_info_a, 431397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info_b) { 432397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_a; 433397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_b; 434397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 435397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check whether the codec info contains valid data 436397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status = 4375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_ParseInfoSbc(&sbc_cie_a, p_codec_info_a, true); 438397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 439397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 440397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 441397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 442397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 4435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie_b, p_codec_info_b, true); 444397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 445397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 446397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 447397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 448397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 449397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 450397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a); 451397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b); 452397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 453397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (codec_type_a == codec_type_b) && (codec_type_a == A2DP_MEDIA_CT_SBC); 45479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 45579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 456397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_CodecEqualsSbc(const uint8_t* p_codec_info_a, 457397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info_b) { 458397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_a; 459397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_b; 460397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 461397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check whether the codec info contains valid data 462397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status = 4635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_ParseInfoSbc(&sbc_cie_a, p_codec_info_a, true); 464397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 465397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 466397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 467397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 468397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 4695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie_b, p_codec_info_b, true); 470397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 471397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 472397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 473397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 474397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 475397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 476397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a); 477397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b); 478397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 479397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((codec_type_a != codec_type_b) || (codec_type_a != A2DP_MEDIA_CT_SBC)) 480397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 481397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 482397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (sbc_cie_a.samp_freq == sbc_cie_b.samp_freq) && 483397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.ch_mode == sbc_cie_b.ch_mode) && 484397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.block_len == sbc_cie_b.block_len) && 485397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.num_subbands == sbc_cie_b.num_subbands) && 486397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.alloc_method == sbc_cie_b.alloc_method) && 487397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.min_bitpool == sbc_cie_b.min_bitpool) && 488397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.max_bitpool == sbc_cie_b.max_bitpool); 489c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov} 490c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov 491cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovint A2DP_GetTrackSampleRateSbc(const uint8_t* p_codec_info) { 492397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 493d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 494feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 495397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 496397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 497397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 498397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 499397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 500d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 501397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.samp_freq) { 502f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_16: 503397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 16000; 504f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_32: 505397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 32000; 506f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_44: 507397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 44100; 508f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_48: 509397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 48000; 510d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 511397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 512397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 513d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 514397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 515d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 516d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 5175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovint A2DP_GetTrackBitsPerSampleSbc(const uint8_t* p_codec_info) { 5185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 5195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 5205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 5215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 5225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 5235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_status); 5245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return -1; 5255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 5265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 5275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return 16; // For SBC we always use 16 bits per audio sample 5285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 5295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 530397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetTrackChannelCountSbc(const uint8_t* p_codec_info) { 531397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 532d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 533feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 534397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 535397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 536397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 537397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 538397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 539d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 540397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 541f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 542397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 1; 543f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 544f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 545f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 546397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 2; 547d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 548397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 549397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 550d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 551397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 552d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 553d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 554397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetNumberOfSubbandsSbc(const uint8_t* p_codec_info) { 555397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 556d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 557feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 558397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 559397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 560397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 561397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 562397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 563d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 564397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.num_subbands) { 565f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_4: 566397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 4; 567f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_8: 568397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 8; 569d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 570397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 571397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 572d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 573397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 574d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 575d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 576397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetNumberOfBlocksSbc(const uint8_t* p_codec_info) { 577397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 578d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 579feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 580397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 581397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 582397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 583397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 584397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 585d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 586397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.block_len) { 587f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_4: 588397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 4; 589f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_8: 590397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 8; 591f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_12: 592397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 12; 593f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_16: 594397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 16; 595d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 596397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 597397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 598d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 599397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 600d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 601d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 602397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetAllocationMethodCodeSbc(const uint8_t* p_codec_info) { 603397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 604d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 605feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 606397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 607397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 608397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 609397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 610397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 611d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 612397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.alloc_method) { 613f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_S: 614397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_SNR; 615f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_L: 616397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_LOUDNESS; 617d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 618397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 619397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 620d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 621397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 622d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 623d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 624397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetChannelModeCodeSbc(const uint8_t* p_codec_info) { 625397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 626d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 627feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 628397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 629397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 630397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 631397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 632397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 633d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 634397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 635f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 636397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_MONO; 637f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 638397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_DUAL; 639f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 640397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_STEREO; 641f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 642397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_JOINT_STEREO; 643d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 644397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 645397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 646d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 647397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 648d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 649d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 650397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetSamplingFrequencyCodeSbc(const uint8_t* p_codec_info) { 651397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 652d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 653feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 654397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 655397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 656397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 657397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 658397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 659d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 660397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.samp_freq) { 661f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_16: 662397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf16000; 663f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_32: 664397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf32000; 665f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_44: 666397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf44100; 667f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_48: 668397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf48000; 669d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 670397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 671397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 672d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 673397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 674d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 675d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 676397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetMinBitpoolSbc(const uint8_t* p_codec_info) { 677397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 678b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 6795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, true); 680397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 681397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 682397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 683397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 684397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 685b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 686397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return sbc_cie.min_bitpool; 687b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 688b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 689397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetMaxBitpoolSbc(const uint8_t* p_codec_info) { 690397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 691b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 6925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, true); 693397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 694397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 695397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 696397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 697397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 698b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 699397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return sbc_cie.max_bitpool; 700b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 701b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 702397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetSinkTrackChannelTypeSbc(const uint8_t* p_codec_info) { 703397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 704d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 705feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 706397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 707397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 708397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 709397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 710397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 711d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 712397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 713f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 714397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 1; 715f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 716f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 717f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 718397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 3; 719d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 720397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 721397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 722d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 723397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 724d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 725d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 726f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovint A2DP_GetSinkFramesCountToProcessSbc(uint64_t time_interval_ms, 727397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info) { 728397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 729397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint32_t freq_multiple; 730397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint32_t num_blocks; 731397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint32_t num_subbands; 732397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov int frames_to_process; 733397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 734feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 735397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 736397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 737397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 738397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 739397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 740397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 741397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the sample frequency 742397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.samp_freq) { 743f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_16: 744397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (16000)", __func__, 745397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 746397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = 16 * time_interval_ms; 747397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 748f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_32: 749397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (32000)", __func__, 750397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 751397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = 32 * time_interval_ms; 752397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 753f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_44: 754397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (44100)", __func__, 755397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 756397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = (441 * time_interval_ms) / 10; 757397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 758f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_48: 759397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (48000)", __func__, 760d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.samp_freq); 761397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = 48 * time_interval_ms; 762397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 763397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 764397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown frequency: %d", __func__, 765397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 766397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 767397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 768d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 769397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the channel mode 770397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 771f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 772397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (Mono)", __func__, sbc_cie.ch_mode); 773397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 774f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 775397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (DUAL)", __func__, sbc_cie.ch_mode); 776397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 777f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 778397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (STEREO)", __func__, 779397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.ch_mode); 780397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 781f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 782397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (JOINT)", __func__, sbc_cie.ch_mode); 783397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 784d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 785397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown channel mode: %d", __func__, 786397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.ch_mode); 787397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 788397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 789d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 790397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the block length 791397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.block_len) { 792f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_4: 793397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (4)", __func__, sbc_cie.block_len); 794397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 4; 795397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 796f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_8: 797397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (8)", __func__, sbc_cie.block_len); 798397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 8; 799397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 800f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_12: 801397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (12)", __func__, 802397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.block_len); 803397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 12; 804397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 805f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_16: 806397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (16)", __func__, 807d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.block_len); 808397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 16; 809397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 810397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 811397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown block length: %d", __func__, 812397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.block_len); 813397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 814397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 815d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 816397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the number of sub-bands 817397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.num_subbands) { 818f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_4: 819397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: num_subbands:%d (4)", __func__, 820397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.num_subbands); 821397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_subbands = 4; 822397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 823f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_8: 824397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: num_subbands:%d (8)", __func__, 825d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.num_subbands); 826397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_subbands = 8; 827397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 828397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 829397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown number of subbands: %d", __func__, 830397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.num_subbands); 831397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 832397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 833d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 834397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the allocation method 835397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.alloc_method) { 836f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_S: 837397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: alloc_method:%d (SNR)", __func__, 838397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.alloc_method); 839397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 840f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_L: 841397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: alloc_method:%d (Loudness)", __func__, 842d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.alloc_method); 843397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 844397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 845397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown allocation method: %d", __func__, 846397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.alloc_method); 847397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 848397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 849d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 850397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: Bit pool Min:%d Max:%d", __func__, 851397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.min_bitpool, sbc_cie.max_bitpool); 852d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 853397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov frames_to_process = ((freq_multiple) / (num_blocks * num_subbands)) + 1; 854d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 855397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return frames_to_process; 8567aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov} 8577aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov 858feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovbool A2DP_GetPacketTimestampSbc(UNUSED_ATTR const uint8_t* p_codec_info, 859397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_data, uint32_t* p_timestamp) { 860397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_timestamp = *(const uint32_t*)p_data; 861397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 862b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 863b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 864397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_BuildCodecHeaderSbc(UNUSED_ATTR const uint8_t* p_codec_info, 865397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov BT_HDR* p_buf, uint16_t frames_per_packet) { 866397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t* p; 867b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 868397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_buf->offset -= A2DP_SBC_MPL_HDR_LEN; 869397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p = (uint8_t*)(p_buf + 1) + p_buf->offset; 870397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_buf->len += A2DP_SBC_MPL_HDR_LEN; 871cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov A2DP_BuildMediaPayloadHeaderSbc(p, false, false, false, 872cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov (uint8_t)frames_per_packet); 873b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 874397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 875b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 876b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 877397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovvoid A2DP_DumpCodecInfoSbc(const uint8_t* p_codec_info) { 878397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status; 879397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 880397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 881397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s", __func__); 882397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 8835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, true); 884397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 885feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: A2DP_ParseInfoSbc fail:%d", __func__, a2dp_status); 886397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return; 887397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 888397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 8895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq: 0x%x", sbc_cie.samp_freq); 8905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_16) { 8915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq: (16000)"); 8925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 8935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_32) { 8945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq: (32000)"); 8955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 8965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 8975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq: (44100)"); 8985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 8995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 9005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq: (48000)"); 901397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 902397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 9035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode: 0x%x", sbc_cie.ch_mode); 9045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 9055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode: (Mono)"); 9065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 9085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode: (Dual)"); 9095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 9115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode: (Stereo)"); 9125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 9145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode: (Joint)"); 915397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 916397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 9175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len: 0x%x", sbc_cie.block_len); 9185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_4) { 9195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len: (4)"); 9205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_8) { 9225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len: (8)"); 9235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_12) { 9255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len: (12)"); 9265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.block_len & A2DP_SBC_IE_BLOCKS_16) { 9285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len: (16)"); 929397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 930397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 9315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tnum_subbands: 0x%x", sbc_cie.num_subbands); 9325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.num_subbands & A2DP_SBC_IE_SUBBAND_4) { 9335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tnum_subbands: (4)"); 9345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.num_subbands & A2DP_SBC_IE_SUBBAND_8) { 9365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tnum_subbands: (8)"); 937397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 938397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 9395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\talloc_method: 0x%x)", sbc_cie.alloc_method); 9405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.alloc_method & A2DP_SBC_IE_ALLOC_MD_S) { 9415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\talloc_method: (SNR)"); 9425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (sbc_cie.alloc_method & A2DP_SBC_IE_ALLOC_MD_L) { 9445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_DEBUG(LOG_TAG, "\talloc_method: (Loundess)"); 945397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 946397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 947397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tBit pool Min:%d Max:%d", sbc_cie.min_bitpool, 948397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.max_bitpool); 9497aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov} 9501394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 951397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterfaceSbc( 952397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info) { 953397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (!A2DP_IsSourceCodecValidSbc(p_codec_info)) return NULL; 9541394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 955397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return &a2dp_encoder_interface_sbc; 9561394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov} 957b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 958b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavovbool A2DP_AdjustCodecSbc(uint8_t* p_codec_info) { 959b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 960b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 9615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) != A2DP_SUCCESS) 962b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov return false; 963b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 964b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov // Updated the max bitpool 965b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov if (cfg_cie.max_bitpool > A2DP_SBC_MAX_BITPOOL) { 966d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov LOG_WARN(LOG_TAG, "%s: Updated the SBC codec max bitpool from %d to %d", 967d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov __func__, cfg_cie.max_bitpool, A2DP_SBC_MAX_BITPOOL); 968b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov cfg_cie.max_bitpool = A2DP_SBC_MAX_BITPOOL; 969b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov } 970b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 971feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &cfg_cie, p_codec_info) == 972feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_SUCCESS); 973b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov} 9745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbtav_a2dp_codec_index_t A2DP_SourceCodecIndexSbc( 9765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR const uint8_t* p_codec_info) { 9775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return BTAV_A2DP_CODEC_INDEX_SOURCE_SBC; 9785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 9795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovconst char* A2DP_CodecIndexStrSbc(void) { return "SBC"; } 9815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovconst char* A2DP_CodecIndexStrSbcSink(void) { return "SBC SINK"; } 9835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2DP_InitCodecConfigSbc(tAVDT_CFG* p_cfg) { 9855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_caps, 9865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_cfg->codec_info) != A2DP_SUCCESS) { 9875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 9885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 9895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#if (BTA_AV_CO_CP_SCMS_T == TRUE) 9915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov /* Content protection info - support SCMS-T */ 9925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t* p = p_cfg->protect_info; 9935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov *p++ = AVDT_CP_LOSC; 9945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UINT16_TO_STREAM(p, AVDT_CP_SCMS_T_ID); 9955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_cfg->num_protect = 1; 9965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#endif 9975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 9985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 9995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2DP_InitCodecConfigSbcSink(tAVDT_CFG* p_cfg) { 10025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_sink_caps, 10035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_cfg->codec_info) != A2DP_SUCCESS) { 10045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 10055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovUNUSED_ATTR static void build_codec_config(const tA2DP_SBC_CIE& config_cie, 10115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* result) { 10125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) 10135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 10145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) 10155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 10165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; 10185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO) 10205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 10215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (config_cie.ch_mode & (A2DP_SBC_IE_CH_MD_STEREO | A2DP_SBC_IE_CH_MD_JOINT | 10235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_SBC_IE_CH_MD_DUAL)) { 10245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 10255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovA2dpCodecConfigSbc::A2dpCodecConfigSbc() 10295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC") {} 10305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovA2dpCodecConfigSbc::~A2dpCodecConfigSbc() {} 10325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbc::init() { 10345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (!isValid()) return false; 10355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Load the encoder 10375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (!A2DP_LoadEncoderSbc()) { 10385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot load the encoder", __func__); 10395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 10405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 10465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the best sample rate from |samp_freq|. 10475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 10485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 10495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 10505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_best_sample_rate(uint8_t samp_freq, tA2DP_SBC_CIE* p_result, 10515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 10525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 10535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 10545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 10555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 10585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 10595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 10605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 10635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 10665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the audio sample rate from |p_codec_audio_config|. 10675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |samp_freq| contains the capability. 10685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 10695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 10705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 10715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_audio_sample_rate( 10725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov const btav_a2dp_codec_config_t* p_codec_audio_config, uint8_t samp_freq, 10735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE* p_result, btav_a2dp_codec_config_t* p_codec_config) { 10745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (p_codec_audio_config->sample_rate) { 10755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_44100: 10765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 10775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 10785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 10795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 10825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_48000: 10835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 10845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 10855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 10865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 10875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 10895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_88200: 10905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_96000: 10915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_176400: 10925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_192000: 10935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE: 10945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 10955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 10965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 10975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 10985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 10995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the best bits per sample. 11025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_codec_config|. 11035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 11045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_best_bits_per_sample( 11065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 11075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; 11085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 11105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the audio bits per sample from |p_codec_audio_config|. 11135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_codec_config|. 11145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 11155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_audio_bits_per_sample( 11175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov const btav_a2dp_codec_config_t* p_codec_audio_config, 11185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 11195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (p_codec_audio_config->bits_per_sample) { 11205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16: 11215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; 11225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24: 11245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32: 11255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE: 11265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 11295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 11305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the best channel mode from |ch_mode|. 11335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 11345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 11355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_best_channel_mode(uint8_t ch_mode, tA2DP_SBC_CIE* p_result, 11375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t* p_codec_config) { 11385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 11395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 11405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 11445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 11455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 11495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 11505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 11545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_MONO; 11555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 11565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 11595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 11605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Selects the audio channel mode from |p_codec_audio_config|. 11635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |ch_mode| contains the capability. 11645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The result is stored in |p_result| and |p_codec_config|. 11655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true if a selection was made, otherwise false. 11665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// 11675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool select_audio_channel_mode( 11685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov const btav_a2dp_codec_config_t* p_codec_audio_config, uint8_t ch_mode, 11695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE* p_result, btav_a2dp_codec_config_t* p_codec_config) { 11705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (p_codec_audio_config->channel_mode) { 11715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO: 11725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 11735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_MONO; 11745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 11755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO: 11795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 11805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 11815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 11855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 11865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 11905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result->ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 11915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_codec_config->channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 11925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 11935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE: 11965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 11975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 11985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 11995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 12005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 12015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info, 12035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov bool is_capability, 12045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t* p_result_codec_config) { 12055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov std::lock_guard<std::recursive_mutex> lock(codec_mutex_); 12065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE sink_info_cie; 12075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_SBC_CIE result_config_cie; 12085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t samp_freq; 12095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t ch_mode; 12105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t block_len; 12115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t num_subbands; 12125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t alloc_method; 12135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Save the internal state 12155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_config = codec_config_; 12165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_capability = codec_capability_; 12175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_; 12185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_; 12195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE]; 12205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t saved_ota_codec_peer_capability[AVDT_CODEC_SIZE]; 12215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov uint8_t saved_ota_codec_peer_config[AVDT_CODEC_SIZE]; 12225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(saved_ota_codec_config, ota_codec_config_, sizeof(ota_codec_config_)); 12235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(saved_ota_codec_peer_capability, ota_codec_peer_capability_, 12245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_capability_)); 12255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(saved_ota_codec_peer_config, ota_codec_peer_config_, 12265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_config_)); 12275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov tA2DP_STATUS status = 12295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_ParseInfoSbc(&sink_info_cie, p_peer_codec_info, is_capability); 12305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (status != A2DP_SUCCESS) { 12315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: can't parse peer's Sink capabilities: error = %d", 12325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, status); 12335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 12345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 12375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Build the preferred configuration 12385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 12395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memset(&result_config_cie, 0, sizeof(result_config_cie)); 12405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 12425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the sample frequency 12435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 12445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov samp_freq = a2dp_sbc_caps.samp_freq & sink_info_cie.samp_freq; 12455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE; 12465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (codec_user_config_.sample_rate) { 12475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_44100: 12485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) { 12495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 12505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate = codec_user_config_.sample_rate; 12515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = codec_user_config_.sample_rate; 12525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_48000: 12555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) { 12565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 12575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate = codec_user_config_.sample_rate; 12585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = codec_user_config_.sample_rate; 12595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_88200: 12625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_96000: 12635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_176400: 12645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_192000: 12655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE: 12665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE; 12675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE; 12685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the sample frequency if there is no user preference 12725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov do { 12735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break; 12745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Compute the common capability 12765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) 12775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100; 12785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) 12795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000; 12805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the codec audio config 12825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_audio_sample_rate(&codec_audio_config_, samp_freq, 12835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 12845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the default config 12885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_sample_rate( 12895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_sbc_default_config.samp_freq & sink_info_cie.samp_freq, 12905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 12915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 12945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the best match 12955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_sample_rate(samp_freq, &result_config_cie, 12965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &codec_config_)) { 12975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 12985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 12995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } while (false); 13005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) { 13015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 13025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match sample frequency: source caps = 0x%x " 13035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "sink info = 0x%x", 13045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.samp_freq, sink_info_cie.samp_freq); 13055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 13065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the bits per sample 13105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // NOTE: this information is NOT included in the SBC A2DP codec description 13125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // that is sent OTA. 13135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE; 13145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (codec_user_config_.bits_per_sample) { 13155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16: 13165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.bits_per_sample = codec_user_config_.bits_per_sample; 13175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.bits_per_sample = codec_user_config_.bits_per_sample; 13185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24: 13205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32: 13215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE: 13225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE; 13235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE; 13245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the bits per sample if there is no user preference 13285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov do { 13295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) 13305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Compute the common capability 13335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16; 13345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the codec audio config 13365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_audio_bits_per_sample(&codec_audio_config_, &codec_config_)) { 13375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the default config 13415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_bits_per_sample(&codec_config_)) { 13425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the best match 13465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // TODO: no-op - temporary kept here for consistency 13475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_bits_per_sample(&codec_config_)) { 13485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } while (false); 13515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) { 13525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 13535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match bits per sample: user preference = 0x%x", 13545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, codec_user_config_.bits_per_sample); 13555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 13565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the channel mode 13605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 13615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov ch_mode = a2dp_sbc_caps.ch_mode & sink_info_cie.ch_mode; 13625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE; 13635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov switch (codec_user_config_.channel_mode) { 13645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO: 13655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) { 13665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_MONO; 13675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 13685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 13695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO: 13725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) { 13735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 13745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 13755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 13765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) { 13795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 13805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 13815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 13825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) { 13855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 13865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = codec_user_config_.channel_mode; 13875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = codec_user_config_.channel_mode; 13885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE: 13925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE; 13935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE; 13945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 13955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 13965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 13975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the channel mode if there is no user preference 13985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov do { 13995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break; 14005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Compute the common capability 14025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) 14035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO; 14045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (ch_mode & (A2DP_SBC_IE_CH_MD_JOINT | A2DP_SBC_IE_CH_MD_STEREO | 14055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov A2DP_SBC_IE_CH_MD_DUAL)) { 14065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO; 14075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the codec audio config 14105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_audio_channel_mode(&codec_audio_config_, ch_mode, 14115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 14125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 14135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - try the default config 14165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_channel_mode( 14175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov a2dp_sbc_default_config.ch_mode & sink_info_cie.ch_mode, 14185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov &result_config_cie, &codec_config_)) { 14195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 14205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // No user preference - use the best match 14235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (select_best_channel_mode(ch_mode, &result_config_cie, &codec_config_)) { 14245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov break; 14255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } while (false); 14275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_config_.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) { 14285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 14295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match channel mode: source caps = 0x%x " 14305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "sink info = 0x%x", 14315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.ch_mode, sink_info_cie.ch_mode); 14325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 14335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the block length 14375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov block_len = a2dp_sbc_caps.block_len & sink_info_cie.block_len; 14395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (block_len & A2DP_SBC_IE_BLOCKS_16) { 14405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_16; 14415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (block_len & A2DP_SBC_IE_BLOCKS_12) { 14425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_12; 14435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (block_len & A2DP_SBC_IE_BLOCKS_8) { 14445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_8; 14455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (block_len & A2DP_SBC_IE_BLOCKS_4) { 14465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.block_len = A2DP_SBC_IE_BLOCKS_4; 14475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 14485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 14495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match block length: source caps = 0x%x " 14505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "sink info = 0x%x", 14515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.block_len, sink_info_cie.block_len); 14525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 14535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the number of sub-bands 14575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov num_subbands = a2dp_sbc_caps.num_subbands & sink_info_cie.num_subbands; 14595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (num_subbands & A2DP_SBC_IE_SUBBAND_8) { 14605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.num_subbands = A2DP_SBC_IE_SUBBAND_8; 14615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (num_subbands & A2DP_SBC_IE_SUBBAND_4) { 14625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.num_subbands = A2DP_SBC_IE_SUBBAND_4; 14635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 14645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 14655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match number of sub-bands: source caps = 0x%x " 14665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "sink info = 0x%x", 14675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.num_subbands, sink_info_cie.num_subbands); 14685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 14695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the allocation method 14735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov alloc_method = a2dp_sbc_caps.alloc_method & sink_info_cie.alloc_method; 14755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (alloc_method & A2DP_SBC_IE_ALLOC_MD_L) { 14765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.alloc_method = A2DP_SBC_IE_ALLOC_MD_L; 14775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else if (alloc_method & A2DP_SBC_IE_ALLOC_MD_S) { 14785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.alloc_method = A2DP_SBC_IE_ALLOC_MD_S; 14795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 14805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 14815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match allocation method: source caps = 0x%x " 14825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "sink info = 0x%x", 14835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.alloc_method, sink_info_cie.alloc_method); 14845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 14855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 14865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 14875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Select the min/max bitpool 14895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 14905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.min_bitpool = a2dp_sbc_caps.min_bitpool; 14915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (result_config_cie.min_bitpool < sink_info_cie.min_bitpool) 14925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.min_bitpool = sink_info_cie.min_bitpool; 14935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.max_bitpool = a2dp_sbc_caps.max_bitpool; 14945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (result_config_cie.max_bitpool > sink_info_cie.max_bitpool) 14955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov result_config_cie.max_bitpool = sink_info_cie.max_bitpool; 14965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (result_config_cie.min_bitpool > result_config_cie.max_bitpool) { 14975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov LOG_ERROR(LOG_TAG, 14985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "%s: cannot match min/max bitpool: " 14995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov "source caps min/max = 0x%x/0x%x sink info min/max = 0x%x/0x%x", 15005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov __func__, a2dp_sbc_caps.min_bitpool, a2dp_sbc_caps.max_bitpool, 15015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sink_info_cie.min_bitpool, sink_info_cie.max_bitpool); 15025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 15035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 15045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &result_config_cie, 15065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov p_result_codec_config) != A2DP_SUCCESS) { 15075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov goto fail; 15085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 15095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 15115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Copy the codec-specific fields if they are not zero 15125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // 15135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_1 != 0) 15145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_1 = codec_user_config_.codec_specific_1; 15155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_2 != 0) 15165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_2 = codec_user_config_.codec_specific_2; 15175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_3 != 0) 15185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_3 = codec_user_config_.codec_specific_3; 15195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (codec_user_config_.codec_specific_4 != 0) 15205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_.codec_specific_4 = codec_user_config_.codec_specific_4; 15215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Create a local copy of the peer codec capability/config, and the 15235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // result codec config. 15245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (is_capability) { 15255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie, 15265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov ota_codec_peer_capability_); 15275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } else { 15285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &sink_info_cie, 15295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov ota_codec_peer_config_); 15305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov } 15315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov CHECK(status == A2DP_SUCCESS); 15325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov status = A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &result_config_cie, 15335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov ota_codec_config_); 15345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov CHECK(status == A2DP_SUCCESS); 15355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 15365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovfail: 15385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // Restore the internal state 15395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_config_ = saved_codec_config; 15405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_capability_ = saved_codec_capability; 15415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_user_config_ = saved_codec_user_config; 15425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov codec_audio_config_ = saved_codec_audio_config; 15435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_)); 15445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(ota_codec_peer_capability_, saved_ota_codec_peer_capability, 15455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_capability_)); 15465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov memcpy(ota_codec_peer_config_, saved_ota_codec_peer_config, 15475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov sizeof(ota_codec_peer_config_)); 15485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 15495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 15505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovA2dpCodecConfigSbcSink::A2dpCodecConfigSbcSink() 15525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SINK_SBC, "SBC(Sink)") {} 15535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovA2dpCodecConfigSbcSink::~A2dpCodecConfigSbcSink() {} 15555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbcSink::init() { 15575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov if (!isValid()) return false; 15585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return true; 15605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 15615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbcSink::setCodecConfig( 15635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR const uint8_t* p_peer_codec_info, 15645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR bool is_capability, 15655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR uint8_t* p_result_codec_config) { 15665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // TODO: This method applies only to Source codecs 15675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 15685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 15695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov 15705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool A2dpCodecConfigSbcSink::updateEncoderUserConfig( 15715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params, 15725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR bool* p_restart_input, UNUSED_ATTR bool* p_restart_output, 15735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov UNUSED_ATTR bool* p_config_updated) { 15745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov // TODO: This method applies only to Source codecs 15755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov return false; 15765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov} 1577