Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c54f8c2c authored by Pavlin Radoslavov's avatar Pavlin Radoslavov
Browse files

Extended the A2DP codec abstraction API

 * Added new A2DP codec-independent API and updated/renamed existing API.
   - A2D_InitCodecConfig()
   - A2D_InitDefaultCodec()
   - A2D_SetCodec()
   - A2D_IsCodecSupported() -> A2D_IsSourceCodecSupported()
   - A2D_IsSinkCodecSupported()
   - A2D_BuildSrc2SinkConfig() - previously bta_av_build_src_cfg()
   - A2D_IsSinkCodecSupported() - previously
       bta_av_co_audio_sink_supports_config()
   - A2D_IsSourceCodecSupported() - previously
       bta_av_co_audio_media_supports_config()
   - A2D_IsPeerSourceCodecSupported()
   - A2D_GetDefaultConfigSbc() - to be deleted
   - A2D_CodecSepIndexStr()

 * Added the corresponding SBC-specific implementation and a placeholder
   for vendor implementation.

 * Added the corresponding unit tests

Also:
 * Added type tA2D_CODEC_SEP_INDEX and list each known codec (Source or Sink):
   A2D_CODEC_SEP_INDEX_*
 * Renamed BTIF_SV_AV_AA_SBC_INDEX -> A2D_CODEC_SEP_INDEX_SBC
 * Renamed BTIF_SV_AV_AA_SBC_SINK_INDEX -> A2D_CODEC_SEP_INDEX_SBC_SINK
 * Renamed BTA_AV_MAX_SEPS -> A2D_CODEC_SEP_INDEX_MAX
 * Renamed tA2D_CODEC -> tA2D_CODEC_TYPE
 * Renamed tBTIF_AV_MEDIA_FEEDINGS -> tA2D_AV_MEDIA_FEEDINGS
 * Renamed tBTIF_AV_CODEC_ID -> tA2D_AV_CODEC_ID (to be deleted)
 * Renamed BTIF_AV_CODEC_PCM -> tA2D_AV_CODEC_PCM (to be deleted)
 * Renamed BTIF_AV_CODEC_NONE -> tA2D_AV_CODEC_NONE (to be deleted)
 * tBTIF_AV_MEDIA_FEED_CFG_PCM -> tA2D_AV_MEDIA_FEED_CFG_PCM (to be
   deleted)
 * tBTIF_AV_MEDIA_FEED_CFG -> tA2D_AV_MEDIA_FEED_CFG (to be deleted)
 * Moved SBC codec-related configuration and capabilities from
   btif/co/bta_av_co.cc to stack/a2dp/a2d_sbc.c :
   - bta_av_co_sbc_caps -> a2d_sbc_caps
   - bta_av_co_sbc_sink_caps -> a2d_sbc_sink_caps
   - btif_av_sbc_default_config -> a2d_sbc_default_config
 * Replaced usage of BTIF_AV_SBC_DEFAULT_SAMP_FREQ with
   A2D_SBC_IE_SAMP_FREQ_44
 * Merged bta_av_sbc_cfg_matches_cap() and bta_av_sbc_cfg_in_cap()
   into A2D_CodecInfoMatchesCapabilitySbc()
 * Misc other fixes and cleanup: use tA2D_STATUS as appropriate, remove
   FUNC_TRACE(), etc.

