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

Commit 9a81a263 authored by Pavlin Radoslavov's avatar Pavlin Radoslavov Committed by Andre Eisenbach
Browse files

A2DP codec related fixes and cleanup

* Update bta_av_co_audio_getconfig() to select the preferred codec
* Fix a bug in selecting the A2DP codec inside
  bta_av_co_audio_set_codec()
* No need for function A2DP_ParsSbcMplHdr() to be exposed in the API
* Generalize the following APIs, so they can be used to redirect
  the call for vendor-specific codecs:
  - A2DP_CodecSepIndexStr()
  - A2DP_InitCodecConfig()
  - A2DP_SetSourceCodec()
* Change tA2DP_ENCODER_INIT_PARAMS.SamplingFreq from uint16_t to
  uint32_t so it can store larger sampling frequency.
* Rename content protection constants from BTA_AV_CP_*
  to AVDT_CP_* and move them from bta_av_co.h to avdt_api.h
* Rename some of the internal functions in a2dp_sbc.cc
* Add extra debug logging and fix some comments

Test: A2DP streaming, unit tests passing
Change-Id: I1b67ff18dc568dd859429fcd89c644799fb1438d
parent fc16300e
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -751,7 +751,7 @@ static void bta_av_adjust_seps_idx(tBTA_AV_SCB *p_scb, uint8_t avdt_handle)
    APPL_TRACE_DEBUG("%s: codec: %s", __func__,
                     A2DP_CodecName(p_scb->cfg.codec_info));
    for (int i = 0; i < A2DP_CODEC_SEP_INDEX_MAX; i++) {
        APPL_TRACE_DEBUG("%s: av_handle: %d codec: %d", __func__,
        APPL_TRACE_DEBUG("%s: av_handle: %d codec: %s", __func__,
                         p_scb->seps[i].av_handle,
                         A2DP_CodecName(p_scb->seps[i].codec_info));
        if (p_scb->seps[i].av_handle &&
@@ -2884,6 +2884,7 @@ void bta_av_rcfg_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
{
    uint8_t   err_code = p_data->str_msg.msg.hdr.err_code;

    APPL_TRACE_DEBUG("%s: err_code = %d", __func__, err_code);
    if (err_code)
    {
        APPL_TRACE_ERROR("%s: reconfig rejected, try close", __func__);
@@ -2900,6 +2901,9 @@ void bta_av_rcfg_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
    else
    {
        /* update the codec info after rcfg cfm */
        APPL_TRACE_DEBUG("%s: updating from codec %s to codec %s",
                         __func__, A2DP_CodecName(p_scb->cfg.codec_info),
                         A2DP_CodecName(p_data->str_msg.msg.reconfig_cfm.p_cfg->codec_info));
        memcpy(p_scb->cfg.codec_info,p_data->str_msg.msg.reconfig_cfm.p_cfg->codec_info,AVDT_CODEC_SIZE);
        /* take the SSM back to OPEN state */
        bta_av_ssm_execute(p_scb, BTA_AV_STR_OPEN_OK_EVT, NULL);
+0 −12
Original line number Diff line number Diff line
@@ -35,18 +35,6 @@ extern "C" {
**  Constants and data types
*****************************************************************************/

/* the content protection IDs assigned by BT SIG */
#define BTA_AV_CP_SCMS_T_ID     0x0002
#define BTA_AV_CP_DTCP_ID       0x0001

#define BTA_AV_CP_LOSC                  2
#define BTA_AV_CP_INFO_LEN              3

#define BTA_AV_CP_SCMS_COPY_MASK        3
#define BTA_AV_CP_SCMS_COPY_FREE        2
#define BTA_AV_CP_SCMS_COPY_ONCE        1
#define BTA_AV_CP_SCMS_COPY_NEVER       0

/*******************************************************************************
**
** Function         bta_av_co_audio_init
+57 −23
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@
#define BTA_AV_CO_AUDIO_INDX_TO_HNDL(indx) (((indx) + 1) | BTA_AV_CHNL_AUDIO)

/* SCMS-T protect info */
const uint8_t bta_av_co_cp_scmst[BTA_AV_CP_INFO_LEN] = {0x02, 0x02, 0x00};
const uint8_t bta_av_co_cp_scmst[AVDT_CP_INFO_LEN] = {0x02, 0x02, 0x00};

/*****************************************************************************
 *  Local data
@@ -63,8 +63,7 @@ typedef struct {
  uint8_t seid;                        /* peer SEP index (in peer tables) */
  uint8_t codec_caps[AVDT_CODEC_SIZE]; /* peer SEP codec capabilities */
  uint8_t num_protect;                 /* peer SEP number of CP elements */
  uint8_t
      protect_info[BTA_AV_CP_INFO_LEN]; /* peer SEP content protection info */
  uint8_t protect_info[AVDT_CP_INFO_LEN]; /* peer SEP content protection info */
} tBTA_AV_CO_SINK;

typedef struct {
@@ -122,9 +121,9 @@ static bool bta_av_co_audio_codec_selected(const uint8_t* codec_config);
 ** Function         bta_av_co_cp_get_flag
 **
 ** Description      Get content protection flag
 **                  BTA_AV_CP_SCMS_COPY_NEVER
 **                  BTA_AV_CP_SCMS_COPY_ONCE
 **                  BTA_AV_CP_SCMS_COPY_FREE
 **                  AVDT_CP_SCMS_COPY_NEVER
 **                  AVDT_CP_SCMS_COPY_ONCE
 **                  AVDT_CP_SCMS_COPY_FREE
 **
 ** Returns          The current flag value
 **
@@ -136,9 +135,9 @@ static uint8_t bta_av_co_cp_get_flag(void) { return bta_av_co_cb.cp.flag; }
 ** Function         bta_av_co_cp_set_flag
 **
 ** Description      Set content protection flag
 **                  BTA_AV_CP_SCMS_COPY_NEVER
 **                  BTA_AV_CP_SCMS_COPY_ONCE
 **                  BTA_AV_CP_SCMS_COPY_FREE
 **                  AVDT_CP_SCMS_COPY_NEVER
 **                  AVDT_CP_SCMS_COPY_ONCE
 **                  AVDT_CP_SCMS_COPY_FREE
 **
 ** Returns          true if setting the SCMS flag is supported else false
 **
@@ -148,7 +147,7 @@ static bool bta_av_co_cp_set_flag(uint8_t cp_flag) {

#if (BTA_AV_CO_CP_SCMS_T == TRUE)
#else
  if (cp_flag != BTA_AV_CP_SCMS_COPY_FREE) {
  if (cp_flag != AVDT_CP_SCMS_COPY_FREE) {
    return false;
  }
#endif
@@ -301,7 +300,7 @@ static tA2DP_STATUS bta_av_audio_sink_getconfig(
      p_src->sep_info_idx = *p_sep_info_idx;
      p_src->seid = seid;
      p_src->num_protect = *p_num_protect;
      memcpy(p_src->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN);
      memcpy(p_src->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
    } else {
      APPL_TRACE_ERROR("%s: no more room for SRC info", __func__);
    }
@@ -414,7 +413,7 @@ tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
      p_sink->sep_info_idx = *p_sep_info_idx;
      p_sink->seid = seid;
      p_sink->num_protect = *p_num_protect;
      memcpy(p_sink->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN);
      memcpy(p_sink->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
    } else {
      APPL_TRACE_ERROR("%s: no more room for SINK info", __func__);
    }
@@ -429,8 +428,35 @@ tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
    mutex_global_lock();

    /* Find a sink that matches the codec config */
    const tBTA_AV_CO_SINK* p_sink =
      bta_av_co_find_peer_sink_supports_codec(bta_av_co_cb.codec_config, p_peer);
    const tBTA_AV_CO_SINK* p_sink = NULL;

    // Initial strawman codec selection mechanism: largest codec SEP index
    // first.
    // TODO: Replace this mechanism with a better one, and abstract it
    // in a separate function.
    for (int i = A2DP_CODEC_SEP_INDEX_SOURCE_MAX - 1;
         i >= A2DP_CODEC_SEP_INDEX_SOURCE_MIN; i--) {
      tA2DP_CODEC_SEP_INDEX source_codec_sep_index =
        static_cast<tA2DP_CODEC_SEP_INDEX>(i);
      APPL_TRACE_DEBUG("%s: trying codec %s with sep_index %d", __func__,
                       A2DP_CodecSepIndexStr(source_codec_sep_index), i);
      tAVDT_CFG avdt_cfg;
      if (!A2DP_InitCodecConfig(source_codec_sep_index, &avdt_cfg)) {
        APPL_TRACE_DEBUG("%s: cannot setup source codec %s", __func__,
                         A2DP_CodecSepIndexStr(source_codec_sep_index));
        continue;
      }
      p_sink = bta_av_co_find_peer_sink_supports_codec(avdt_cfg.codec_info,
                                                       p_peer);
      if (p_sink == NULL)
        continue;
      // Found a preferred codec
      APPL_TRACE_DEBUG("%s: selected codec %s", __func__,
                       A2DP_CodecName(avdt_cfg.codec_info));
      memcpy(bta_av_co_cb.codec_config, avdt_cfg.codec_info, AVDT_CODEC_SIZE);
      break;
    }

    if (p_sink == NULL) {
      APPL_TRACE_ERROR("%s: cannot find peer SINK for this codec config",
                       __func__);
@@ -466,8 +492,8 @@ tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
        p_peer->cp_active = bta_av_co_audio_sink_has_scmst(p_sink);
        bta_av_co_cb.cp.active = p_peer->cp_active;
        if (p_peer->cp_active) {
          *p_num_protect = BTA_AV_CP_INFO_LEN;
          memcpy(p_protect_info, bta_av_co_cp_scmst, BTA_AV_CP_INFO_LEN);
          *p_num_protect = AVDT_CP_INFO_LEN;
          memcpy(p_protect_info, bta_av_co_cp_scmst, AVDT_CP_INFO_LEN);
        }
#endif

@@ -795,12 +821,12 @@ void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, uint16_t delay) {
static bool bta_av_co_cp_is_scmst(const uint8_t* p_protectinfo) {
  APPL_TRACE_DEBUG("%s", __func__);

  if (*p_protectinfo >= BTA_AV_CP_LOSC) {
  if (*p_protectinfo >= AVDT_CP_LOSC) {
    uint16_t cp_id;

    p_protectinfo++;
    STREAM_TO_UINT16(cp_id, p_protectinfo);
    if (cp_id == BTA_AV_CP_SCMS_T_ID) {
    if (cp_id == AVDT_CP_SCMS_T_ID) {
      APPL_TRACE_DEBUG("%s: SCMS-T found", __func__);
      return true;
    }
@@ -852,7 +878,7 @@ static bool bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK* p_sink) {
  APPL_TRACE_DEBUG("%s", __func__);

  /* Check if content protection is enabled for this stream */
  if (bta_av_co_cp_get_flag() != BTA_AV_CP_SCMS_COPY_FREE)
  if (bta_av_co_cp_get_flag() != AVDT_CP_SCMS_COPY_FREE)
    return bta_av_co_audio_sink_has_scmst(p_sink);

  APPL_TRACE_DEBUG("%s: not required", __func__);
@@ -933,16 +959,24 @@ bool bta_av_co_audio_set_codec(const tA2DP_FEEDING_PARAMS* p_feeding_params) {
       i >= A2DP_CODEC_SEP_INDEX_SOURCE_MIN; i--) {
    tA2DP_CODEC_SEP_INDEX source_codec_sep_index =
      static_cast<tA2DP_CODEC_SEP_INDEX>(i);
    APPL_TRACE_DEBUG("%s: trying codec %s with sep_index %d", __func__,
                     A2DP_CodecSepIndexStr(source_codec_sep_index), i);
    if (!A2DP_SetSourceCodec(source_codec_sep_index, p_feeding_params,
                             new_config)) {
      APPL_TRACE_DEBUG("%s: cannot setup source codec %s", __func__,
                       A2DP_CodecSepIndexStr(source_codec_sep_index));
      continue;
    }

    /* Try to select an open device for the codec */
    if (bta_av_co_audio_codec_selected(bta_av_co_cb.codec_config)) {
    if (bta_av_co_audio_codec_selected(new_config)) {
      APPL_TRACE_DEBUG("%s: selected codec %s with sep_index %d", __func__,
                       A2DP_CodecSepIndexStr(source_codec_sep_index), i);
      mutex_global_unlock();
      return true;
    }
    APPL_TRACE_DEBUG("%s: cannot select source codec %s", __func__,
                     A2DP_CodecSepIndexStr(source_codec_sep_index));
  }
  mutex_global_unlock();
  return false;
@@ -995,7 +1029,7 @@ static bool bta_av_co_audio_codec_selected(const uint8_t* codec_config) {
    bool cp_active = bta_av_co_audio_sink_has_scmst(p_sink);
    bta_av_co_cb.cp.active = cp_active;
    p_peer->cp_active = cp_active;
    if (p_peer->cp_active) num_protect = BTA_AV_CP_INFO_LEN;
    if (p_peer->cp_active) num_protect = AVDT_CP_INFO_LEN;
#endif
    APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(0x%x)", __func__,
                     BTA_AV_CO_AUDIO_INDX_TO_HNDL(index));
@@ -1161,9 +1195,9 @@ void bta_av_co_init(void) {
  memset(&bta_av_co_cb, 0, sizeof(bta_av_co_cb));

#if (BTA_AV_CO_CP_SCMS_T == TRUE)
  bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_NEVER);
  bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_NEVER);
#else
  bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_FREE);
  bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_FREE);
#endif

  /* Reset the current config */
+18 −6
Original line number Diff line number Diff line
@@ -524,11 +524,17 @@ bool A2DP_SetSourceCodec(tA2DP_CODEC_SEP_INDEX source_codec_sep_index,
    case A2DP_CODEC_SEP_INDEX_SOURCE_SBC:
      return A2DP_SetSourceCodecSbc(p_feeding_params, p_codec_info);
    case A2DP_CODEC_SEP_INDEX_SINK_SBC:
      return false;
    case A2DP_CODEC_SEP_INDEX_MAX:
      return false;             // Not a source codec
    default:
      break;
  }

  if (source_codec_sep_index < A2DP_CODEC_SEP_INDEX_MAX) {
    return A2DP_VendorSetSourceCodec(source_codec_sep_index,
                                     p_feeding_params,
                                     p_codec_info);
  }

  return false;
}

@@ -587,13 +593,16 @@ bool A2DP_UsesRtpHeader(bool content_protection_enabled,
const char* A2DP_CodecSepIndexStr(tA2DP_CODEC_SEP_INDEX codec_sep_index) {
  switch (codec_sep_index) {
    case A2DP_CODEC_SEP_INDEX_SOURCE_SBC:
      return "SBC";
      return A2DP_CodecSepIndexStrSbc();
    case A2DP_CODEC_SEP_INDEX_SINK_SBC:
      return "SBC SINK";
    case A2DP_CODEC_SEP_INDEX_MAX:
      return A2DP_CodecSepIndexStrSbcSink();
    default:
      break;
  }

  if (codec_sep_index < A2DP_CODEC_SEP_INDEX_MAX)
    return A2DP_VendorCodecSepIndexStr(codec_sep_index);

  return "UNKNOWN CODEC SEP INDEX";
}

@@ -611,10 +620,13 @@ bool A2DP_InitCodecConfig(tA2DP_CODEC_SEP_INDEX codec_sep_index,
      return A2DP_InitCodecConfigSbc(p_cfg);
    case A2DP_CODEC_SEP_INDEX_SINK_SBC:
      return A2DP_InitCodecConfigSbcSink(p_cfg);
    case A2DP_CODEC_SEP_INDEX_MAX:
    default:
      break;
  }

  if (codec_sep_index < A2DP_CODEC_SEP_INDEX_MAX)
    return A2DP_VendorInitCodecConfig(codec_sep_index, p_cfg);

  return false;
}

+80 −65

File changed.

Preview size limit exceeded, changes collapsed.

Loading