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

Commit c921e2c9 authored by Pavlin Radoslavov's avatar Pavlin Radoslavov Committed by android-build-merger
Browse files

Update the A2DP Codec Config API

am: d26099b8

Change-Id: I02831600027b777d41dc5c1b67ac844fa03e9118
parents c2b17ded d26099b8
Loading
Loading
Loading
Loading
+90 −18
Original line number Diff line number Diff line
@@ -132,6 +132,8 @@ static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(
static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer);
static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(
    A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer);
static bool bta_av_co_audio_update_selectable_codec(
    A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer);
static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer,
                                            const uint8_t* new_codec_config,
                                            uint8_t num_protect,
@@ -848,21 +850,39 @@ static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(

//
// Select the current codec configuration based on peer codec support.
// Return true on success, otherwise false.
// Furthermore, the local state for the remaining non-selected codecs is
// updated to reflect whether the codec is selectable.
// Return a pointer to the corresponding |tBTA_AV_CO_SINK| sink entry
// on success, otherwise NULL.
//
static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer) {
  tBTA_AV_CO_SINK* p_sink = NULL;

  // Update all selectable codecs.
  // This is needed to update the selectable parameters for each codec.
  // NOTE: The selectable codec info is used only for informational purpose.
  for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) {
    APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__,
                     iter->name().c_str());
    bta_av_co_audio_update_selectable_codec(*iter, p_peer);
  }

  // Select the codec
  for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) {
    APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str());
    // Try to select an open device for the codec
    tBTA_AV_CO_SINK* p_sink = bta_av_co_audio_codec_selected(*iter, p_peer);
    p_sink = bta_av_co_audio_codec_selected(*iter, p_peer);
    if (p_sink != NULL) {
      APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str());
      return p_sink;
      break;
    }
    APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str());
  }

  return NULL;
  // NOTE: Unconditionally dispatch the event to make sure a callback with
  // the most recent codec info is generated.
  btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);

  return p_sink;
}

// Select an open device for the preferred codec specified by |codec_config|.
@@ -896,8 +916,9 @@ static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(
                     codec_config.name().c_str());
    return NULL;
  }
  if (!bta_av_co_cb.codecs->setCodecConfig(p_sink->codec_caps, true,
                                           new_codec_config)) {
  if (!bta_av_co_cb.codecs->setCodecConfig(
          p_sink->codec_caps, true /* is_capability */, new_codec_config,
          true /* select_current_codec */)) {
    APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__,
                     codec_config.name().c_str());
    return NULL;
@@ -906,11 +927,52 @@ static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(

  bta_av_co_save_new_codec_config(p_peer, new_codec_config, p_sink->num_protect,
                                  p_sink->protect_info);
  btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
  // NOTE: Event BTIF_AV_SOURCE_CONFIG_UPDATED_EVT is dispatched by the caller

  return p_sink;
}

// Update a selectable codec |codec_config| with the corresponding codec
// information from a peer device |p_peer|.
// Returns true if the codec is updated, otherwise false.
static bool bta_av_co_audio_update_selectable_codec(
    A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer) {
  uint8_t new_codec_config[AVDT_CODEC_SIZE];

  APPL_TRACE_DEBUG("%s", __func__);

  // Find the peer sink for the codec
  const tBTA_AV_CO_SINK* p_sink = NULL;
  for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
    btav_a2dp_codec_index_t peer_codec_index =
        A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
    if (peer_codec_index != codec_config.codecIndex()) {
      continue;
    }
    if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) {
      APPL_TRACE_DEBUG(
          "%s: peer sink for codec %s does not support "
          "Copy Protection",
          __func__, codec_config.name().c_str());
      continue;
    }
    p_sink = &p_peer->sinks[index];
    break;
  }
  if (p_sink == NULL) {
    // The peer sink device does not support this codec
    return false;
  }
  if (!bta_av_co_cb.codecs->setCodecConfig(
          p_sink->codec_caps, true /* is_capability */, new_codec_config,
          false /* select_current_codec */)) {
    APPL_TRACE_DEBUG("%s: cannot update source codec %s", __func__,
                     codec_config.name().c_str());
    return false;
  }
  return true;
}

