a2dp_sbc.cc revision feee26c3dae12b53773b31f57cf2533a3d993979
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 305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h> 31f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov#include "a2dp_api.h" 32f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov#include "a2dp_int.h" 33f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov#include "a2dp_sbc.h" 34f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov#include "a2dp_sbc_encoder.h" 350df29ac95d057a1bf74b003fa6dd6459743bcf54Mike J. Chen#include "bt_utils.h" 36d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov#include "embdrv/sbc/encoder/include/sbc_encoder.h" 3779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov#include "osi/include/log.h" 38b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov#include "osi/include/osi.h" 3979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 40397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov#define A2DP_SBC_MAX_BITPOOL 53 4179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 42feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov/* data type for the SBC Codec Information Element */ 43397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovtypedef struct { 44397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t samp_freq; /* Sampling frequency */ 45397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t ch_mode; /* Channel mode */ 46397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t block_len; /* Block length */ 47397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t num_subbands; /* Number of subbands */ 48397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t alloc_method; /* Allocation method */ 49397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t min_bitpool; /* Minimum bitpool */ 50397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t max_bitpool; /* Maximum bitpool */ 51f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov} tA2DP_SBC_CIE; 52b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 5379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* SBC SRC codec capabilities */ 54397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovstatic const tA2DP_SBC_CIE a2dp_sbc_caps = { 55397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */ 56397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_CH_MD_JOINT, /* ch_mode */ 57397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_BLOCKS_16, /* block_len */ 58397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ 59397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ 60397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 61397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_MAX_BITPOOL /* max_bitpool */ 6279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 6379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 6479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* SBC SINK codec capabilities */ 65397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovstatic const tA2DP_SBC_CIE a2dp_sbc_sink_caps = { 66397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_SAMP_FREQ_48 | A2DP_SBC_IE_SAMP_FREQ_44), /* samp_freq */ 67f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov (A2DP_SBC_IE_CH_MD_MONO | A2DP_SBC_IE_CH_MD_STEREO | 68397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_CH_MD_JOINT | A2DP_SBC_IE_CH_MD_DUAL), /* ch_mode */ 69397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_BLOCKS_16 | A2DP_SBC_IE_BLOCKS_12 | A2DP_SBC_IE_BLOCKS_8 | 70397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_BLOCKS_4), /* block_len */ 71397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_SUBBAND_4 | A2DP_SBC_IE_SUBBAND_8), /* num_subbands */ 72397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (A2DP_SBC_IE_ALLOC_MD_L | A2DP_SBC_IE_ALLOC_MD_S), /* alloc_method */ 73397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 74397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_MAX_BITPOOL /* max_bitpool */ 7579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 7679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 7779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* Default SBC codec configuration */ 78397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst tA2DP_SBC_CIE a2dp_sbc_default_config = { 79397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SAMP_FREQ_44, /* samp_freq */ 80397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_CH_MD_JOINT, /* ch_mode */ 81397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_BLOCKS_16, /* block_len */ 82397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_SUBBAND_8, /* num_subbands */ 83397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_ALLOC_MD_L, /* alloc_method */ 84397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_IE_MIN_BITPOOL, /* min_bitpool */ 85397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SBC_MAX_BITPOOL /* max_bitpool */ 8679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}; 870df29ac95d057a1bf74b003fa6dd6459743bcf54Mike J. Chen 88f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic const tA2DP_ENCODER_INTERFACE a2dp_encoder_interface_sbc = { 89f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov a2dp_sbc_encoder_init, 90f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov a2dp_sbc_encoder_update, 91f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov a2dp_sbc_encoder_cleanup, 92f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov a2dp_sbc_feeding_init, 93f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov a2dp_sbc_feeding_reset, 94f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov a2dp_sbc_feeding_flush, 95f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov a2dp_sbc_get_encoder_interval_ms, 96f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov a2dp_sbc_send_frames, 97feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov a2dp_sbc_debug_codec_dump 98feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov}; 991394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 100f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic tA2DP_STATUS A2DP_CodecInfoMatchesCapabilitySbc( 101397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const tA2DP_SBC_CIE* p_cap, const uint8_t* p_codec_info, 102397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov bool is_peer_codec_info); 103feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovstatic void A2DP_ParseMplHeaderSbc(uint8_t* p_src, bool* p_frag, bool* p_start, 104feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov bool* p_last, uint8_t* p_num); 105b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 106b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Builds the SBC Media Codec Capabilities byte sequence beginning from the 107b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// LOSC octet. |media_type| is the media type |AVDT_MEDIA_TYPE_*|. 108b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// |p_ie| is a pointer to the SBC Codec Information Element information. 109f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov// The result is stored in |p_result|. Returns A2DP_SUCCESS on success, 110b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// otherwise the corresponding A2DP error status code. 111feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovstatic tA2DP_STATUS A2DP_BuildInfoSbc(uint8_t media_type, 112feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov const tA2DP_SBC_CIE* p_ie, 113feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov uint8_t* p_result) { 114397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS status; 115397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 116397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie == NULL || p_result == NULL || 117397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->samp_freq & ~A2DP_SBC_IE_SAMP_FREQ_MSK) || 118397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->ch_mode & ~A2DP_SBC_IE_CH_MD_MSK) || 119397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->block_len & ~A2DP_SBC_IE_BLOCKS_MSK) || 120397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->num_subbands & ~A2DP_SBC_IE_SUBBAND_MSK) || 121397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->alloc_method & ~A2DP_SBC_IE_ALLOC_MD_MSK) || 122397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->min_bitpool > p_ie->max_bitpool) || 123397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->min_bitpool < A2DP_SBC_IE_MIN_BITPOOL) || 124397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->min_bitpool > A2DP_SBC_IE_MAX_BITPOOL) || 125397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->max_bitpool < A2DP_SBC_IE_MIN_BITPOOL) || 126397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_ie->max_bitpool > A2DP_SBC_IE_MAX_BITPOOL)) { 127397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* if any unused bit is set */ 128397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_INVALID_PARAMS; 129397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else { 130397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_SUCCESS; 131397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = A2DP_SBC_INFO_LEN; 132397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = (media_type << 4); 133397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = A2DP_MEDIA_CT_SBC; 134397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 135397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Media Codec Specific Information Element */ 136397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = p_ie->samp_freq | p_ie->ch_mode; 137397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 138397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = p_ie->block_len | p_ie->num_subbands | p_ie->alloc_method; 139397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 140397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result++ = p_ie->min_bitpool; 141397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_result = p_ie->max_bitpool; 142397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 143397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return status; 1445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 146b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Parses the SBC Media Codec Capabilities byte sequence beginning from the 147b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// LOSC octet. The result is stored in |p_ie|. The byte sequence to parse is 148feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov// |p_codec_info|. If |is_peer_src_codec_info| is true, the byte sequence is 149feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov// for get capabilities response from a peer Source. 150feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov// Returns A2DP_SUCCESS on success, otherwise the corresponding A2DP error 151feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov// status code. 152feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovstatic tA2DP_STATUS A2DP_ParseInfoSbc(tA2DP_SBC_CIE* p_ie, 153feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov const uint8_t* p_codec_info, 154feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov bool is_peer_src_codec_info) { 155397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS status = A2DP_SUCCESS; 156397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t losc; 157397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t media_type; 158397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type; 159397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 160397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie == NULL || p_codec_info == NULL) return A2DP_INVALID_PARAMS; 161397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 162397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the codec capability length 163397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov losc = *p_codec_info++; 164397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (losc != A2DP_SBC_INFO_LEN) return A2DP_WRONG_CODEC; 165397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 166397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov media_type = (*p_codec_info++) >> 4; 167397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov codec_type = *p_codec_info++; 168397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Check the Media Type and Media Codec Type */ 169397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (media_type != AVDT_MEDIA_TYPE_AUDIO || codec_type != A2DP_MEDIA_CT_SBC) { 170397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_WRONG_CODEC; 171397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 172397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 173397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->samp_freq = *p_codec_info & A2DP_SBC_IE_SAMP_FREQ_MSK; 174397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->ch_mode = *p_codec_info & A2DP_SBC_IE_CH_MD_MSK; 175397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_codec_info++; 176397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->block_len = *p_codec_info & A2DP_SBC_IE_BLOCKS_MSK; 177397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->num_subbands = *p_codec_info & A2DP_SBC_IE_SUBBAND_MSK; 178397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->alloc_method = *p_codec_info & A2DP_SBC_IE_ALLOC_MD_MSK; 179397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_codec_info++; 180397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->min_bitpool = *p_codec_info++; 181397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->max_bitpool = *p_codec_info; 182397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie->min_bitpool < A2DP_SBC_IE_MIN_BITPOOL || 183397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->min_bitpool > A2DP_SBC_IE_MAX_BITPOOL) { 184397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_MIN_BITPOOL; 185397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 186397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 187397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_ie->max_bitpool < A2DP_SBC_IE_MIN_BITPOOL || 188397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->max_bitpool > A2DP_SBC_IE_MAX_BITPOOL || 189397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_ie->max_bitpool < p_ie->min_bitpool) { 190397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_MAX_BITPOOL; 191397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 192397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 193397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (is_peer_src_codec_info) return status; 194397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 195397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->samp_freq) != A2DP_SET_ONE_BIT) 196397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_SAMP_FREQ; 197397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->ch_mode) != A2DP_SET_ONE_BIT) 198397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_CH_MODE; 199397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->block_len) != A2DP_SET_ONE_BIT) 200397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_BLOCK_LEN; 201397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->num_subbands) != A2DP_SET_ONE_BIT) 202397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_SUBBANDS; 203397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (A2DP_BitsSet(p_ie->alloc_method) != A2DP_SET_ONE_BIT) 204397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov status = A2DP_BAD_ALLOC_METHOD; 205397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 206397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return status; 2075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 211f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov** Function A2DP_BldSbcMplHdr 2125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 2135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description This function is called by an application to parse 2145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** the SBC Media Payload header. 2155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Input Parameters: 2165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** frag: 1, if fragmented. 0, otherwise. 2175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 2185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** start: 1, if the starting packet of a fragmented frame. 2195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** last: 1, if the last packet of a fragmented frame. 2215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 222397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov** num: If frag is 1, this is the number of remaining 223397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov** fragments (including this fragment) of this frame. 224397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov** If frag is 0, this is the number of frames in 225397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov** this packet. 2265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 2275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Output Parameters: 228397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov** p_dst: the resulting media payload header byte 229397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov** sequence. 2305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 2315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns void. 2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/ 233397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovstatic void A2DP_BldSbcMplHdr(uint8_t* p_dst, bool frag, bool start, bool last, 234397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t num) { 235397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_dst == NULL) return; 236397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 237397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_dst = 0; 238397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (frag) *p_dst |= A2DP_SBC_HDR_F_MSK; 239397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (start) *p_dst |= A2DP_SBC_HDR_S_MSK; 240397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (last) *p_dst |= A2DP_SBC_HDR_L_MSK; 241397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_dst |= (A2DP_SBC_HDR_NUM_MSK & num); 2425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/****************************************************************************** 2455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 246feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov** Function A2DP_ParseMplHeaderSbc 2475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 2485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description This function is called by an application to parse 2495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** the SBC Media Payload header. 2505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Input Parameters: 2515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** p_src: the byte sequence to parse.. 2525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 2535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Output Parameters: 2545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** frag: 1, if fragmented. 0, otherwise. 2555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 2565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** start: 1, if the starting packet of a fragmented frame. 2575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 2585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** last: 1, if the last packet of a fragmented frame. 2595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 260397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov** num: If frag is 1, this is the number of remaining 261397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov** fragments 2625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** (including this fragment) of this frame. 263397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov** If frag is 0, this is the number of frames in 264397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov** this packet. 2655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** 2665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns void. 2675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/ 268feee26c3dae12b53773b31f57cf2533a3d993979Pavlin RadoslavovUNUSED_ATTR static void A2DP_ParseMplHeaderSbc(uint8_t* p_src, bool* p_frag, 269feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov bool* p_start, bool* p_last, 270feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov uint8_t* p_num) { 271397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (p_src && p_frag && p_start && p_last && p_num) { 272397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_frag = (*p_src & A2DP_SBC_HDR_F_MSK) ? true : false; 273397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_start = (*p_src & A2DP_SBC_HDR_S_MSK) ? true : false; 274397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_last = (*p_src & A2DP_SBC_HDR_L_MSK) ? true : false; 275397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_num = (*p_src & A2DP_SBC_HDR_NUM_MSK); 276397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 2775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 279feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovconst char* A2DP_CodecSepIndexStrSbc(void) { 280feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return "SBC"; 281feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov} 282feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov 283feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovconst char* A2DP_CodecSepIndexStrSbcSink(void) { 284feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return "SBC SINK"; 285feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov} 286feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov 287397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_InitCodecConfigSbc(tAVDT_CFG* p_cfg) { 288feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_caps, 289feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov p_cfg->codec_info) != A2DP_SUCCESS) { 290397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 291397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 29279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 29379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov#if (BTA_AV_CO_CP_SCMS_T == TRUE) 294397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Content protection info - support SCMS-T */ 295397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t* p = p_cfg->protect_info; 296feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov *p++ = AVDT_CP_LOSC; 297feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov UINT16_TO_STREAM(p, AVDT_CP_SCMS_T_ID); 298397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_cfg->num_protect = 1; 29979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov#endif 30079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 301397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 30279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 30379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 304397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst char* A2DP_CodecNameSbc(UNUSED_ATTR const uint8_t* p_codec_info) { 305397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return "SBC"; 306b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 307b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 308397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_InitCodecConfigSbcSink(tAVDT_CFG* p_cfg) { 309feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_sink_caps, 310feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov p_cfg->codec_info) != A2DP_SUCCESS) { 311397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 312397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 31379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 314397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 31579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 31679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 317397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSourceCodecValidSbc(const uint8_t* p_codec_info) { 318397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 319a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 320397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 321feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 322feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 323a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 324a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 325397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSinkCodecValidSbc(const uint8_t* p_codec_info) { 326397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 327a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 328397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 329feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 330feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 331a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 332a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 333397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSourceCodecValidSbc(const uint8_t* p_codec_info) { 334397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 335a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 336397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 337feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 338feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 339a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov} 340a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov 341397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSinkCodecValidSbc(const uint8_t* p_codec_info) { 342397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 343b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 344397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Use a liberal check when parsing the codec info */ 345feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) || 346feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS); 347b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 348b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 349397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSourceCodecSupportedSbc(const uint8_t* p_codec_info) { 350397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (A2DP_CodecInfoMatchesCapabilitySbc(&a2dp_sbc_caps, p_codec_info, 351397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov false) == A2DP_SUCCESS); 35279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 35379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 354397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsSinkCodecSupportedSbc(const uint8_t* p_codec_info) { 355397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (A2DP_CodecInfoMatchesCapabilitySbc(&a2dp_sbc_sink_caps, p_codec_info, 356397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov false) == A2DP_SUCCESS); 35779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 35879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 359397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_IsPeerSourceCodecSupportedSbc(const uint8_t* p_codec_info) { 360397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (A2DP_CodecInfoMatchesCapabilitySbc(&a2dp_sbc_sink_caps, p_codec_info, 361397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov true) == A2DP_SUCCESS); 36279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 36379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 364397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovvoid A2DP_InitDefaultCodecSbc(uint8_t* p_codec_info) { 365feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_default_config, 366feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov p_codec_info) != A2DP_SUCCESS) { 367feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: A2DP_BuildInfoSbc failed", __func__); 368397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 36979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 37079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 37182fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavovbool A2DP_SetSourceCodecSbc(const tA2DP_FEEDING_PARAMS* p_feeding_params, 37282fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov uint8_t* p_codec_info) { 373397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_config = a2dp_sbc_default_config; 374397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 375397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s", __func__); 376397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 377397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Check the number of channels */ 378397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((p_feeding_params->num_channel != 1) && 379397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_feeding_params->num_channel != 2)) { 380397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: Unsupported PCM channel number %d", __func__, 381397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_feeding_params->num_channel); 382397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 383397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 384397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 385397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Check the bits per sample */ 386397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((p_feeding_params->bit_per_sample != 8) && 387397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (p_feeding_params->bit_per_sample != 16)) { 388397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: Unsupported PCM sample size %d", __func__, 389397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_feeding_params->bit_per_sample); 390397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 391397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 392397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 393397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Check the sampling frequency */ 394397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (p_feeding_params->sampling_freq) { 395c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov case 8000: 396c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov case 12000: 397c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov case 16000: 398c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov case 24000: 399c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov case 32000: 400c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov case 48000: 401397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_config.samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 402397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 403c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov case 11025: 404c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov case 22050: 405c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov case 44100: 406397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_config.samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 407397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 40879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov default: 409397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: Unsupported PCM sampling frequency %d", __func__, 410397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_feeding_params->sampling_freq); 411397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 412397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 413397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 414397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Build the codec config */ 415feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov if (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &sbc_config, p_codec_info) != 416397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_SUCCESS) { 417feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: A2DP_BuildInfoSbc failed", __func__); 418397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 419397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 420397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 421397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 42279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 42379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 424b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Checks whether A2DP SBC codec configuration matches with a device's codec 425b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// capabilities. |p_cap| is the SBC codec configuration. |p_codec_info| is 426b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// the device's codec capabilities. |is_peer_src_codec_info| is true if 427b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// |p_codec_info| contains the codec capabilities for a peer device that 428b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// is acting as an A2DP source. 429f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov// Returns A2DP_SUCCESS if the codec configuration matches with capabilities, 430b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// otherwise the corresponding A2DP error status code. 431f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovstatic tA2DP_STATUS A2DP_CodecInfoMatchesCapabilitySbc( 432397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const tA2DP_SBC_CIE* p_cap, const uint8_t* p_codec_info, 433397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov bool is_peer_src_codec_info) { 434397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS status; 435397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 436397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 437397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* parse configuration */ 438feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov status = A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, is_peer_src_codec_info); 439397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (status != A2DP_SUCCESS) { 440397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: parsing failed %d", __func__, status); 441397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return status; 442397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 443397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 444397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* verify that each parameter is in range */ 445397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 446397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "FREQ peer: 0x%x, capability 0x%x", cfg_cie.samp_freq, 447397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_cap->samp_freq); 448397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "CH_MODE peer: 0x%x, capability 0x%x", cfg_cie.ch_mode, 449397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_cap->ch_mode); 450397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "BLOCK_LEN peer: 0x%x, capability 0x%x", cfg_cie.block_len, 451397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_cap->block_len); 452397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "SUB_BAND peer: 0x%x, capability 0x%x", 453397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.num_subbands, p_cap->num_subbands); 454397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "ALLOC_METHOD peer: 0x%x, capability 0x%x", 455397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.alloc_method, p_cap->alloc_method); 456397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "MIN_BitPool peer: 0x%x, capability 0x%x", 457397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.min_bitpool, p_cap->min_bitpool); 458397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "MAX_BitPool peer: 0x%x, capability 0x%x", 459397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov cfg_cie.max_bitpool, p_cap->max_bitpool); 460397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 461397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* sampling frequency */ 462397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0) return A2DP_NS_SAMP_FREQ; 463397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 464397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* channel mode */ 465397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.ch_mode & p_cap->ch_mode) == 0) return A2DP_NS_CH_MODE; 466397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 467397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* block length */ 468397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.block_len & p_cap->block_len) == 0) return A2DP_BAD_BLOCK_LEN; 469397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 470397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* subbands */ 471397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.num_subbands & p_cap->num_subbands) == 0) 472397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_NS_SUBBANDS; 473397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 474397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* allocation method */ 475397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((cfg_cie.alloc_method & p_cap->alloc_method) == 0) 476397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_NS_ALLOC_METHOD; 477397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 478397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* min bitpool */ 479397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (cfg_cie.min_bitpool < p_cap->min_bitpool) return A2DP_NS_MIN_BITPOOL; 480397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 481397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* max bitpool */ 482397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (cfg_cie.max_bitpool > p_cap->max_bitpool) return A2DP_NS_MAX_BITPOOL; 483397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 484397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_SUCCESS; 48579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 48679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 487397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin RadoslavovtA2DP_STATUS A2DP_BuildSrc2SinkConfigSbc(const uint8_t* p_src_cap, 488397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t* p_pref_cfg) { 489397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE src_cap; 490397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE pref_cap; 491397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 492397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* initialize it to default SBC configuration */ 493feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &a2dp_sbc_default_config, 494feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov p_pref_cfg); 495397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 496397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* now try to build a preferred one */ 497397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* parse configuration */ 498feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS status = A2DP_ParseInfoSbc(&src_cap, p_src_cap, true); 499397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (status != A2DP_SUCCESS) { 500397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: can't parse src cap ret = %d", __func__, status); 501397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_FAIL; 502397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 503397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 504397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) 505397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.samp_freq = A2DP_SBC_IE_SAMP_FREQ_48; 506397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) 507397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.samp_freq = A2DP_SBC_IE_SAMP_FREQ_44; 508397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 509397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) 510397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_JOINT; 511397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) 512397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_STEREO; 513397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) 514397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_DUAL; 515397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.ch_mode & A2DP_SBC_IE_CH_MD_MONO) 516397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.ch_mode = A2DP_SBC_IE_CH_MD_MONO; 517397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 518397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_16) 519397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_16; 520397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_12) 521397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_12; 522397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_8) 523397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_8; 524397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.block_len & A2DP_SBC_IE_BLOCKS_4) 525397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.block_len = A2DP_SBC_IE_BLOCKS_4; 526397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 527397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.num_subbands & A2DP_SBC_IE_SUBBAND_8) 528397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.num_subbands = A2DP_SBC_IE_SUBBAND_8; 529397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.num_subbands & A2DP_SBC_IE_SUBBAND_4) 530397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.num_subbands = A2DP_SBC_IE_SUBBAND_4; 531397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 532397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (src_cap.alloc_method & A2DP_SBC_IE_ALLOC_MD_L) 533397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.alloc_method = A2DP_SBC_IE_ALLOC_MD_L; 534397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov else if (src_cap.alloc_method & A2DP_SBC_IE_ALLOC_MD_S) 535397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.alloc_method = A2DP_SBC_IE_ALLOC_MD_S; 536397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 537397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.min_bitpool = src_cap.min_bitpool; 538397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov pref_cap.max_bitpool = src_cap.max_bitpool; 539397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 540feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &pref_cap, p_pref_cfg); 541397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 542397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_SUCCESS; 54379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 54479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 545397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin RadoslavovtA2DP_STATUS A2DP_BuildSinkConfigSbc(const uint8_t* p_src_config, 546397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_sink_cap, 547397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t* p_result_sink_config) { 548397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE src_config_cie; 549397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sink_cap_cie; 550397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 551397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Decode the source codec config */ 552397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status = 553feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_ParseInfoSbc(&src_config_cie, p_src_config, false); 554397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 555397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode source codec information: %d", 556397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov __func__, a2dp_status); 557397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_FAIL; 558397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 559397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 560397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Decode the sink codec capabilities */ 561feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sink_cap_cie, p_sink_cap, true); 562397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 563397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode sink capability information: %d", 564397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov __func__, a2dp_status); 565397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_FAIL; 566397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 567397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 568397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Update the bitpool boundaries from the sink codec capabilities */ 569397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov src_config_cie.min_bitpool = sink_cap_cie.min_bitpool; 570397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov src_config_cie.max_bitpool = sink_cap_cie.max_bitpool; 571397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 572397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* Build the result sink config from the source config */ 573feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &src_config_cie, 574feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov p_result_sink_config); 575397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 576397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return A2DP_SUCCESS; 577c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov} 578c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov 579397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_CodecTypeEqualsSbc(const uint8_t* p_codec_info_a, 580397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info_b) { 581397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_a; 582397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_b; 583397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 584397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check whether the codec info contains valid data 585397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status = 586feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_ParseInfoSbc(&sbc_cie_a, p_codec_info_a, false); 587397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 588397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 589397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 590397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 591397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 592feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie_b, p_codec_info_b, false); 593397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 594397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 595397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 596397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 597397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 598397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 599397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a); 600397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b); 601397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 602397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (codec_type_a == codec_type_b) && (codec_type_a == A2DP_MEDIA_CT_SBC); 60379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov} 60479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov 605397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_CodecEqualsSbc(const uint8_t* p_codec_info_a, 606397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info_b) { 607397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_a; 608397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_b; 609397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 610397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check whether the codec info contains valid data 611397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status = 612feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_ParseInfoSbc(&sbc_cie_a, p_codec_info_a, false); 613397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 614397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 615397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 616397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 617397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 618feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie_b, p_codec_info_b, false); 619397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 620397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 621397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 622397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 623397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 624397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 625397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a); 626397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b); 627397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 628397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((codec_type_a != codec_type_b) || (codec_type_a != A2DP_MEDIA_CT_SBC)) 629397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 630397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 631397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (sbc_cie_a.samp_freq == sbc_cie_b.samp_freq) && 632397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.ch_mode == sbc_cie_b.ch_mode) && 633397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.block_len == sbc_cie_b.block_len) && 634397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.num_subbands == sbc_cie_b.num_subbands) && 635397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.alloc_method == sbc_cie_b.alloc_method) && 636397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.min_bitpool == sbc_cie_b.min_bitpool) && 637397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.max_bitpool == sbc_cie_b.max_bitpool); 638c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov} 639c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov 640397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_CodecRequiresReconfigSbc(const uint8_t* p_codec_info_a, 641397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info_b) { 642397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_a; 643397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_b; 644397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 645397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check whether the codec info contains valid data 646397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status = 647feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_ParseInfoSbc(&sbc_cie_a, p_codec_info_a, false); 648397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 649397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 650397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 651397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 652397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 653feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie_b, p_codec_info_b, 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 true; 658397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 659397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 660397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a); 661397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b); 662397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 663397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if ((codec_type_a != codec_type_b) || (codec_type_a != A2DP_MEDIA_CT_SBC)) 664397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 665397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 666397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* NOTE: The min_bitpool and max_bitpool fields are ignored */ 667397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return (sbc_cie_a.samp_freq != sbc_cie_b.samp_freq) || 668397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.ch_mode != sbc_cie_b.ch_mode) || 669397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.block_len != sbc_cie_b.block_len) || 670397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.num_subbands != sbc_cie_b.num_subbands) || 671397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_a.alloc_method != sbc_cie_b.alloc_method); 672c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov} 673c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov 674397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_CodecConfigMatchesCapabilitiesSbc(const uint8_t* p_codec_config, 675397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_caps) { 676397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_config; 677397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie_caps; 678397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 679397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check whether the codec info contains valid data 680397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status = 681feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_ParseInfoSbc(&sbc_cie_config, p_codec_config, false); 682397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 683397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec config: %d", __func__, 684397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 685397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 686397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 687feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie_caps, p_codec_caps, true); 688397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 689397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec capabilities: %d", __func__, 690397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 691397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return false; 692397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 693397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 694397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov /* 695397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov * Must match all SBC codec fields except min/max bitpool boundaries which 696397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov * can be adjusted. 697397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov */ 698397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov bool result = (sbc_cie_config.samp_freq & sbc_cie_caps.samp_freq) && 699397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_config.ch_mode & sbc_cie_caps.ch_mode) && 700397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_config.block_len & sbc_cie_caps.block_len) && 701397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_config.num_subbands & sbc_cie_caps.num_subbands) && 702397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov (sbc_cie_config.alloc_method & sbc_cie_caps.alloc_method); 703397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 704397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s: result=%s", __func__, result ? "true" : "false"); 705397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, 706397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov "%s: config samp_freq=0x%x ch_mode=0x%x " 707397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov "block_len=0x%x num_subbands=0x%x alloc_method=0x%x", 708397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov __func__, sbc_cie_config.samp_freq, sbc_cie_config.ch_mode, 709397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie_config.block_len, sbc_cie_config.num_subbands, 710397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie_config.alloc_method); 711397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, 712397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov "%s: caps samp_freq=0x%x ch_mode=0x%x " 713397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov "block_len=0x%x num_subbands=0x%x alloc_method=0x%x", 714397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov __func__, sbc_cie_caps.samp_freq, sbc_cie_caps.ch_mode, 715397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie_caps.block_len, sbc_cie_caps.num_subbands, 716397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie_caps.alloc_method); 717397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 718397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return result; 719c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov} 720c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov 721397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetTrackFrequencySbc(const uint8_t* p_codec_info) { 722397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 723d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 724feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 725397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 726397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 727397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 728397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 729397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 730d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 731397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.samp_freq) { 732f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_16: 733397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 16000; 734f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_32: 735397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 32000; 736f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_44: 737397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 44100; 738f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_48: 739397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 48000; 740d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 741397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 742397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 743d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 744397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 745d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 746d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 747397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetTrackChannelCountSbc(const uint8_t* p_codec_info) { 748397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 749d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 750feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 751397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 752397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 753397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 754397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 755397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 756d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 757397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 758f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 759397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 1; 760f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 761f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 762f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 763397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 2; 764d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 765397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 766397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 767d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 768397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 769d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 770d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 771397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetNumberOfSubbandsSbc(const uint8_t* p_codec_info) { 772397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 773d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 774feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 775397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 776397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 777397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 778397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 779397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 780d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 781397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.num_subbands) { 782f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_4: 783397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 4; 784f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_8: 785397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 8; 786d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 787397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 788397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 789d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 790397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 791d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 792d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 793397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetNumberOfBlocksSbc(const uint8_t* p_codec_info) { 794397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 795d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 796feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 797397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 798397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 799397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 800397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 801397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 802d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 803397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.block_len) { 804f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_4: 805397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 4; 806f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_8: 807397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 8; 808f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_12: 809397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 12; 810f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_16: 811397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 16; 812d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 813397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 814397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 815d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 816397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 817d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 818d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 819397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetAllocationMethodCodeSbc(const uint8_t* p_codec_info) { 820397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 821d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 822feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 823397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 824397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 825397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 826397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 827397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 828d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 829397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.alloc_method) { 830f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_S: 831397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_SNR; 832f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_L: 833397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_LOUDNESS; 834d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 835397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 836397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 837d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 838397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 839d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 840d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 841397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetChannelModeCodeSbc(const uint8_t* p_codec_info) { 842397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 843d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 844feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 845397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 846397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 847397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 848397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 849397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 850d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 851397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 852f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 853397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_MONO; 854f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 855397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_DUAL; 856f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 857397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_STEREO; 858f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 859397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_JOINT_STEREO; 860d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 861397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 862397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 863d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 864397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 865d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 866d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 867397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetSamplingFrequencyCodeSbc(const uint8_t* p_codec_info) { 868397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 869d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 870feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 871397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 872397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 873397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 874397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 875397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 876d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 877397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.samp_freq) { 878f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_16: 879397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf16000; 880f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_32: 881397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf32000; 882f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_44: 883397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf44100; 884f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_48: 885397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return SBC_sf48000; 886d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 887397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 888397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 889d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 890397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 891d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 892d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 893397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetMinBitpoolSbc(const uint8_t* p_codec_info) { 894397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 895b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 896feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 897397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 898397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 899397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 900397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 901397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 902b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 903397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return sbc_cie.min_bitpool; 904b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 905b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 906397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetMaxBitpoolSbc(const uint8_t* p_codec_info) { 907397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 908b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 909feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 910397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 911397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 912397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 913397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 914397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 915b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 916397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return sbc_cie.max_bitpool; 917b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} 918b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov 919397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovint A2DP_GetSinkTrackChannelTypeSbc(const uint8_t* p_codec_info) { 920397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 921d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 922feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 923397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 924397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 925397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 926397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 927397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 928d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 929397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 930f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 931397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 1; 932f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 933f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 934f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 935397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return 3; 936d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 937397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 938397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 939d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 940397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 941d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov} 942d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 943f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavovint A2DP_GetSinkFramesCountToProcessSbc(uint64_t time_interval_ms, 944397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info) { 945397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 946397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint32_t freq_multiple; 947397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint32_t num_blocks; 948397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint32_t num_subbands; 949397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov int frames_to_process; 950397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 951feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 952397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 953397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, 954397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov a2dp_status); 955397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 956397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 957397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 958397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the sample frequency 959397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.samp_freq) { 960f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_16: 961397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (16000)", __func__, 962397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 963397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = 16 * time_interval_ms; 964397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 965f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_32: 966397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (32000)", __func__, 967397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 968397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = 32 * time_interval_ms; 969397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 970f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_44: 971397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (44100)", __func__, 972397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 973397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = (441 * time_interval_ms) / 10; 974397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 975f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SAMP_FREQ_48: 976397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: samp_freq:%d (48000)", __func__, 977d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.samp_freq); 978397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov freq_multiple = 48 * time_interval_ms; 979397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 980397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 981397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown frequency: %d", __func__, 982397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.samp_freq); 983397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 984397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 985d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 986397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the channel mode 987397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.ch_mode) { 988f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_MONO: 989397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (Mono)", __func__, sbc_cie.ch_mode); 990397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 991f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_DUAL: 992397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (DUAL)", __func__, sbc_cie.ch_mode); 993397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 994f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_STEREO: 995397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (STEREO)", __func__, 996397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.ch_mode); 997397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 998f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_CH_MD_JOINT: 999397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: ch_mode:%d (JOINT)", __func__, sbc_cie.ch_mode); 1000397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 1001d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov default: 1002397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown channel mode: %d", __func__, 1003397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.ch_mode); 1004397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 1005397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 1006d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 1007397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the block length 1008397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.block_len) { 1009f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_4: 1010397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (4)", __func__, sbc_cie.block_len); 1011397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 4; 1012397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 1013f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_8: 1014397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (8)", __func__, sbc_cie.block_len); 1015397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 8; 1016397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 1017f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_12: 1018397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (12)", __func__, 1019397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.block_len); 1020397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 12; 1021397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 1022f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_BLOCKS_16: 1023397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: block_len:%d (16)", __func__, 1024d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.block_len); 1025397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_blocks = 16; 1026397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 1027397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 1028397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown block length: %d", __func__, 1029397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.block_len); 1030397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 1031397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 1032d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 1033397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the number of sub-bands 1034397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.num_subbands) { 1035f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_4: 1036397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: num_subbands:%d (4)", __func__, 1037397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.num_subbands); 1038397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_subbands = 4; 1039397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 1040f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_SUBBAND_8: 1041397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: num_subbands:%d (8)", __func__, 1042d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.num_subbands); 1043397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov num_subbands = 8; 1044397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 1045397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 1046397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown number of subbands: %d", __func__, 1047397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.num_subbands); 1048397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 1049397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 1050d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 1051397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov // Check the allocation method 1052397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov switch (sbc_cie.alloc_method) { 1053f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_S: 1054397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: alloc_method:%d (SNR)", __func__, 1055397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.alloc_method); 1056397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 1057f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov case A2DP_SBC_IE_ALLOC_MD_L: 1058397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: alloc_method:%d (Loudness)", __func__, 1059d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov sbc_cie.alloc_method); 1060397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov break; 1061397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov default: 1062397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: unknown allocation method: %d", __func__, 1063397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.alloc_method); 1064397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return -1; 1065397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 1066d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 1067397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_VERBOSE(LOG_TAG, "%s: Bit pool Min:%d Max:%d", __func__, 1068397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.min_bitpool, sbc_cie.max_bitpool); 1069d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 1070397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov frames_to_process = ((freq_multiple) / (num_blocks * num_subbands)) + 1; 1071d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov 1072397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return frames_to_process; 10737aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov} 10747aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov 1075feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovbool A2DP_GetPacketTimestampSbc(UNUSED_ATTR const uint8_t* p_codec_info, 1076397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_data, uint32_t* p_timestamp) { 1077397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov *p_timestamp = *(const uint32_t*)p_data; 1078397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 1079b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 1080b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 1081397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovbool A2DP_BuildCodecHeaderSbc(UNUSED_ATTR const uint8_t* p_codec_info, 1082397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov BT_HDR* p_buf, uint16_t frames_per_packet) { 1083397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov uint8_t* p; 1084b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 1085397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_buf->offset -= A2DP_SBC_MPL_HDR_LEN; 1086397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p = (uint8_t*)(p_buf + 1) + p_buf->offset; 1087397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov p_buf->len += A2DP_SBC_MPL_HDR_LEN; 1088397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov A2DP_BldSbcMplHdr(p, false, false, false, (uint8_t)frames_per_packet); 1089b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 1090397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return true; 1091b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov} 1092b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov 1093397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovvoid A2DP_DumpCodecInfoSbc(const uint8_t* p_codec_info) { 1094397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_STATUS a2dp_status; 1095397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov tA2DP_SBC_CIE sbc_cie; 1096397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 1097397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "%s", __func__); 1098397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 1099feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false); 1100397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (a2dp_status != A2DP_SUCCESS) { 1101feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov LOG_ERROR(LOG_TAG, "%s: A2DP_ParseInfoSbc fail:%d", __func__, a2dp_status); 1102397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return; 1103397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 1104397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 1105397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (sbc_cie.samp_freq == A2DP_SBC_IE_SAMP_FREQ_16) { 1106397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq:%d (16000)", sbc_cie.samp_freq); 1107397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else if (sbc_cie.samp_freq == A2DP_SBC_IE_SAMP_FREQ_32) { 1108397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq:%d (32000)", sbc_cie.samp_freq); 1109397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else if (sbc_cie.samp_freq == A2DP_SBC_IE_SAMP_FREQ_44) { 1110397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq:%d (44.100)", sbc_cie.samp_freq); 1111397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else if (sbc_cie.samp_freq == A2DP_SBC_IE_SAMP_FREQ_48) { 1112397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tsamp_freq:%d (48000)", sbc_cie.samp_freq); 1113397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else { 1114397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tBAD samp_freq:%d", sbc_cie.samp_freq); 1115397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 1116397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 1117397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (sbc_cie.ch_mode == A2DP_SBC_IE_CH_MD_MONO) { 1118397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode:%d (Mono)", sbc_cie.ch_mode); 1119397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else if (sbc_cie.ch_mode == A2DP_SBC_IE_CH_MD_DUAL) { 1120397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode:%d (Dual)", sbc_cie.ch_mode); 1121397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else if (sbc_cie.ch_mode == A2DP_SBC_IE_CH_MD_STEREO) { 1122397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode:%d (Stereo)", sbc_cie.ch_mode); 1123397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else if (sbc_cie.ch_mode == A2DP_SBC_IE_CH_MD_JOINT) { 1124397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tch_mode:%d (Joint)", sbc_cie.ch_mode); 1125397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else { 1126397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tBAD ch_mode:%d", sbc_cie.ch_mode); 1127397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 1128397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 1129397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (sbc_cie.block_len == A2DP_SBC_IE_BLOCKS_4) { 1130397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len:%d (4)", sbc_cie.block_len); 1131397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else if (sbc_cie.block_len == A2DP_SBC_IE_BLOCKS_8) { 1132397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len:%d (8)", sbc_cie.block_len); 1133397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else if (sbc_cie.block_len == A2DP_SBC_IE_BLOCKS_12) { 1134397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len:%d (12)", sbc_cie.block_len); 1135397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else if (sbc_cie.block_len == A2DP_SBC_IE_BLOCKS_16) { 1136397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tblock_len:%d (16)", sbc_cie.block_len); 1137397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else { 1138397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tBAD block_len:%d", sbc_cie.block_len); 1139397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 1140397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 1141397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (sbc_cie.num_subbands == A2DP_SBC_IE_SUBBAND_4) { 1142397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tnum_subbands:%d (4)", sbc_cie.num_subbands); 1143397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else if (sbc_cie.num_subbands == A2DP_SBC_IE_SUBBAND_8) { 1144397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tnum_subbands:%d (8)", sbc_cie.num_subbands); 1145397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else { 1146397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tBAD num_subbands:%d", sbc_cie.num_subbands); 1147397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 1148397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 1149397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (sbc_cie.alloc_method == A2DP_SBC_IE_ALLOC_MD_S) { 1150397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\talloc_method:%d (SNR)", sbc_cie.alloc_method); 1151397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else if (sbc_cie.alloc_method == A2DP_SBC_IE_ALLOC_MD_L) { 1152397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\talloc_method:%d (Loundess)", sbc_cie.alloc_method); 1153397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } else { 1154397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tBAD alloc_method:%d", sbc_cie.alloc_method); 1155397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov } 1156397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov 1157397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov LOG_DEBUG(LOG_TAG, "\tBit pool Min:%d Max:%d", sbc_cie.min_bitpool, 1158397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov sbc_cie.max_bitpool); 11597aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov} 11601394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 1161397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavovconst tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterfaceSbc( 1162397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov const uint8_t* p_codec_info) { 1163397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov if (!A2DP_IsSourceCodecValidSbc(p_codec_info)) return NULL; 11641394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov 1165397e5a5d6a6e14779af8431734ff605ccc49b2a7Pavlin Radoslavov return &a2dp_encoder_interface_sbc; 11661394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov} 1167b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 1168b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavovbool A2DP_AdjustCodecSbc(uint8_t* p_codec_info) { 1169b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov tA2DP_SBC_CIE cfg_cie; 1170b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 1171feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov if (A2DP_ParseInfoSbc(&cfg_cie, p_codec_info, false) != A2DP_SUCCESS) 1172b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov return false; 1173b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 1174b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov // Updated the max bitpool 1175b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov if (cfg_cie.max_bitpool > A2DP_SBC_MAX_BITPOOL) { 1176b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov LOG_WARN(LOG_TAG, "Updated the SBC codec max bitpool from %d to %d", 1177b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov cfg_cie.max_bitpool, A2DP_SBC_MAX_BITPOOL); 1178b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov cfg_cie.max_bitpool = A2DP_SBC_MAX_BITPOOL; 1179b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov } 1180b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov 1181feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov return (A2DP_BuildInfoSbc(AVDT_MEDIA_TYPE_AUDIO, &cfg_cie, p_codec_info) == 1182feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov A2DP_SUCCESS); 1183b7bb9f066cb2c5268c9f8a24ed0988c0e03b49c8Pavlin Radoslavov} 1184