Bug: 30958229
Change-Id: I35e224754041cdce479c87e57d8e2c8b3adc8edd
parent dd7760ec
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -250,7 +250,7 @@ tAVDT_CTRL_CBACK * const bta_av_dt_cback[] =
***********************************************/
static uint8_t bta_av_get_scb_handle(tBTA_AV_SCB *p_scb, uint8_t local_sep)
{
    for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
    for (int i = 0; i < A2D_CODEC_SEP_INDEX_MAX; i++) {
        if ((p_scb->seps[i].tsep == local_sep) &&
            (p_scb->seps[i].codec_type == p_scb->codec_type))
            return (p_scb->seps[i].av_handle);
@@ -270,7 +270,7 @@ static uint8_t bta_av_get_scb_handle(tBTA_AV_SCB *p_scb, uint8_t local_sep)
***********************************************/
static uint8_t bta_av_get_scb_sep_type(tBTA_AV_SCB *p_scb, uint8_t tavdt_handle)
{
    for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
    for (int i = 0; i < A2D_CODEC_SEP_INDEX_MAX; i++) {
        if (p_scb->seps[i].av_handle == tavdt_handle)
            return (p_scb->seps[i].tsep);
    }
@@ -744,7 +744,7 @@ static void bta_av_a2d_sdp_cback(bool found, tA2D_Service *p_service)
static void bta_av_adjust_seps_idx(tBTA_AV_SCB *p_scb, uint8_t avdt_handle)
{
    APPL_TRACE_DEBUG("%s: codec_type: %d", __func__, p_scb->codec_type);
    for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
    for (int i = 0; i < A2D_CODEC_SEP_INDEX_MAX; i++) {
        APPL_TRACE_DEBUG("%s: av_handle: %d codec_type: %d", __func__,
            p_scb->seps[i].av_handle, p_scb->seps[i].codec_type);
        if((p_scb->seps[i].av_handle && p_scb->codec_type == p_scb->seps[i].codec_type)
@@ -1091,7 +1091,7 @@ void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
    if (p_scb->deregistring)
    {
        /* remove stream */
        for (int i = 0; i < BTA_AV_MAX_SEPS; i++) {
        for (int i = 0; i < A2D_CODEC_SEP_INDEX_MAX; i++) {
            if (p_scb->seps[i].av_handle)
                AVDT_RemoveStream(p_scb->seps[i].av_handle);
            p_scb->seps[i].av_handle = 0;
@@ -1897,7 +1897,7 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
                              A2D_GetCodecType(p_scb->p_cap->codec_info),
                              cfg.codec_info, &p_scb->sep_info_idx,
                              p_info->seid, &cfg.num_protect,
                              cfg.protect_info) == 0))
                              cfg.protect_info) == A2D_SUCCESS))
    {
#if AVDT_MULTIPLEXING == TRUE
        cfg.mux_mask &= p_scb->p_cap->mux_mask;
+1 −1
Original line number Diff line number Diff line
@@ -71,7 +71,7 @@ void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, uint8_t err_code, uint8_t category,
        (tBTA_AV_CI_SETCONFIG *)osi_malloc(sizeof(tBTA_AV_CI_SETCONFIG));

    p_buf->hdr.layer_specific   = hndl;
    p_buf->hdr.event = (err_code == AVDT_SUCCESS) ?
    p_buf->hdr.event = (err_code == A2D_SUCCESS) ?
        BTA_AV_CI_SETCONFIG_OK_EVT : BTA_AV_CI_SETCONFIG_FAIL_EVT;
    p_buf->err_code = err_code;
    p_buf->category = category;
+21 −18
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include "bta_av_api.h"
#include "avdt_api.h"
#include "bta_av_co.h"
#include "stack/include/a2d_api.h"

#define BTA_AV_DEBUG TRUE
/*****************************************************************************
@@ -155,31 +156,33 @@ enum
*****************************************************************************/

/* function types for call-out functions */
typedef bool (*tBTA_AV_CO_INIT) (uint8_t *p_codec_type, uint8_t *p_codec_info,
                                 uint8_t *p_num_protect,
                                 uint8_t *p_protect_info, uint8_t index);
typedef bool (*tBTA_AV_CO_INIT) (tA2D_CODEC_SEP_INDEX codec_sep_index,
                                 tAVDT_CFG *p_cfg);
typedef void (*tBTA_AV_CO_DISC_RES) (tBTA_AV_HNDL hndl, uint8_t num_seps,
                                     uint8_t num_snk, uint8_t num_src,
                                     BD_ADDR addr, uint16_t uuid_local);
typedef uint8_t (*tBTA_AV_CO_GETCFG) (tBTA_AV_HNDL hndl, tA2D_CODEC codec_type,
typedef tA2D_STATUS (*tBTA_AV_CO_GETCFG) (tBTA_AV_HNDL hndl,
                                          tA2D_CODEC_TYPE codec_type,
                                          uint8_t *p_codec_info,
                                      uint8_t *p_sep_info_idx, uint8_t seid,
                                          uint8_t *p_sep_info_idx,
                                          uint8_t seid,
                                          uint8_t *p_num_protect,
                                          uint8_t *p_protect_info);
typedef void (*tBTA_AV_CO_SETCFG) (tBTA_AV_HNDL hndl, tA2D_CODEC codec_type,
typedef void (*tBTA_AV_CO_SETCFG) (tBTA_AV_HNDL hndl,
                                   tA2D_CODEC_TYPE codec_type,
                                   uint8_t *p_codec_info, uint8_t seid,
                                   BD_ADDR addr, uint8_t num_protect,
                                   uint8_t *p_protect_info,
                                   uint8_t t_local_sep, uint8_t avdt_handle);
typedef void (*tBTA_AV_CO_OPEN) (tBTA_AV_HNDL hndl, tA2D_CODEC codec_type,
typedef void (*tBTA_AV_CO_OPEN) (tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type,
                                 uint8_t *p_codec_info, uint16_t mtu);
typedef void (*tBTA_AV_CO_CLOSE) (tBTA_AV_HNDL hndl, tA2D_CODEC codec_type,
typedef void (*tBTA_AV_CO_CLOSE) (tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type,
                                  uint16_t mtu);
typedef void (*tBTA_AV_CO_START) (tBTA_AV_HNDL hndl, tA2D_CODEC codec_type,
typedef void (*tBTA_AV_CO_START) (tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type,
                                  uint8_t *p_codec_info, bool *p_no_rtp_hdr);
typedef void (*tBTA_AV_CO_STOP) (tBTA_AV_HNDL hndl, tA2D_CODEC codec_type);
typedef void * (*tBTA_AV_CO_DATAPATH) (tA2D_CODEC codec_type, uint32_t *p_len,
                                       uint32_t *p_timestamp);
typedef void (*tBTA_AV_CO_STOP) (tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type);
typedef void * (*tBTA_AV_CO_DATAPATH) (tA2D_CODEC_TYPE codec_type,
                                       uint32_t *p_len, uint32_t *p_timestamp);
typedef void (*tBTA_AV_CO_DELAY) (tBTA_AV_HNDL hndl, uint16_t delay);

/* the call-out functions for one stream */
@@ -395,7 +398,7 @@ typedef struct
typedef struct
{
    uint8_t             av_handle;         /* AVDTP handle */
    tA2D_CODEC          codec_type;        /* codec type */
    tA2D_CODEC_TYPE     codec_type;        /* codec type */
    uint8_t             tsep;              /* SEP type of local SEP */
    tBTA_AV_SINK_DATA_CBACK *p_app_sink_data_cback; /* Sink application callback for media packets */
} tBTA_AV_SEP;
@@ -468,7 +471,7 @@ typedef struct
    const tBTA_AV_ACT   *p_act_tbl;     /* the action table for stream state machine */
    const tBTA_AV_CO_FUNCTS *p_cos;     /* the associated callout functions */
    bool                sdp_discovery_started; /* variable to determine whether SDP is started */
    tBTA_AV_SEP         seps[BTA_AV_MAX_SEPS];
    tBTA_AV_SEP         seps[A2D_CODEC_SEP_INDEX_MAX];
    tAVDT_CFG           *p_cap;         /* buffer used for get capabilities */
    list_t              *a2d_list;      /* used for audio channels only */
    tBTA_AV_Q_INFO      q_info;
@@ -480,7 +483,7 @@ typedef struct
    uint16_t            stream_mtu;     /* MTU of stream */
    uint16_t            avdt_version;   /* the avdt version of peer device */
    tBTA_SEC            sec_mask;       /* security mask */
    tA2D_CODEC          codec_type;     /* codec type */
    tA2D_CODEC_TYPE     codec_type;     /* codec type */
    uint8_t             media_type;     /* Media type */
    bool                cong;           /* true if AVDTP congested */
    tBTA_AV_STATUS      open_status;    /* open failure status */
+13 −15
Original line number Diff line number Diff line
@@ -439,7 +439,6 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
    tAVDT_REG       reg;
    tAVDT_CS        cs;
    char            *p_service_name;
    tA2D_CODEC      codec_type;
    tBTA_UTL_COD    cod;

    memset(&cs,0,sizeof(tAVDT_CS));
@@ -558,7 +557,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
            cs.media_type    = AVDT_MEDIA_AUDIO;
            cs.mtu           = p_bta_av_cfg->audio_mtu;
            cs.flush_to      = L2CAP_DEFAULT_FLUSH_TO;
            uint8_t index    = 0;
            tA2D_CODEC_SEP_INDEX codec_sep_index = A2D_CODEC_SEP_INDEX_SBC;

#if (AVDT_REPORTING == TRUE)
            if(bta_av_cb.features & BTA_AV_FEAT_REPORT)
@@ -576,38 +575,37 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
            if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE)
            {
                cs.tsep = AVDT_TSEP_SRC;
                index = BTIF_SV_AV_AA_SBC_INDEX;
                codec_sep_index = A2D_CODEC_SEP_INDEX_SBC;
            }
            else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK)
            {
                cs.tsep = AVDT_TSEP_SNK;
                cs.p_sink_data_cback = bta_av_sink_data_cback;
                index = BTIF_SV_AV_AA_SBC_SINK_INDEX;
                codec_sep_index = A2D_CODEC_SEP_INDEX_SBC_SINK;
            }

            /* Initialize Handles to zero */
            for (int xx=0; xx < BTA_AV_MAX_SEPS; xx++)
            /* Initialize handles to zero */
            for (int xx = 0; xx < A2D_CODEC_SEP_INDEX_MAX; xx++)
            {
                p_scb->seps[xx].av_handle = 0;
            }

            /* keep the configuration in the stream control block */
            memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG));
            if ((*bta_av_a2d_cos.init)(&codec_type, cs.cfg.codec_info,
                &cs.cfg.num_protect, cs.cfg.protect_info, index) == true)
            {
                if(AVDT_CreateStream(&p_scb->seps[index].av_handle, &cs) == AVDT_SUCCESS)
                {
                    p_scb->seps[index].codec_type = codec_type;
                    p_scb->seps[index].tsep = cs.tsep;
            if ((*bta_av_a2d_cos.init)(codec_sep_index, &cs.cfg)) {
                if (AVDT_CreateStream(&p_scb->seps[codec_sep_index].av_handle, &cs)
                    == AVDT_SUCCESS) {
                    p_scb->seps[codec_sep_index].codec_type =
                        A2D_GetCodecType(cs.cfg.codec_info);
                    p_scb->seps[codec_sep_index].tsep = cs.tsep;
                    if (cs.tsep == AVDT_TSEP_SNK) {
                        p_scb->seps[index].p_app_sink_data_cback =
                        p_scb->seps[codec_sep_index].p_app_sink_data_cback =
                            p_data->api_reg.p_app_sink_data_cback;
                    } else {
                        /* In case of A2DP SOURCE we don't need a callback to
                         * handle media packets.
                         */
                        p_scb->seps[index].p_app_sink_data_cback = NULL;
                        p_scb->seps[codec_sep_index].p_app_sink_data_cback = NULL;
                    }
                }
            }
+0 −135
Original line number Diff line number Diff line
@@ -406,141 +406,6 @@ int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst,
    return ((char *)p_dst_tmp - (char *)p_dst);
}

/*******************************************************************************
**
** Function         bta_av_sbc_cfg_matches_cap
**
** Description      This function checks whether an SBC codec configuration
**                  matched with capabilities. Here we check subset.
**
** Returns          0 if ok, nonzero if error.
**
*******************************************************************************/
uint8_t bta_av_sbc_cfg_matches_cap(uint8_t *p_cfg, tA2D_SBC_CIE *p_cap)
{
    uint8_t           status = 0;
    tA2D_SBC_CIE    cfg_cie;

    /* parse configuration */
    if ((status = A2D_ParsSbcInfo(&cfg_cie, p_cfg, true)) != 0)
    {
        APPL_TRACE_ERROR(" bta_av_sbc_cfg_matches_cap Parsing Failed %d", status);
        return status;
    }

    /* verify that each parameter is in range */

    APPL_TRACE_DEBUG(" FREQ peer: 0%x, capability  0%x", cfg_cie.samp_freq, p_cap->samp_freq);
    APPL_TRACE_DEBUG(" CH_MODE peer: 0%x, capability  0%x", cfg_cie.ch_mode, p_cap->ch_mode);
    APPL_TRACE_DEBUG(" BLOCK_LEN peer: 0%x, capability  0%x", cfg_cie.block_len, p_cap->block_len);
    APPL_TRACE_DEBUG(" SUB_BAND peer: 0%x, capability  0%x", cfg_cie.num_subbands, p_cap->num_subbands);
    APPL_TRACE_DEBUG(" ALLOC_MTHD peer: 0%x, capability  0%x", cfg_cie.alloc_mthd, p_cap->alloc_mthd);
    APPL_TRACE_DEBUG(" MAX_BitPool peer: 0%x, capability  0%x", cfg_cie.max_bitpool, p_cap->max_bitpool);
    APPL_TRACE_DEBUG(" Min_bitpool peer: 0%x, capability  0%x", cfg_cie.min_bitpool, p_cap->min_bitpool);

    /* sampling frequency */
    if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0)
    {
        status = A2D_NS_SAMP_FREQ;
    }
    /* channel mode */
    else if ((cfg_cie.ch_mode & p_cap->ch_mode) == 0)
    {
        status = A2D_NS_CH_MODE;
    }
    /* block length */
    else if ((cfg_cie.block_len & p_cap->block_len) == 0)
    {
        status = A2D_BAD_BLOCK_LEN;
    }
    /* subbands */
    else if ((cfg_cie.num_subbands & p_cap->num_subbands) == 0)
    {
        status = A2D_NS_SUBBANDS;
    }
    /* allocation method */
    else if ((cfg_cie.alloc_mthd & p_cap->alloc_mthd) == 0)
    {
        status = A2D_NS_ALLOC_MTHD;
    }
    /* max bitpool */
    else if (cfg_cie.max_bitpool > p_cap->max_bitpool)
    {
        status = A2D_NS_MAX_BITPOOL;
    }
    /* min bitpool */
    else if (cfg_cie.min_bitpool < p_cap->min_bitpool)
    {
        status = A2D_NS_MIN_BITPOOL;
    }

    return status;
}


/*******************************************************************************
**
** Function         bta_av_sbc_cfg_in_cap
**
** Description      This function checks whether an SBC codec configuration
**                  is allowable for the given codec capabilities.
**
** Returns          0 if ok, nonzero if error.
**
*******************************************************************************/
uint8_t bta_av_sbc_cfg_in_cap(uint8_t *p_cfg, tA2D_SBC_CIE *p_cap)
{
    uint8_t           status = 0;
    tA2D_SBC_CIE    cfg_cie;

    /* parse configuration */
    if ((status = A2D_ParsSbcInfo(&cfg_cie, p_cfg, false)) != 0)
    {
        return status;
    }

    /* verify that each parameter is in range */


    /* sampling frequency */
    if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0)
    {
        status = A2D_NS_SAMP_FREQ;
    }
    /* channel mode */
    else if ((cfg_cie.ch_mode & p_cap->ch_mode) == 0)
    {
        status = A2D_NS_CH_MODE;
    }
    /* block length */
    else if ((cfg_cie.block_len & p_cap->block_len) == 0)
    {
        status = A2D_BAD_BLOCK_LEN;
    }
    /* subbands */
    else if ((cfg_cie.num_subbands & p_cap->num_subbands) == 0)
    {
        status = A2D_NS_SUBBANDS;
    }
    /* allocation method */
    else if ((cfg_cie.alloc_mthd & p_cap->alloc_mthd) == 0)
    {
        status = A2D_NS_ALLOC_MTHD;
    }
    /* max bitpool */
    else if (cfg_cie.max_bitpool > p_cap->max_bitpool)
    {
        status = A2D_NS_MAX_BITPOOL;
    }
    /* min bitpool */
    else if (cfg_cie.min_bitpool < p_cap->min_bitpool)
    {
        status = A2D_NS_MIN_BITPOOL;
    }

    return status;
}

/*******************************************************************************
**
** Function         bta_av_sbc_bld_hdr
Loading