a2dp_sbc.cc revision a0db321d98c98e10f45720075fb9c83e3ef596bf
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
2679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov#define LOG_TAG "a2d_sbc"
2779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_target.h"
2924ff5af9e40aaebc236bb6a16849c63bff0f23baSharvil Nanavati
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h>
315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "a2d_api.h"
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "a2d_int.h"
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "a2d_sbc.h"
340df29ac95d057a1bf74b003fa6dd6459743bcf54Mike J. Chen#include "bt_utils.h"
35d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov#include "embdrv/sbc/encoder/include/sbc_encoder.h"
3679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov#include "osi/include/log.h"
37b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov#include "osi/include/osi.h"
3879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
3979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
4079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov#define A2D_SBC_MAX_BITPOOL  53
4179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
42b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov/* data type for the SBC Codec Information Element*/
43b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavovtypedef struct
44b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov{
45b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    uint8_t samp_freq;      /* Sampling frequency */
46b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    uint8_t ch_mode;        /* Channel mode */
47b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    uint8_t block_len;      /* Block length */
48b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    uint8_t num_subbands;   /* Number of subbands */
49b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    uint8_t alloc_method;   /* Allocation method */
50b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    uint8_t min_bitpool;    /* Minimum bitpool */
51b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    uint8_t max_bitpool;    /* Maximum bitpool */
52b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov} tA2D_SBC_CIE;
53b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
5479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* SBC SRC codec capabilities */
5579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavovstatic const tA2D_SBC_CIE a2d_sbc_caps =
5679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
5779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    A2D_SBC_IE_SAMP_FREQ_44,            /* samp_freq */
5879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    A2D_SBC_IE_CH_MD_JOINT,             /* ch_mode */
5979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    A2D_SBC_IE_BLOCKS_16,               /* block_len */
6079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    A2D_SBC_IE_SUBBAND_8,               /* num_subbands */
61d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    A2D_SBC_IE_ALLOC_MD_L,              /* alloc_method */
62d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    A2D_SBC_IE_MIN_BITPOOL,             /* min_bitpool */
63d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    A2D_SBC_MAX_BITPOOL                 /* max_bitpool */
6479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov};
6579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
6679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* SBC SINK codec capabilities */
6779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavovstatic const tA2D_SBC_CIE a2d_sbc_sink_caps =
6879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
6979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    (A2D_SBC_IE_SAMP_FREQ_48 | A2D_SBC_IE_SAMP_FREQ_44),        /* samp_freq */
7079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    (A2D_SBC_IE_CH_MD_MONO | A2D_SBC_IE_CH_MD_STEREO |
7179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov     A2D_SBC_IE_CH_MD_JOINT | A2D_SBC_IE_CH_MD_DUAL),           /* ch_mode */
7279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    (A2D_SBC_IE_BLOCKS_16 | A2D_SBC_IE_BLOCKS_12 |
7379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov     A2D_SBC_IE_BLOCKS_8 | A2D_SBC_IE_BLOCKS_4),                /* block_len */
7479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    (A2D_SBC_IE_SUBBAND_4 | A2D_SBC_IE_SUBBAND_8),      /* num_subbands */
75d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    (A2D_SBC_IE_ALLOC_MD_L | A2D_SBC_IE_ALLOC_MD_S),    /* alloc_method */
76d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    A2D_SBC_IE_MIN_BITPOOL,                             /* min_bitpool */
77d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    A2D_SBC_IE_MAX_BITPOOL                              /* max_bitpool */
7879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov};
7979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
8079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov/* Default SBC codec configuration */
8179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavovconst tA2D_SBC_CIE a2d_sbc_default_config =
8279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
8379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    A2D_SBC_IE_SAMP_FREQ_44,            /* samp_freq */
8479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    A2D_SBC_IE_CH_MD_JOINT,             /* ch_mode */
8579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    A2D_SBC_IE_BLOCKS_16,               /* block_len */
8679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    A2D_SBC_IE_SUBBAND_8,               /* num_subbands */
87d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    A2D_SBC_IE_ALLOC_MD_L,              /* alloc_method */
88d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    A2D_SBC_IE_MIN_BITPOOL,             /* min_bitpool */
89d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    A2D_SBC_MAX_BITPOOL                 /* max_bitpool */
9079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov};
910df29ac95d057a1bf74b003fa6dd6459743bcf54Mike J. Chen
92b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavovstatic tA2D_STATUS A2D_CodecInfoMatchesCapabilitySbc(
93b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov        const tA2D_SBC_CIE *p_cap,
94b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov        const uint8_t *p_codec_info,
95b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov        bool is_peer_codec_info);
96b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
97b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Builds the SBC Media Codec Capabilities byte sequence beginning from the
98b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// LOSC octet. |media_type| is the media type |AVDT_MEDIA_TYPE_*|.
99b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// |p_ie| is a pointer to the SBC Codec Information Element information.
100b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// The result is stored in |p_result|. Returns A2D_SUCCESS on success,
101b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// otherwise the corresponding A2DP error status code.
102b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavovstatic tA2D_STATUS A2D_BldSbcInfo(uint8_t media_type, const tA2D_SBC_CIE *p_ie,
103b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov                                  uint8_t *p_result)
1045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
1055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    tA2D_STATUS status;
1065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if( p_ie == NULL || p_result == NULL ||
1085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        (p_ie->samp_freq & ~A2D_SBC_IE_SAMP_FREQ_MSK) ||
1095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        (p_ie->ch_mode & ~A2D_SBC_IE_CH_MD_MSK) ||
1105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        (p_ie->block_len & ~A2D_SBC_IE_BLOCKS_MSK) ||
1115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        (p_ie->num_subbands & ~A2D_SBC_IE_SUBBAND_MSK) ||
112d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        (p_ie->alloc_method & ~A2D_SBC_IE_ALLOC_MD_MSK) ||
113d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        (p_ie->min_bitpool > p_ie->max_bitpool) ||
1145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        (p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL) ||
115d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        (p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL) ||
116d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        (p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL) ||
117c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        (p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL)) {
1185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* if any unused bit is set */
1195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        status = A2D_INVALID_PARAMS;
120c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    } else {
1215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        status = A2D_SUCCESS;
1225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        *p_result++ = A2D_SBC_INFO_LEN;
123d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        *p_result++ = (media_type << 4);
1245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        *p_result++ = A2D_MEDIA_CT_SBC;
1255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        /* Media Codec Specific Information Element */
1275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        *p_result++ = p_ie->samp_freq | p_ie->ch_mode;
1285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
129d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        *p_result++ = p_ie->block_len | p_ie->num_subbands | p_ie->alloc_method;
1305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        *p_result++ = p_ie->min_bitpool;
1325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        *p_result   = p_ie->max_bitpool;
1335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return status;
1355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
137b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Parses the SBC Media Codec Capabilities byte sequence beginning from the
138b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// LOSC octet. The result is stored in |p_ie|. The byte sequence to parse is
139b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// |p_codec_info|. If |for_caps| is true, the byte sequence is for get
140b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// capabilities response. Returns A2D_SUCCESS on success, otherwise the
141b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// corresponding A2DP error status code.
142b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavovstatic tA2D_STATUS A2D_ParsSbcInfo(tA2D_SBC_CIE *p_ie,
143b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov                                   const uint8_t *p_codec_info,
144b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov                                   bool is_peer_src_codec_info)
1455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
14676198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge    tA2D_STATUS status = A2D_SUCCESS;
147d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen    uint8_t losc;
148d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    uint8_t media_type;
149d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_CODEC_TYPE codec_type;
1505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (p_ie == NULL || p_codec_info == NULL)
15276198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge        return A2D_INVALID_PARAMS;
153cab5fc179730ce6910989307680b275195876c4dArman Uguray
154d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    // Check the codec capability length
155d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    losc = *p_codec_info++;
156d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (losc != A2D_SBC_INFO_LEN)
157d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return A2D_WRONG_CODEC;
1585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
159d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    media_type = (*p_codec_info++) >> 4;
160d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    codec_type = *p_codec_info++;
161d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    /* Check the Media Type and Media Codec Type */
162d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (media_type != AVDT_MEDIA_TYPE_AUDIO ||
163d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        codec_type != A2D_MEDIA_CT_SBC) {
16476198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge        return A2D_WRONG_CODEC;
165d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
16676198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge
16779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    p_ie->samp_freq = *p_codec_info & A2D_SBC_IE_SAMP_FREQ_MSK;
16879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    p_ie->ch_mode   = *p_codec_info & A2D_SBC_IE_CH_MD_MSK;
16979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    p_codec_info++;
17079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    p_ie->block_len     = *p_codec_info & A2D_SBC_IE_BLOCKS_MSK;
17179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    p_ie->num_subbands  = *p_codec_info & A2D_SBC_IE_SUBBAND_MSK;
172d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    p_ie->alloc_method  = *p_codec_info & A2D_SBC_IE_ALLOC_MD_MSK;
17379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    p_codec_info++;
17479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    p_ie->min_bitpool = *p_codec_info++;
17579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    p_ie->max_bitpool = *p_codec_info;
176d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL ||
177d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL) {
17876198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge        status = A2D_BAD_MIN_BITPOOL;
179d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
18076198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge
181d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL ||
182d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL ||
183d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        p_ie->max_bitpool < p_ie->min_bitpool) {
18476198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge        status = A2D_BAD_MAX_BITPOOL;
185d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
18676198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge
18779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (is_peer_src_codec_info)
18876198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge        return status;
18976198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge
19076198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge    if (A2D_BitsSet(p_ie->samp_freq) != A2D_SET_ONE_BIT)
19176198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge        status = A2D_BAD_SAMP_FREQ;
19276198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge    if (A2D_BitsSet(p_ie->ch_mode) != A2D_SET_ONE_BIT)
19376198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge        status = A2D_BAD_CH_MODE;
19476198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge    if (A2D_BitsSet(p_ie->block_len) != A2D_SET_ONE_BIT)
19576198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge        status = A2D_BAD_BLOCK_LEN;
19676198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge    if (A2D_BitsSet(p_ie->num_subbands) != A2D_SET_ONE_BIT)
19776198e72bf5b8942dbc97bb53c97dba62bf30da1Ian Coolidge        status = A2D_BAD_SUBBANDS;
198d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (A2D_BitsSet(p_ie->alloc_method) != A2D_SET_ONE_BIT)
199d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        status = A2D_BAD_ALLOC_METHOD;
2005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    return status;
2025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
2055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         A2D_BldSbcMplHdr
2075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is called by an application to parse
2095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  the SBC Media Payload header.
2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  Input Parameters:
2115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                      frag:  1, if fragmented. 0, otherwise.
2125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                      start:  1, if the starting packet of a fragmented frame.
2145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                      last:  1, if the last packet of a fragmented frame.
2165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                      num:  If frag is 1, this is the number of remaining fragments
2185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                            (including this fragment) of this frame.
2195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                            If frag is 0, this is the number of frames in this packet.
2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  Output Parameters:
2225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                      p_dst:  the resulting media payload header byte sequence.
2235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          void.
2255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
226b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavovstatic void A2D_BldSbcMplHdr(uint8_t *p_dst, bool frag, bool start, bool last,
227b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov                             uint8_t num)
2285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
229b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    if (p_dst == NULL)
230b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov        return;
231b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov
232b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    *p_dst = 0;
233b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    if (frag)
234b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov        *p_dst |= A2D_SBC_HDR_F_MSK;
235b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    if (start)
236b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov        *p_dst |= A2D_SBC_HDR_S_MSK;
237b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    if (last)
238b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov        *p_dst |= A2D_SBC_HDR_L_MSK;
239b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    *p_dst |= (A2D_SBC_HDR_NUM_MSK & num);
2405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
2435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Function         A2D_ParsSbcMplHdr
2455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Description      This function is called by an application to parse
2475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  the SBC Media Payload header.
2485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  Input Parameters:
2495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                      p_src:  the byte sequence to parse..
2505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                  Output Parameters:
2525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                      frag:  1, if fragmented. 0, otherwise.
2535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                      start:  1, if the starting packet of a fragmented frame.
2555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                      last:  1, if the last packet of a fragmented frame.
2575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                      num:  If frag is 1, this is the number of remaining fragments
2595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                            (including this fragment) of this frame.
2605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**                            If frag is 0, this is the number of frames in this packet.
2615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project**
2625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project** Returns          void.
2635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project******************************************************************************/
264d19e0785e662e640191a075eda07acce61c2aedaMarie Janssenvoid A2D_ParsSbcMplHdr(uint8_t *p_src, bool *p_frag, bool *p_start, bool *p_last, uint8_t *p_num)
2655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project{
2665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    if(p_src && p_frag && p_start && p_last && p_num)
2675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
268d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen        *p_frag = (*p_src & A2D_SBC_HDR_F_MSK) ? true: false;
269d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen        *p_start= (*p_src & A2D_SBC_HDR_S_MSK) ? true: false;
270d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen        *p_last = (*p_src & A2D_SBC_HDR_L_MSK) ? true: false;
2715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        *p_num  = (*p_src & A2D_SBC_HDR_NUM_MSK);
2725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
27579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavovbool A2D_InitCodecConfigSbc(tAVDT_CFG *p_cfg)
27679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
277d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (A2D_BldSbcInfo(AVDT_MEDIA_TYPE_AUDIO, &a2d_sbc_caps,
27879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov                       p_cfg->codec_info) != A2D_SUCCESS) {
27979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        return false;
28079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    }
28179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
28279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov#if (BTA_AV_CO_CP_SCMS_T == TRUE)
28379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* Content protection info - support SCMS-T */
28479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    uint8_t *p = p_cfg->protect_info;
28579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    *p++ = BTA_AV_CP_LOSC;
28679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    UINT16_TO_STREAM(p, BTA_AV_CP_SCMS_T_ID);
28779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    p_cfg->num_protect = 1;
28879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov#endif
28979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
29079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    return true;
29179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}
29279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
293b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavovconst char *A2D_CodecNameSbc(UNUSED_ATTR const uint8_t *p_codec_info)
294b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov{
295b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    return "SBC";
296b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov}
297b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov
29879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavovbool A2D_InitCodecConfigSbcSink(tAVDT_CFG *p_cfg)
29979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
300d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (A2D_BldSbcInfo(AVDT_MEDIA_TYPE_AUDIO, &a2d_sbc_sink_caps,
30179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov                       p_cfg->codec_info) != A2D_SUCCESS) {
30279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        return false;
30379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    }
30479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
30579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    return true;
30679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}
30779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
308a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavovbool A2D_IsSourceCodecValidSbc(const uint8_t *p_codec_info)
309a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov{
310a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    tA2D_SBC_CIE cfg_cie;
311a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov
312a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    /* Use a liberal check when parsing the codec info */
313a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    return (A2D_ParsSbcInfo(&cfg_cie, p_codec_info, false) == A2D_SUCCESS) ||
314a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov      (A2D_ParsSbcInfo(&cfg_cie, p_codec_info, true) == A2D_SUCCESS);
315a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov}
316a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov
317a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavovbool A2D_IsSinkCodecValidSbc(const uint8_t *p_codec_info)
318a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov{
319a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    tA2D_SBC_CIE cfg_cie;
320a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov
321a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    /* Use a liberal check when parsing the codec info */
322a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    return (A2D_ParsSbcInfo(&cfg_cie, p_codec_info, false) == A2D_SUCCESS) ||
323a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov      (A2D_ParsSbcInfo(&cfg_cie, p_codec_info, true) == A2D_SUCCESS);
324a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov}
325a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov
326a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavovbool A2D_IsPeerSourceCodecValidSbc(const uint8_t *p_codec_info)
327a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov{
328a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    tA2D_SBC_CIE cfg_cie;
329a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov
330a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    /* Use a liberal check when parsing the codec info */
331a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    return (A2D_ParsSbcInfo(&cfg_cie, p_codec_info, false) == A2D_SUCCESS) ||
332a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov      (A2D_ParsSbcInfo(&cfg_cie, p_codec_info, true) == A2D_SUCCESS);
333a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov}
334a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov
335a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavovbool A2D_IsPeerSinkCodecValidSbc(const uint8_t *p_codec_info)
336b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov{
337b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    tA2D_SBC_CIE cfg_cie;
338b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
339b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    /* Use a liberal check when parsing the codec info */
340b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    return (A2D_ParsSbcInfo(&cfg_cie, p_codec_info, false) == A2D_SUCCESS) ||
341b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov      (A2D_ParsSbcInfo(&cfg_cie, p_codec_info, true) == A2D_SUCCESS);
342b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov}
343b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
34479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavovbool A2D_IsSourceCodecSupportedSbc(const uint8_t *p_codec_info)
34579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
34679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    return (A2D_CodecInfoMatchesCapabilitySbc(&a2d_sbc_caps, p_codec_info,
34779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov                                              false) == A2D_SUCCESS);
34879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}
34979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
35079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavovbool A2D_IsSinkCodecSupportedSbc(const uint8_t *p_codec_info)
35179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
35279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    return (A2D_CodecInfoMatchesCapabilitySbc(&a2d_sbc_sink_caps, p_codec_info,
35379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov                                              false) == A2D_SUCCESS);
35479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}
35579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
35679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavovbool A2D_IsPeerSourceCodecSupportedSbc(const uint8_t *p_codec_info)
35779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
35879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    return (A2D_CodecInfoMatchesCapabilitySbc(&a2d_sbc_sink_caps, p_codec_info,
35979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov                                              true) == A2D_SUCCESS);
36079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}
36179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
36279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavovvoid A2D_InitDefaultCodecSbc(uint8_t *p_codec_info)
36379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
364d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (A2D_BldSbcInfo(AVDT_MEDIA_TYPE_AUDIO, &a2d_sbc_default_config,
36579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov                       p_codec_info) != A2D_SUCCESS) {
36679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: A2D_BldSbcInfo failed", __func__);
36779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    }
36879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}
36979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
37079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavovbool A2D_SetCodecSbc(const tA2D_AV_MEDIA_FEEDINGS *p_feeding,
37179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov                     uint8_t *p_codec_info)
37279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
373c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_SBC_CIE sbc_config = a2d_sbc_default_config;
374c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
375c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    LOG_DEBUG(LOG_TAG, "%s", __func__);
376c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
377c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    /* Check the number of channels */
378c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if ((p_feeding->num_channel != 1) && (p_feeding->num_channel != 2)) {
379c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: Unsupported PCM channel number %d",
380c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                  __func__, p_feeding->num_channel);
381c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return false;
382c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    }
383c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
384c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    /* Check the bits per sample */
385c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if ((p_feeding->bit_per_sample != 8) &&
386c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        (p_feeding->bit_per_sample != 16)) {
387c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: Unsupported PCM sample size %d",
388c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                  __func__, p_feeding->bit_per_sample);
389c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return false;
390c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    }
39179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
392c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    /* Check the sampling frequency */
393c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    switch (p_feeding->sampling_freq) {
394c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    case 8000:
395c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    case 12000:
396c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    case 16000:
397c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    case 24000:
398c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    case 32000:
399c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    case 48000:
400c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_48;
401c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        break;
402c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    case 11025:
403c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    case 22050:
404c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    case 44100:
405c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_44;
406c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        break;
40779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    default:
408c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: Unsupported PCM sampling frequency %d",
409c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                  __func__, p_feeding->sampling_freq);
410c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return false;
411c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    }
412c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
413c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    /* Build the codec config */
414c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if (A2D_BldSbcInfo(AVDT_MEDIA_TYPE_AUDIO, &sbc_config, p_codec_info)
415c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        != A2D_SUCCESS) {
416c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: A2D_BldSbcInfo failed", __func__);
41779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        return false;
41879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    }
41979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
42079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    return true;
42179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}
42279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
423b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Checks whether A2DP SBC codec configuration matches with a device's codec
424b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// capabilities. |p_cap| is the SBC codec configuration. |p_codec_info| is
425b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// the device's codec capabilities. |is_peer_src_codec_info| is true if
426b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// |p_codec_info| contains the codec capabilities for a peer device that
427b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// is acting as an A2DP source.
428b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// Returns A2D_SUCCESS if the codec configuration matches with capabilities,
429b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov// otherwise the corresponding A2DP error status code.
43079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavovstatic tA2D_STATUS A2D_CodecInfoMatchesCapabilitySbc(
43179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        const tA2D_SBC_CIE *p_cap,
43279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        const uint8_t *p_codec_info,
43379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        bool is_peer_src_codec_info)
43479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
43579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    tA2D_STATUS status;
43679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    tA2D_SBC_CIE cfg_cie;
43779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
43879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* parse configuration */
43979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    status = A2D_ParsSbcInfo(&cfg_cie, p_codec_info, is_peer_src_codec_info);
44079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (status != A2D_SUCCESS) {
44179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: parsing failed %d", __func__, status);
44279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        return status;
44379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    }
44479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
44579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* verify that each parameter is in range */
44679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
44779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    LOG_DEBUG(LOG_TAG, "FREQ peer: 0x%x, capability 0x%x",
44879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov              cfg_cie.samp_freq, p_cap->samp_freq);
44979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    LOG_DEBUG(LOG_TAG, "CH_MODE peer: 0x%x, capability 0x%x",
45079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov              cfg_cie.ch_mode, p_cap->ch_mode);
45179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    LOG_DEBUG(LOG_TAG, "BLOCK_LEN peer: 0x%x, capability 0x%x",
45279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov              cfg_cie.block_len, p_cap->block_len);
45379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    LOG_DEBUG(LOG_TAG, "SUB_BAND peer: 0x%x, capability 0x%x",
45479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov              cfg_cie.num_subbands, p_cap->num_subbands);
455d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    LOG_DEBUG(LOG_TAG, "ALLOC_METHOD peer: 0x%x, capability 0x%x",
456d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov              cfg_cie.alloc_method, p_cap->alloc_method);
45779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    LOG_DEBUG(LOG_TAG, "MIN_BitPool peer: 0x%x, capability 0x%x",
45879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov              cfg_cie.min_bitpool, p_cap->min_bitpool);
459d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    LOG_DEBUG(LOG_TAG, "MAX_BitPool peer: 0x%x, capability 0x%x",
460d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov              cfg_cie.max_bitpool, p_cap->max_bitpool);
46179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
46279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* sampling frequency */
46379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0)
46479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        return A2D_NS_SAMP_FREQ;
46579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
46679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* channel mode */
46779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if ((cfg_cie.ch_mode & p_cap->ch_mode) == 0)
46879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        return A2D_NS_CH_MODE;
46979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
47079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* block length */
47179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if ((cfg_cie.block_len & p_cap->block_len) == 0)
47279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        return A2D_BAD_BLOCK_LEN;
47379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
47479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* subbands */
47579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if ((cfg_cie.num_subbands & p_cap->num_subbands) == 0)
47679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        return A2D_NS_SUBBANDS;
47779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
47879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* allocation method */
479d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if ((cfg_cie.alloc_method & p_cap->alloc_method) == 0)
480d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return A2D_NS_ALLOC_METHOD;
48179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
48279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* min bitpool */
48379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (cfg_cie.min_bitpool < p_cap->min_bitpool)
48479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        return A2D_NS_MIN_BITPOOL;
48579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
486d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    /* max bitpool */
487d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (cfg_cie.max_bitpool > p_cap->max_bitpool)
488d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return A2D_NS_MAX_BITPOOL;
489d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
49079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    return A2D_SUCCESS;
49179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}
49279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
493c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin RadoslavovtA2D_STATUS A2D_BuildSrc2SinkConfigSbc(const uint8_t *p_src_cap,
494c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                                       uint8_t *p_pref_cfg)
49579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
49679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    tA2D_SBC_CIE    src_cap;
49779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    tA2D_SBC_CIE    pref_cap;
49879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
49979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* initialize it to default SBC configuration */
500d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    A2D_BldSbcInfo(AVDT_MEDIA_TYPE_AUDIO, &a2d_sbc_default_config, p_pref_cfg);
50179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
50279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* now try to build a preferred one */
50379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    /* parse configuration */
50479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    tA2D_STATUS status = A2D_ParsSbcInfo(&src_cap, p_src_cap, true);
50579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (status != A2D_SUCCESS) {
50679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: can't parse src cap ret = %d",
50779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov                  __func__, status);
50879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        return A2D_FAIL;
50979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    }
51079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
51179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_48)
51279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.samp_freq = A2D_SBC_IE_SAMP_FREQ_48;
51379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    else if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_44)
51479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.samp_freq = A2D_SBC_IE_SAMP_FREQ_44;
51579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
51679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_JOINT)
51779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.ch_mode = A2D_SBC_IE_CH_MD_JOINT;
51879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_STEREO)
51979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.ch_mode = A2D_SBC_IE_CH_MD_STEREO;
52079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_DUAL)
52179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.ch_mode = A2D_SBC_IE_CH_MD_DUAL;
52279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_MONO)
52379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.ch_mode = A2D_SBC_IE_CH_MD_MONO;
52479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
52579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (src_cap.block_len & A2D_SBC_IE_BLOCKS_16)
52679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.block_len = A2D_SBC_IE_BLOCKS_16;
52779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_12)
52879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.block_len = A2D_SBC_IE_BLOCKS_12;
52979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_8)
53079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.block_len = A2D_SBC_IE_BLOCKS_8;
53179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    else if (src_cap.block_len & A2D_SBC_IE_BLOCKS_4)
53279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.block_len = A2D_SBC_IE_BLOCKS_4;
53379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
53479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (src_cap.num_subbands & A2D_SBC_IE_SUBBAND_8)
53579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.num_subbands = A2D_SBC_IE_SUBBAND_8;
53679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    else if(src_cap.num_subbands & A2D_SBC_IE_SUBBAND_4)
53779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        pref_cap.num_subbands = A2D_SBC_IE_SUBBAND_4;
53879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
539d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (src_cap.alloc_method & A2D_SBC_IE_ALLOC_MD_L)
540d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        pref_cap.alloc_method = A2D_SBC_IE_ALLOC_MD_L;
541d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    else if(src_cap.alloc_method & A2D_SBC_IE_ALLOC_MD_S)
542d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        pref_cap.alloc_method = A2D_SBC_IE_ALLOC_MD_S;
54379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
54479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    pref_cap.min_bitpool = src_cap.min_bitpool;
545d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    pref_cap.max_bitpool = src_cap.max_bitpool;
54679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
547d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    A2D_BldSbcInfo(AVDT_MEDIA_TYPE_AUDIO, &pref_cap, p_pref_cfg);
54879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
54979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    return A2D_SUCCESS;
55079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}
55179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
552c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin RadoslavovtA2D_STATUS A2D_BuildSinkConfigSbc(const uint8_t *p_src_config,
553c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                                   const uint8_t *p_sink_cap,
554c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                                   uint8_t *p_result_sink_config)
555c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov{
556c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_SBC_CIE src_config_cie;
557c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_SBC_CIE sink_cap_cie;
558c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
559c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    /* Decode the source codec config */
560c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&src_config_cie,
561c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                                             p_src_config, false);
562c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
563c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode source codec information: %d",
564c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                  __func__, a2d_status);
565c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return A2D_FAIL;
566c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    }
567c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
568c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    /* Decode the sink codec capabilities */
569c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    a2d_status = A2D_ParsSbcInfo(&sink_cap_cie, p_sink_cap, true);
570c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
571c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode sink capability information: %d",
572c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                  __func__, a2d_status);
573c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return A2D_FAIL;
574c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    }
575c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
576c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    /* Update the bitpool boundaries from the sink codec capabilities */
577c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    src_config_cie.min_bitpool = sink_cap_cie.min_bitpool;
578c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    src_config_cie.max_bitpool = sink_cap_cie.max_bitpool;
579c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
580c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    /* Build the result sink config from the source config */
581c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    A2D_BldSbcInfo(AVDT_MEDIA_TYPE_AUDIO, &src_config_cie,
582c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                   p_result_sink_config);
583c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
584c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    return A2D_SUCCESS;
585c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov}
586c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
587b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavovbool A2D_CodecTypeEqualsSbc(const uint8_t *p_codec_info_a,
588b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov                            const uint8_t *p_codec_info_b)
58979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
590b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    tA2D_SBC_CIE sbc_cie_a;
591b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    tA2D_SBC_CIE sbc_cie_b;
592b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
593b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    // Check whether the codec info contains valid data
594b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie_a, p_codec_info_a, false);
595b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
596b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
597b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov                  __func__, a2d_status);
598b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov        return false;
599b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    }
600b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    a2d_status = A2D_ParsSbcInfo(&sbc_cie_b, p_codec_info_b, false);
601b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
602b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
603b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov                  __func__, a2d_status);
604b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov        return false;
605b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    }
606b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
607b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    tA2D_CODEC_TYPE codec_type_a = A2D_GetCodecType(p_codec_info_a);
608b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    tA2D_CODEC_TYPE codec_type_b = A2D_GetCodecType(p_codec_info_b);
609b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
610b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    return (codec_type_a == codec_type_b) && (codec_type_a == A2D_MEDIA_CT_SBC);
61179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov}
61279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
613c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavovbool A2D_CodecEqualsSbc(const uint8_t *p_codec_info_a,
614c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                        const uint8_t *p_codec_info_b)
615c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov{
616c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_SBC_CIE sbc_cie_a;
617c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_SBC_CIE sbc_cie_b;
618c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
619c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    // Check whether the codec info contains valid data
620c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie_a, p_codec_info_a, false);
621c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
622c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
623c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                  __func__, a2d_status);
624c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return false;
625c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    }
626c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    a2d_status = A2D_ParsSbcInfo(&sbc_cie_b, p_codec_info_b, false);
627c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
628c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
629c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                  __func__, a2d_status);
630c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return false;
631c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    }
632c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
633c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_CODEC_TYPE codec_type_a = A2D_GetCodecType(p_codec_info_a);
634c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_CODEC_TYPE codec_type_b = A2D_GetCodecType(p_codec_info_b);
635c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
636c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if ((codec_type_a != codec_type_b) || (codec_type_a != A2D_MEDIA_CT_SBC))
637c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return false;
638c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
639c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    return (sbc_cie_a.samp_freq == sbc_cie_b.samp_freq) &&
640c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_a.ch_mode == sbc_cie_b.ch_mode) &&
641c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_a.block_len == sbc_cie_b.block_len) &&
642c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_a.num_subbands == sbc_cie_b.num_subbands) &&
643c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_a.alloc_method == sbc_cie_b.alloc_method) &&
644c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_a.min_bitpool == sbc_cie_b.min_bitpool) &&
645c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_a.max_bitpool == sbc_cie_b.max_bitpool);
646c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov}
647c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
648c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavovbool A2D_CodecRequiresReconfigSbc(const uint8_t *p_codec_info_a,
649c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                                  const uint8_t *p_codec_info_b)
650c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov{
651c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_SBC_CIE sbc_cie_a;
652c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_SBC_CIE sbc_cie_b;
653c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
654c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    // Check whether the codec info contains valid data
655c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie_a, p_codec_info_a, false);
656c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
657c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
658c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                  __func__, a2d_status);
659c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return true;
660c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    }
661c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    a2d_status = A2D_ParsSbcInfo(&sbc_cie_b, p_codec_info_b, false);
662c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
663c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
664c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                  __func__, a2d_status);
665c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return true;
666c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    }
667c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
668c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_CODEC_TYPE codec_type_a = A2D_GetCodecType(p_codec_info_a);
669c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_CODEC_TYPE codec_type_b = A2D_GetCodecType(p_codec_info_b);
670c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
671c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if ((codec_type_a != codec_type_b) || (codec_type_a != A2D_MEDIA_CT_SBC))
672c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return true;
673c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
674c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    /* NOTE: The min_bitpool and max_bitpool fields are ignored */
675c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    return (sbc_cie_a.samp_freq != sbc_cie_b.samp_freq) ||
676c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_a.ch_mode != sbc_cie_b.ch_mode) ||
677c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_a.block_len != sbc_cie_b.block_len) ||
678c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_a.num_subbands != sbc_cie_b.num_subbands) ||
679c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_a.alloc_method != sbc_cie_b.alloc_method);
680c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov}
681c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
682c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavovbool A2D_CodecConfigMatchesCapabilitiesSbc(const uint8_t *p_codec_config,
683c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                                           const uint8_t *p_codec_caps)
684c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov{
685c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_SBC_CIE sbc_cie_config;
686c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_SBC_CIE sbc_cie_caps;
687c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
688c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    // Check whether the codec info contains valid data
689c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie_config, p_codec_config,
690c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                                             false);
691c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
692c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec config: %d",
693c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                  __func__, a2d_status);
694c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return false;
695c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    }
696c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    a2d_status = A2D_ParsSbcInfo(&sbc_cie_caps, p_codec_caps, true);
697c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
698c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec capabilities: %d",
699c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov                  __func__, a2d_status);
700c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov        return false;
701c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    }
702c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
703c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov    /*
704c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov     * Must match all SBC codec fields except min/max bitpool boundaries which
705c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov     * can be adjusted.
706c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov     */
707a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    bool result =
708a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov      (sbc_cie_config.samp_freq & sbc_cie_caps.samp_freq) &&
709c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_config.ch_mode & sbc_cie_caps.ch_mode) &&
710c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_config.block_len & sbc_cie_caps.block_len) &&
711c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_config.num_subbands & sbc_cie_caps.num_subbands) &&
712c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov      (sbc_cie_config.alloc_method & sbc_cie_caps.alloc_method);
713a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov
714a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    LOG_DEBUG(LOG_TAG, "%s: result=%s", __func__, result ? "true" : "false");
715a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    LOG_DEBUG(LOG_TAG, "%s: config samp_freq=0x%x ch_mode=0x%x block_len=0x%x "
716a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov              "num_subbands=0x%x alloc_method=0x%x",
717a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov              __func__,
718a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov              sbc_cie_config.samp_freq, sbc_cie_config.ch_mode,
719a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov              sbc_cie_config.block_len, sbc_cie_config.num_subbands,
720a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov              sbc_cie_config.alloc_method);
721a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    LOG_DEBUG(LOG_TAG, "%s: caps   samp_freq=0x%x ch_mode=0x%x block_len=0x%x "
722a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov              "num_subbands=0x%x alloc_method=0x%x",
723a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov              __func__,
724a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov              sbc_cie_caps.samp_freq, sbc_cie_caps.ch_mode,
725a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov              sbc_cie_caps.block_len, sbc_cie_caps.num_subbands,
726a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov              sbc_cie_caps.alloc_method);
727a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov
728a0db321d98c98e10f45720075fb9c83e3ef596bfPavlin Radoslavov    return result;
729c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov}
730c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
731d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavovint A2D_GetTrackFrequencySbc(const uint8_t *p_codec_info)
73279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov{
733d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
734d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
735d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
736d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
737d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
738d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  __func__, a2d_status);
739d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
740d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
741d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
742d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.samp_freq) {
743d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_16:
744d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 16000;
745d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_32:
746d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 32000;
747d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_44:
748d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 44100;
749d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_48:
750d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 48000;
751d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
752d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
753d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
754d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
755d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    return -1;
756d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov}
757d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
758d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavovint A2D_GetTrackChannelCountSbc(const uint8_t *p_codec_info)
759d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov{
760d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
761d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
762d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
763d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
764d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
765d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  __func__, a2d_status);
766d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
767d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
768d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
769d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.ch_mode) {
770d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_MONO:
771d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 1;
772d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_DUAL:
773d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_STEREO:
774d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_JOINT:
775d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 2;
776d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
777d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
778d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
779d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
780d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    return -1;
781d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov}
782d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
783d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavovint A2D_GetNumberOfSubbandsSbc(const uint8_t *p_codec_info)
784d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov{
785d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
786d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
787d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
788d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
789d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
790d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  __func__, a2d_status);
791d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
792d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
793d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
794d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.num_subbands) {
795d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SUBBAND_4:
796d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 4;
797d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SUBBAND_8:
798d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 8;
799d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
800d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
801d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
802d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
803d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    return -1;
804d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov}
805d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
806d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavovint A2D_GetNumberOfBlocksSbc(const uint8_t *p_codec_info)
807d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov{
808d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
809d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
810d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
811d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
812d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
813d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  __func__, a2d_status);
814d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
815d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
816d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
817d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.block_len) {
818d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_BLOCKS_4:
819d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 4;
820d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_BLOCKS_8:
821d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 8;
822d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_BLOCKS_12:
823d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 12;
824d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_BLOCKS_16:
825d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 16;
826d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
827d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
828d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
829d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
830d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    return -1;
831d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov}
832d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
833d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavovint A2D_GetAllocationMethodCodeSbc(const uint8_t *p_codec_info)
834d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov{
835d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
836d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
837d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
838d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
839d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
840d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  __func__, a2d_status);
841d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
8427aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov    }
843d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
844d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.alloc_method) {
845d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_ALLOC_MD_S:
846d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return SBC_SNR;
847d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_ALLOC_MD_L:
848d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return SBC_LOUDNESS;
849d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
850d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
851d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
852d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
853d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    return -1;
854d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov}
855d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
856d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavovint A2D_GetChannelModeCodeSbc(const uint8_t *p_codec_info)
857d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov{
858d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
859d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
860d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
861d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
862d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
863d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  __func__, a2d_status);
864d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
865d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
866d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
867d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.ch_mode) {
868d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_MONO:
869d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return SBC_MONO;
870d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_DUAL:
871d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return SBC_DUAL;
872d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_STEREO:
873d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return SBC_STEREO;
874d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_JOINT:
875d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return SBC_JOINT_STEREO;
876d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
877d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
878d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
879d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
880d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    return -1;
881d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov}
882d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
883d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavovint A2D_GetSamplingFrequencyCodeSbc(const uint8_t *p_codec_info)
884d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov{
885d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
886d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
887d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
888d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
889d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
890d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  __func__, a2d_status);
891d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
892d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
893d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
894d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.samp_freq) {
895d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_16:
896d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return SBC_sf16000;
897d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_32:
898d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return SBC_sf32000;
899d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_44:
900d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return SBC_sf44100;
901d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_48:
902d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return SBC_sf48000;
903d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
904d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
905d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
906d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
907d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    return -1;
908d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov}
909d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
910b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavovint A2D_GetMinBitpoolSbc(const uint8_t *p_codec_info)
911b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov{
912b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
913b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
914b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
915b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
916b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
917b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov                  __func__, a2d_status);
918b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov        return -1;
919b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    }
920b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
921b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    return sbc_cie.min_bitpool;
922b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov}
923b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
924b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavovint A2D_GetMaxBitpoolSbc(const uint8_t *p_codec_info)
925b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov{
926b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
927b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
928b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
929b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
930b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
931b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov                  __func__, a2d_status);
932b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov        return -1;
933b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    }
934b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
935b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov    return sbc_cie.max_bitpool;
936b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov}
937b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
938d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavovint A2D_GetSinkTrackChannelTypeSbc(const uint8_t *p_codec_info)
939d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov{
940d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
941d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
942d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
943d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
944d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
945d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  __func__, a2d_status);
946d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
947d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
948d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
949d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.ch_mode) {
950d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_MONO:
951d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 1;
952d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_DUAL:
953d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_STEREO:
954d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_JOINT:
955d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return 3;
956d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
957d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
958d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
959d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
960d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    return -1;
961d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov}
962d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
963d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavovint A2D_GetSinkFramesCountToProcessSbc(uint64_t time_interval_ms,
964d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                                       const uint8_t *p_codec_info)
965d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov{
966d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
967d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    uint32_t freq_multiple;
968d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    uint32_t num_blocks;
969d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    uint32_t num_subbands;
970d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    int frames_to_process;
971d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
972d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    tA2D_STATUS a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
973d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
974d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d",
975d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  __func__, a2d_status);
976d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
977d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
978d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
979d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    // Check the sample frequency
980d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.samp_freq) {
981d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_16:
982d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: samp_freq:%d (16000)", __func__,
983d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.samp_freq);
984d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        freq_multiple = 16 * time_interval_ms;
985d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
986d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_32:
987d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: samp_freq:%d (32000)", __func__,
988d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.samp_freq);
989d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        freq_multiple = 32 * time_interval_ms;
990d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
991d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_44:
992d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: samp_freq:%d (44100)", __func__,
993d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.samp_freq);
994d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        freq_multiple = (441 * time_interval_ms) / 10;
995d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
996d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SAMP_FREQ_48:
997d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: samp_freq:%d (48000)", __func__,
998d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.samp_freq);
999d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        freq_multiple = 48 * time_interval_ms;
1000d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1001d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
1002d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: unknown frequency: %d", __func__,
1003d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.samp_freq);
1004d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
1005d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
1006d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
1007d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    // Check the channel mode
1008d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.ch_mode) {
1009d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_MONO:
1010d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: ch_mode:%d (Mono)", __func__,
1011d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.ch_mode);
1012d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1013d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_DUAL:
1014d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: ch_mode:%d (DUAL)", __func__,
1015d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.ch_mode);
1016d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1017d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_STEREO:
1018d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: ch_mode:%d (STEREO)", __func__,
1019d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.ch_mode);
1020d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1021d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_CH_MD_JOINT:
1022d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: ch_mode:%d (JOINT)", __func__,
1023d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.ch_mode);
1024d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1025d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
1026d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: unknown channel mode: %d", __func__,
1027d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.ch_mode);
1028d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
1029d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
1030d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
1031d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    // Check the block length
1032d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.block_len) {
1033d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_BLOCKS_4:
1034d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: block_len:%d (4)", __func__,
1035d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.block_len);
1036d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        num_blocks = 4;
1037d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1038d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_BLOCKS_8:
1039d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: block_len:%d (8)", __func__,
1040d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.block_len);
1041d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        num_blocks = 8;
1042d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1043d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_BLOCKS_12:
1044d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: block_len:%d (12)", __func__,
1045d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.block_len);
1046d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        num_blocks = 12;
1047d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1048d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_BLOCKS_16:
1049d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: block_len:%d (16)", __func__,
1050d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.block_len);
1051d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        num_blocks = 16;
1052d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1053d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
1054d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: unknown block length: %d", __func__,
1055d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.block_len);
1056d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
1057d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
1058d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
1059d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    // Check the number of sub-bands
1060d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.num_subbands) {
1061d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SUBBAND_4:
1062d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: num_subbands:%d (4)", __func__,
1063d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.num_subbands);
1064d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        num_subbands = 4;
1065d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1066d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_SUBBAND_8:
1067d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: num_subbands:%d (8)", __func__,
1068d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.num_subbands);
1069d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        num_subbands = 8;
1070d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1071d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
1072d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: unknown number of subbands: %d", __func__,
1073d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.num_subbands);
1074d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
1075d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
1076d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
1077d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    // Check the allocation method
1078d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    switch (sbc_cie.alloc_method) {
1079d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_ALLOC_MD_S:
1080d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: alloc_method:%d (SNR)", __func__,
1081d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.alloc_method);
1082d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1083d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    case A2D_SBC_IE_ALLOC_MD_L:
1084d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "%s: alloc_method:%d (Loudness)", __func__,
1085d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.alloc_method);
1086d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        break;
1087d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    default:
1088d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: unknown allocation method: %d", __func__,
1089d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov                  sbc_cie.alloc_method);
1090d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        return -1;
1091d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    }
1092d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
1093d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    LOG_DEBUG(LOG_TAG, "%s: Bit pool Min:%d Max:%d", __func__,
1094d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov              sbc_cie.min_bitpool, sbc_cie.max_bitpool);
1095d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
1096d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    frames_to_process = ((freq_multiple) / (num_blocks * num_subbands)) + 1;
1097d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov
1098d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    return frames_to_process;
10997aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov}
11007aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov
1101b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavovbool A2D_GetPacketTimestampSbc(const uint8_t *p_codec_info,
1102b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov                               const uint8_t *p_data, uint32_t *p_timestamp)
1103b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov{
1104b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    *p_timestamp = *(const uint32_t *)p_data;
1105b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    return true;
1106b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov}
1107b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov
1108b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavovbool A2D_BuildCodecHeaderSbc(UNUSED_ATTR const uint8_t *p_codec_info,
1109b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov                             BT_HDR *p_buf, uint16_t frames_per_packet)
1110b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov{
1111b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    uint8_t *p;
1112b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov
1113b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    p_buf->offset -= A2D_SBC_MPL_HDR_LEN;
1114b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    p = (uint8_t *) (p_buf + 1) + p_buf->offset;
1115b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    p_buf->len += A2D_SBC_MPL_HDR_LEN;
1116b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    A2D_BldSbcMplHdr(p, false, false, false, (uint8_t) frames_per_packet);
1117b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov
1118b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov    return true;
1119b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov}
1120b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov
1121d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavovvoid A2D_DumpCodecInfoSbc(const uint8_t *p_codec_info)
11227aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov{
11237aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov    tA2D_STATUS a2d_status;
11247aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov    tA2D_SBC_CIE sbc_cie;
11257aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov
112679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    LOG_DEBUG(LOG_TAG, "%s", __func__);
11277aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov
1128d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    a2d_status = A2D_ParsSbcInfo(&sbc_cie, p_codec_info, false);
11297aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov    if (a2d_status != A2D_SUCCESS) {
113079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_ERROR(LOG_TAG, "%s: A2D_ParsSbcInfo fail:%d",
113179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov                  __func__, a2d_status);
11327aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov        return;
11337aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov    }
11347aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov
113579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_16) {
113679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tsamp_freq:%d (16000)", sbc_cie.samp_freq);
113779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_32) {
113879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tsamp_freq:%d (32000)", sbc_cie.samp_freq);
113979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_44) {
114079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tsamp_freq:%d (44.100)", sbc_cie.samp_freq);
114179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else if (sbc_cie.samp_freq == A2D_SBC_IE_SAMP_FREQ_48) {
114279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tsamp_freq:%d (48000)", sbc_cie.samp_freq);
114379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else {
114479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tBAD samp_freq:%d", sbc_cie.samp_freq);
114579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    }
11467aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov
114779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_MONO) {
114879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tch_mode:%d (Mono)", sbc_cie.ch_mode);
114979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_DUAL) {
115079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tch_mode:%d (Dual)", sbc_cie.ch_mode);
115179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_STEREO) {
115279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tch_mode:%d (Stereo)", sbc_cie.ch_mode);
115379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else if (sbc_cie.ch_mode == A2D_SBC_IE_CH_MD_JOINT) {
115479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tch_mode:%d (Joint)", sbc_cie.ch_mode);
115579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else {
115679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tBAD ch_mode:%d", sbc_cie.ch_mode);
115779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    }
11587aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov
115979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_4) {
116079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tblock_len:%d (4)", sbc_cie.block_len);
116179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_8) {
116279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tblock_len:%d (8)", sbc_cie.block_len);
116379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_12) {
116479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tblock_len:%d (12)", sbc_cie.block_len);
116579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else if (sbc_cie.block_len == A2D_SBC_IE_BLOCKS_16) {
116679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tblock_len:%d (16)", sbc_cie.block_len);
116779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else {
116879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tBAD block_len:%d", sbc_cie.block_len);
116979506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    }
117079506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
117179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    if (sbc_cie.num_subbands == A2D_SBC_IE_SUBBAND_4) {
117279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tnum_subbands:%d (4)", sbc_cie.num_subbands);
117379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else if (sbc_cie.num_subbands == A2D_SBC_IE_SUBBAND_8) {
117479506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tnum_subbands:%d (8)", sbc_cie.num_subbands);
117579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else {
117679506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tBAD num_subbands:%d", sbc_cie.num_subbands);
117779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    }
117879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
1179d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    if (sbc_cie.alloc_method == A2D_SBC_IE_ALLOC_MD_S) {
1180d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\talloc_method:%d (SNR)", sbc_cie.alloc_method);
1181d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov    } else if (sbc_cie.alloc_method == A2D_SBC_IE_ALLOC_MD_L) {
1182d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\talloc_method:%d (Loundess)", sbc_cie.alloc_method);
118379506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    } else {
1184d7ff47cc64838ecd9d5a8366b75815aab97b6f7dPavlin Radoslavov        LOG_DEBUG(LOG_TAG, "\tBAD alloc_method:%d", sbc_cie.alloc_method);
118579506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    }
11867aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov
118779506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov    LOG_DEBUG(LOG_TAG, "\tBit pool Min:%d Max:%d", sbc_cie.min_bitpool,
118879506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov              sbc_cie.max_bitpool);
11897aaf7c6c42a06e174ce305000ab7a223dc99cbdfPavlin Radoslavov}
1190