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