static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer,
                                            const uint8_t* new_codec_config,
                                            uint8_t num_protect,
@@ -973,9 +1035,11 @@ const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) {
bool bta_av_co_set_codec_user_config(
    const btav_a2dp_codec_config_t& codec_user_config) {
  uint8_t result_codec_config[AVDT_CODEC_SIZE];
  const tBTA_AV_CO_SINK* p_sink = nullptr;
  bool restart_input = false;
  bool restart_output = false;
  bool config_updated = false;
  bool success = true;

  // Find the peer that is currently open
  tBTA_AV_CO_PEER* p_peer = nullptr;
@@ -988,11 +1052,11 @@ bool bta_av_co_set_codec_user_config(
  }
  if (p_peer == nullptr) {
    APPL_TRACE_ERROR("%s: no open peer to configure", __func__);
    return false;
    success = false;
    goto done;
  }

  // Find the peer SEP codec to use
  const tBTA_AV_CO_SINK* p_sink = nullptr;
  if (codec_user_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) {
    for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
      btav_a2dp_codec_index_t peer_codec_index =
@@ -1008,7 +1072,8 @@ bool bta_av_co_set_codec_user_config(
  }
  if (p_sink == nullptr) {
    APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__);
    return false;
    success = false;
    goto done;
  }

  tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
@@ -1017,7 +1082,8 @@ bool bta_av_co_set_codec_user_config(
          codec_user_config, &peer_params, p_sink->codec_caps,
          result_codec_config, &restart_input, &restart_output,
          &config_updated)) {
    return false;
    success = false;
    goto done;
  }

  if (restart_output) {
@@ -1034,13 +1100,15 @@ bool bta_av_co_set_codec_user_config(
                   p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
  }

  if (restart_input || config_updated) {
done:
  // NOTE: We uncoditionally send the upcall even if there is no change
  // or the user config failed. Thus, the caller would always know whether the
  // request succeeded or failed.
  // NOTE: Currently, the input is restarted by sending an upcall
  // and informing the Media Framework about the change.
  btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
  }

  return true;
  return success;
}

// Sets the Over-The-Air preferred codec configuration.
@@ -1211,4 +1279,8 @@ void bta_av_co_init(void) {
  bta_av_co_cb.codecs->init();
  A2DP_InitDefaultCodec(bta_av_co_cb.codec_config);
  mutex_global_unlock();

  // NOTE: Unconditionally dispatch the event to make sure a callback with
  // the most recent codec info is generated.
  btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
}
+6 −4
Original line number Diff line number Diff line
@@ -296,12 +296,14 @@ static void btif_update_source_codec(void* p_data) {

static void btif_report_source_codec_state(UNUSED_ATTR void* p_data) {
  btav_a2dp_codec_config_t codec_config;
  std::vector<btav_a2dp_codec_config_t> codec_capabilities;
  std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities;
  std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities;

  A2dpCodecs* a2dp_codecs = bta_av_get_a2dp_codecs();
  if (a2dp_codecs == nullptr) return;
  if (!a2dp_codecs->getCodecConfigAndCapabilities(&codec_config,
                                                  &codec_capabilities)) {
  if (!a2dp_codecs->getCodecConfigAndCapabilities(
          &codec_config, &codecs_local_capabilities,
          &codecs_selectable_capabilities)) {
    BTIF_TRACE_WARNING(
        "BTIF_AV_SOURCE_CONFIG_UPDATED_EVT failed: "
        "cannot get codec config and capabilities");
@@ -309,7 +311,7 @@ static void btif_report_source_codec_state(UNUSED_ATTR void* p_data) {
  }
  if (bt_av_src_callbacks != NULL) {
    HAL_CBACK(bt_av_src_callbacks, audio_config_cb, codec_config,
              codec_capabilities);
              codecs_local_capabilities, codecs_selectable_capabilities);
  }
}

+57 −1
Original line number Diff line number Diff line
@@ -650,7 +650,28 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_AAC_CIE& config_cie,
}

A2dpCodecConfigAac::A2dpCodecConfigAac()
    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC, "AAC") {}
    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC, "AAC") {
  // Compute the local capability
  if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) {
    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
  }
  if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) {
    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
  }
  if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) {
    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
  }
  if (a2dp_aac_caps.sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) {
    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
  }
  codec_local_capability_.bits_per_sample = a2dp_aac_caps.bits_per_sample;
  if (a2dp_aac_caps.channelMode & A2DP_AAC_CHANNEL_MODE_MONO) {
    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
  }
  if (a2dp_aac_caps.channelMode & A2DP_AAC_CHANNEL_MODE_STEREO) {
    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
  }
}

A2dpCodecConfigAac::~A2dpCodecConfigAac() {}

@@ -873,6 +894,8 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info,
  // Save the internal state
  btav_a2dp_codec_config_t saved_codec_config = codec_config_;
  btav_a2dp_codec_config_t saved_codec_capability = codec_capability_;
  btav_a2dp_codec_config_t saved_codec_selectable_capability =
      codec_selectable_capability_;
  btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_;
  btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_;
  uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE];
@@ -953,6 +976,24 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info,

  // Select the sample frequency if there is no user preference
  do {
    // Compute the selectable capability
    if (sampleRate & A2DP_AAC_SAMPLING_FREQ_44100) {
      codec_selectable_capability_.sample_rate |=
          BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
    }
    if (sampleRate & A2DP_AAC_SAMPLING_FREQ_48000) {
      codec_selectable_capability_.sample_rate |=
          BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
    }
    if (sampleRate & A2DP_AAC_SAMPLING_FREQ_88200) {
      codec_selectable_capability_.sample_rate |=
          BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
    }
    if (sampleRate & A2DP_AAC_SAMPLING_FREQ_96000) {
      codec_selectable_capability_.sample_rate |=
          BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
    }

    if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break;

    // Compute the common capability
@@ -1030,6 +1071,10 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info,

  // Select the bits per sample if there is no user preference
  do {
    // Compute the selectable capability
    codec_selectable_capability_.bits_per_sample =
        a2dp_aac_caps.bits_per_sample;

    if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
      break;

@@ -1092,6 +1137,16 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info,

  // Select the channel mode if there is no user preference
  do {
    // Compute the selectable capability
    if (channelMode & A2DP_AAC_CHANNEL_MODE_MONO) {
      codec_selectable_capability_.channel_mode |=
          BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
    }
    if (channelMode & A2DP_AAC_CHANNEL_MODE_STEREO) {
      codec_selectable_capability_.channel_mode |=
          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
    }

    if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break;

    // Compute the common capability
@@ -1164,6 +1219,7 @@ fail:
  // Restore the internal state
  codec_config_ = saved_codec_config;
  codec_capability_ = saved_codec_capability;
  codec_selectable_capability_ = saved_codec_selectable_capability;
  codec_user_config_ = saved_codec_user_config;
  codec_audio_config_ = saved_codec_audio_config;
  memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_));
+66 −20
Original line number Diff line number Diff line
@@ -35,22 +35,34 @@
/* The Media Type offset within the codec info byte array */
#define A2DP_MEDIA_TYPE_OFFSET 1

// Initializes the codec config.
// |codec_config| is the codec config to initialize.
// |codec_index| and |codec_priority| are the codec type and priority to use
// for the initialization.
static void init_btav_a2dp_codec_config(
    btav_a2dp_codec_config_t* codec_config, btav_a2dp_codec_index_t codec_index,
    btav_a2dp_codec_priority_t codec_priority) {
  memset(codec_config, 0, sizeof(btav_a2dp_codec_config_t));
  codec_config->codec_type = codec_index;
  codec_config->codec_priority = codec_priority;
}

A2dpCodecConfig::A2dpCodecConfig(btav_a2dp_codec_index_t codec_index,
                                 const std::string& name)
    : codec_index_(codec_index), name_(name) {
  setDefaultCodecPriority();

  memset(&codec_config_, 0, sizeof(codec_config_));
  codec_config_.codec_type = codec_index_;

  memset(&codec_capability_, 0, sizeof(codec_capability_));
  codec_capability_.codec_type = codec_index_;

  memset(&codec_user_config_, 0, sizeof(codec_user_config_));
  codec_user_config_.codec_type = codec_index_;

  memset(&codec_audio_config_, 0, sizeof(codec_audio_config_));
  codec_audio_config_.codec_type = codec_index_;
  init_btav_a2dp_codec_config(&codec_config_, codec_index_, codecPriority());
  init_btav_a2dp_codec_config(&codec_capability_, codec_index_,
                              codecPriority());
  init_btav_a2dp_codec_config(&codec_local_capability_, codec_index_,
                              codecPriority());
  init_btav_a2dp_codec_config(&codec_selectable_capability_, codec_index_,
                              codecPriority());
  init_btav_a2dp_codec_config(&codec_user_config_, codec_index_,
                              BTAV_A2DP_CODEC_PRIORITY_DEFAULT);
  init_btav_a2dp_codec_config(&codec_audio_config_, codec_index_,
                              BTAV_A2DP_CODEC_PRIORITY_DEFAULT);

  memset(ota_codec_config_, 0, sizeof(ota_codec_config_));
  memset(ota_codec_peer_capability_, 0, sizeof(ota_codec_peer_capability_));
@@ -61,7 +73,7 @@ A2dpCodecConfig::~A2dpCodecConfig() {}

void A2dpCodecConfig::setCodecPriority(
    btav_a2dp_codec_priority_t codec_priority) {
  if (codec_priority == 0) {
  if (codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) {
    // Compute the default codec priority
    setDefaultCodecPriority();
  } else {
@@ -71,7 +83,8 @@ void A2dpCodecConfig::setCodecPriority(

void A2dpCodecConfig::setDefaultCodecPriority() {
  // Compute the default codec priority
  codec_priority_ = 1000 * codec_index_ + 1;
  uint32_t priority = 1000 * codec_index_ + 1;
  codec_priority_ = static_cast<btav_a2dp_codec_priority_t>(priority);
}

A2dpCodecConfig* A2dpCodecConfig::createCodec(
@@ -141,6 +154,20 @@ btav_a2dp_codec_config_t A2dpCodecConfig::getCodecCapability() {
  return codec_capability_;
}

btav_a2dp_codec_config_t A2dpCodecConfig::getCodecLocalCapability() {
  std::lock_guard<std::recursive_mutex> lock(codec_mutex_);

  // TODO: We should check whether the codec capability is valid
  return codec_local_capability_;
}

btav_a2dp_codec_config_t A2dpCodecConfig::getCodecSelectableCapability() {
  std::lock_guard<std::recursive_mutex> lock(codec_mutex_);

  // TODO: We should check whether the codec capability is valid
  return codec_selectable_capability_;
}

btav_a2dp_codec_config_t A2dpCodecConfig::getCodecUserConfig() {
  std::lock_guard<std::recursive_mutex> lock(codec_mutex_);

@@ -172,7 +199,7 @@ uint8_t A2dpCodecConfig::getAudioBitsPerSample() {
bool A2dpCodecConfig::isCodecConfigEmpty(
    const btav_a2dp_codec_config_t& codec_config) {
  return (
      (codec_config.codec_priority == 0) &&
      (codec_config.codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) &&
      (codec_config.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) &&
      (codec_config.bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) &&
      (codec_config.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) &&
@@ -324,7 +351,8 @@ A2dpCodecConfig* A2dpCodecs::findSourceCodecConfig(

bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info,
                                bool is_capability,
                                uint8_t* p_result_codec_config) {
                                uint8_t* p_result_codec_config,
                                bool select_current_codec) {
  std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
  A2dpCodecConfig* a2dp_codec_config = findSourceCodecConfig(p_peer_codec_info);
  if (a2dp_codec_config == nullptr) return false;
@@ -332,7 +360,9 @@ bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info,
                                         p_result_codec_config)) {
    return false;
  }
  if (select_current_codec) {
    current_codec_config_ = a2dp_codec_config;
  }
  return true;
}

@@ -522,7 +552,8 @@ fail:

bool A2dpCodecs::getCodecConfigAndCapabilities(
    btav_a2dp_codec_config_t* p_codec_config,
    std::vector<btav_a2dp_codec_config_t>* p_codec_capabilities) {
    std::vector<btav_a2dp_codec_config_t>* p_codecs_local_capabilities,
    std::vector<btav_a2dp_codec_config_t>* p_codecs_selectable_capabilities) {
  std::lock_guard<std::recursive_mutex> lock(codec_mutex_);

  if (current_codec_config_ != nullptr) {
@@ -533,11 +564,26 @@ bool A2dpCodecs::getCodecConfigAndCapabilities(
    *p_codec_config = codec_config;
  }

  std::vector<btav_a2dp_codec_config_t> codec_capabilities;
  std::vector<btav_a2dp_codec_config_t> codecs_capabilities;
  for (auto codec : orderedSourceCodecs()) {
    codec_capabilities.push_back(codec->getCodecCapability());
    codecs_capabilities.push_back(codec->getCodecLocalCapability());
  }
  *p_codec_capabilities = codec_capabilities;
  *p_codecs_local_capabilities = codecs_capabilities;

  codecs_capabilities.clear();
  for (auto codec : orderedSourceCodecs()) {
    btav_a2dp_codec_config_t codec_capability =
        codec->getCodecSelectableCapability();
    // Don't add entries that cannot be used
    if ((codec_capability.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) ||
        (codec_capability.bits_per_sample ==
         BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) ||
        (codec_capability.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE)) {
      continue;
    }
    codecs_capabilities.push_back(codec_capability);
  }
  *p_codecs_selectable_capabilities = codecs_capabilities;

  return true;
}
+77 −17
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ typedef struct {
  uint8_t alloc_method; /* Allocation method */
  uint8_t min_bitpool;  /* Minimum bitpool */
  uint8_t max_bitpool;  /* Maximum bitpool */
  btav_a2dp_codec_bits_per_sample_t bits_per_sample;
} tA2DP_SBC_CIE;

/* SBC SRC codec capabilities */
@@ -59,7 +60,8 @@ static const tA2DP_SBC_CIE a2dp_sbc_caps = {
    A2DP_SBC_IE_SUBBAND_8,             /* num_subbands */
    A2DP_SBC_IE_ALLOC_MD_L,            /* alloc_method */
    A2DP_SBC_IE_MIN_BITPOOL,           /* min_bitpool */
    A2DP_SBC_MAX_BITPOOL      /* max_bitpool */
    A2DP_SBC_MAX_BITPOOL,              /* max_bitpool */
    BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */
};

/* SBC SINK codec capabilities */
@@ -72,7 +74,8 @@ static const tA2DP_SBC_CIE a2dp_sbc_sink_caps = {
    (A2DP_SBC_IE_SUBBAND_4 | A2DP_SBC_IE_SUBBAND_8),   /* num_subbands */
    (A2DP_SBC_IE_ALLOC_MD_L | A2DP_SBC_IE_ALLOC_MD_S), /* alloc_method */
    A2DP_SBC_IE_MIN_BITPOOL,                           /* min_bitpool */
    A2DP_SBC_MAX_BITPOOL                               /* max_bitpool */
    A2DP_SBC_MAX_BITPOOL,                              /* max_bitpool */
    BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16                 /* bits_per_sample */
};

/* Default SBC codec configuration */
@@ -83,7 +86,8 @@ const tA2DP_SBC_CIE a2dp_sbc_default_config = {
    A2DP_SBC_IE_SUBBAND_8,             /* num_subbands */
    A2DP_SBC_IE_ALLOC_MD_L,            /* alloc_method */
    A2DP_SBC_IE_MIN_BITPOOL,           /* min_bitpool */
    A2DP_SBC_MAX_BITPOOL      /* max_bitpool */
    A2DP_SBC_MAX_BITPOOL,              /* max_bitpool */
    BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 /* bits_per_sample */
};

static const tA2DP_ENCODER_INTERFACE a2dp_encoder_interface_sbc = {
@@ -1014,7 +1018,7 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_SBC_CIE& config_cie,
  if (config_cie.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48)
    result->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;

  result->bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
  result->bits_per_sample = config_cie.bits_per_sample;

  if (config_cie.ch_mode & A2DP_SBC_IE_CH_MD_MONO)
    result->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
@@ -1026,7 +1030,28 @@ UNUSED_ATTR static void build_codec_config(const tA2DP_SBC_CIE& config_cie,
}

A2dpCodecConfigSbc::A2dpCodecConfigSbc()
    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC") {}
    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC") {
  // Compute the local capability
  if (a2dp_sbc_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) {
    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
  }
  if (a2dp_sbc_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) {
    codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
  }
  codec_local_capability_.bits_per_sample = a2dp_sbc_caps.bits_per_sample;
  if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_MONO) {
    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
  }
  if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_JOINT) {
    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
  }
  if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_STEREO) {
    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
  }
  if (a2dp_sbc_caps.ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
    codec_local_capability_.channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
  }
}

A2dpCodecConfigSbc::~A2dpCodecConfigSbc() {}

@@ -1214,6 +1239,8 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info,
  // Save the internal state
  btav_a2dp_codec_config_t saved_codec_config = codec_config_;
  btav_a2dp_codec_config_t saved_codec_capability = codec_capability_;
  btav_a2dp_codec_config_t saved_codec_selectable_capability =
      codec_selectable_capability_;
  btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_;
  btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_;
  uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE];
@@ -1270,6 +1297,16 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info,

  // Select the sample frequency if there is no user preference
  do {
    // Compute the selectable capability
    if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) {
      codec_selectable_capability_.sample_rate |=
          BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
    }
    if (samp_freq & A2DP_SBC_IE_SAMP_FREQ_48) {
      codec_selectable_capability_.sample_rate |=
          BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
    }

    if (codec_config_.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) break;

    // Compute the common capability
@@ -1326,6 +1363,10 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info,

  // Select the bits per sample if there is no user preference
  do {
    // Compute the selectable capability
    codec_selectable_capability_.bits_per_sample =
        a2dp_sbc_caps.bits_per_sample;

    if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
      break;

@@ -1396,6 +1437,24 @@ bool A2dpCodecConfigSbc::setCodecConfig(const uint8_t* p_peer_codec_info,

  // Select the channel mode if there is no user preference
  do {
    // Compute the selectable capability
    if (ch_mode & A2DP_SBC_IE_CH_MD_MONO) {
      codec_selectable_capability_.channel_mode |=
          BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
    }
    if (ch_mode & A2DP_SBC_IE_CH_MD_JOINT) {
      codec_selectable_capability_.channel_mode |=
          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
    }
    if (ch_mode & A2DP_SBC_IE_CH_MD_STEREO) {
      codec_selectable_capability_.channel_mode |=
          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
    }
    if (ch_mode & A2DP_SBC_IE_CH_MD_DUAL) {
      codec_selectable_capability_.channel_mode |=
          BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
    }

    if (codec_config_.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) break;

    // Compute the common capability
@@ -1538,6 +1597,7 @@ fail:
  // Restore the internal state
  codec_config_ = saved_codec_config;
  codec_capability_ = saved_codec_capability;
  codec_selectable_capability_ = saved_codec_selectable_capability;
  codec_user_config_ = saved_codec_user_config;
  codec_audio_config_ = saved_codec_audio_config;
  memcpy(ota_codec_config_, saved_ota_codec_config, sizeof(ota_codec_config_));
Loading