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

Commit db0a7134 authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

broadcaster: Fix channel location in BIG

Each BIS should have individual channel location unless it's
a mono signal.

Bug: 150670922
Tag: #feature
Test: start broadcast using LeAudioTestApp and verify HCI logs
Sponsor: jpawlowski@

Change-Id: Ibf0dbffb9ac76e04595a06fd01370f3305cb00bb
parent f331b2b4
Loading
Loading
Loading
Loading
+7 −11
Original line number Diff line number Diff line
@@ -129,12 +129,11 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
    announcement.presentation_delay = 0x004E20; /* TODO: Use the proper value */

    auto const& codec_id = codec_config.GetLeAudioCodecId();
    auto codec_spec_data = codec_config.GetCodecSpecData();

    /* Note: Currently we have a single audio source configured with a one
     *       set of codec/pcm parameters thus we can use a single subgroup
     *       for all the BISes. And configure codec params at the BIG level,
     *       since all these BISes share common codec configuration.
     *       for all the BISes. Configure common BIS codec params at the
     *       subgroup level.
     */
    announcement.subgroup_configs = {{
        .codec_config =
@@ -142,21 +141,18 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
                .codec_id = codec_id.coding_format,
                .vendor_company_id = codec_id.vendor_company_id,
                .vendor_codec_id = codec_id.vendor_codec_id,
                .codec_specific_params = std::move(codec_spec_data),
                .codec_specific_params =
                    codec_config.GetSubgroupCodecSpecData().RawPacket(),
            },
        .metadata = std::move(metadata),
        .bis_configs = {},
    }};

    /* In general we could have individual BISes in this single subgroup
     * have different codec configurations, but here we put all channel bises
     * into this one subgroup and assign every BIS's index with an empty config
     * to indicate that the lower lvl config should be used instead.
     * BIS indices range is [1-31] - BASS, Sec.3.2 Broadcast Receive State.
     */
    /* BIS indices range is [1-31] - BASS, Sec.3.2 Broadcast Receive State. */
    for (uint8_t i = 0; i < codec_config.GetNumChannels(); ++i) {
      announcement.subgroup_configs[0].bis_configs.push_back(
          {.codec_specific_params = {},
          {.codec_specific_params =
               codec_config.GetBisCodecSpecData(i + 1).RawPacket(),
           .bis_index = static_cast<uint8_t>(i + 1)});
    }

+26 −16
Original line number Diff line number Diff line
@@ -228,7 +228,27 @@ const std::map<uint32_t, uint8_t> data_interval_ms_to_frame_duration = {
     codec_spec_conf::kLeAudioCodecLC3FrameDur10000us},
};

std::vector<uint8_t> BroadcastCodecWrapper::GetCodecSpecData() const {
types::LeAudioLtvMap BroadcastCodecWrapper::GetBisCodecSpecData(
    uint8_t bis_idx) const {
  /* For a single channel this will be set at the subgroup lvl. */
  if (source_codec_config.num_channels == 1) return {};

  switch (bis_idx) {
    case 1:
      return types::LeAudioLtvMap(
          {{codec_spec_conf::kLeAudioCodecLC3TypeAudioChannelAllocation,
            UINT32_TO_VEC_UINT8(codec_spec_conf::kLeAudioLocationFrontLeft)}});
    case 2:
      return types::LeAudioLtvMap(
          {{codec_spec_conf::kLeAudioCodecLC3TypeAudioChannelAllocation,
            UINT32_TO_VEC_UINT8(codec_spec_conf::kLeAudioLocationFrontRight)}});
      break;
    default:
      return {};
  }
}

types::LeAudioLtvMap BroadcastCodecWrapper::GetSubgroupCodecSpecData() const {
  LOG_ASSERT(
      sample_rate_to_sampling_freq_map.count(source_codec_config.sample_rate))
      << "Invalid sample_rate";
@@ -252,23 +272,13 @@ std::vector<uint8_t> BroadcastCodecWrapper::GetCodecSpecData() const {
        UINT16_TO_VEC_UINT8(bc);
  }

  uint32_t audio_location;
  switch (source_codec_config.num_channels) {
    case 1:
      audio_location = codec_spec_conf::kLeAudioLocationMonoUnspecified;
      break;
    default:
      audio_location = codec_spec_conf::kLeAudioLocationFrontLeft |
                       codec_spec_conf::kLeAudioLocationFrontRight;
      break;
  if (source_codec_config.num_channels == 1) {
    codec_spec_ltvs
        [codec_spec_conf::kLeAudioCodecLC3TypeAudioChannelAllocation] =
            UINT32_TO_VEC_UINT8(codec_spec_conf::kLeAudioLocationFrontCenter);
  }
  codec_spec_ltvs[codec_spec_conf::kLeAudioCodecLC3TypeAudioChannelAllocation] =
      UINT32_TO_VEC_UINT8(audio_location);

  types::LeAudioLtvMap ltv_map(codec_spec_ltvs);
  std::vector<uint8_t> data(ltv_map.RawPacketSize());
  ltv_map.RawPacket(data.data());
  return data;
  return types::LeAudioLtvMap(codec_spec_ltvs);
}

std::ostream& operator<<(
+4 −1
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@ namespace broadcaster {
static const uint16_t kBroadcastAudioAnnouncementServiceUuid = 0x1852;
static const uint16_t kBasicAudioAnnouncementServiceUuid = 0x1851;

static const uint8_t kBisIndexInvalid = 0;

struct BasicAudioAnnouncementCodecConfig {
  /* 5 octets for the Codec ID */
  uint8_t codec_id;
@@ -101,7 +103,8 @@ struct BroadcastCodecWrapper {
  static const BroadcastCodecWrapper& getCodecConfigForProfile(
      LeAudioBroadcaster::AudioProfile profile);

  std::vector<uint8_t> GetCodecSpecData() const;
  types::LeAudioLtvMap GetSubgroupCodecSpecData() const;
  types::LeAudioLtvMap GetBisCodecSpecData(uint8_t bis_idx) const;

  uint16_t GetMaxSduSizePerChannel() const {
    if (codec_id.coding_format == types::kLeAudioCodingFormatLC3) {
+16 −2
Original line number Diff line number Diff line
@@ -476,8 +476,22 @@ class BroadcastStateMachineImpl : public BroadcastStateMachine {
        /* TODO: Implement HCI command to get the controller delay */
        .controller_delay = 0x00000000,
    };
    if (codec_id.coding_format != le_audio::types::kLeAudioCodingFormatLC3)
      param.codec_conf = sm_config_.codec_wrapper.GetCodecSpecData();
    if (codec_id.coding_format != le_audio::types::kLeAudioCodingFormatLC3) {
      // TODO: Until the proper offloader support is added, pass all the params
      auto const& conn_handles = active_config_->connection_handles;

      auto it =
          std::find(conn_handles.begin(), conn_handles.end(), conn_handle);
      if (it != conn_handles.end()) {
        /* Find BIS index - BIS indices start at 1 */
        auto bis_idx = it - conn_handles.begin() + 1;

        /* Compose subgroup params with BIS params  */
        auto params = sm_config_.codec_wrapper.GetSubgroupCodecSpecData();
        params.Append(sm_config_.codec_wrapper.GetBisCodecSpecData(bis_idx));
        param.codec_conf = params.RawPacket();
      }
    }

    IsoManager::GetInstance()->SetupIsoDataPath(conn_handle, std::move(param));
  }
+10 −8
Original line number Diff line number Diff line
@@ -380,24 +380,26 @@ static BasicAudioAnnouncementData prepareAnnouncement(
  BasicAudioAnnouncementData announcement;

  announcement.presentation_delay = 0x004E20;
  auto const& codec_id = codec_config.GetLeAudioCodecId();

  announcement.subgroup_configs = {{
      .codec_config =
          {
              .codec_id = codec_config.GetLeAudioCodecId().coding_format,
              .vendor_company_id =
                  codec_config.GetLeAudioCodecId().vendor_company_id,
              .vendor_codec_id =
                  codec_config.GetLeAudioCodecId().vendor_codec_id,
              .codec_specific_params = codec_config.GetCodecSpecData(),
              .codec_id = codec_id.coding_format,
              .vendor_company_id = codec_id.vendor_company_id,
              .vendor_codec_id = codec_id.vendor_codec_id,
              .codec_specific_params =
                  codec_config.GetSubgroupCodecSpecData().RawPacket(),
          },
      .metadata = metadata,
      .metadata = std::move(metadata),
      .bis_configs = {},
  }};

  for (uint8_t i = 0; i < codec_config.GetNumChannels(); ++i) {
    announcement.subgroup_configs[0].bis_configs.push_back(
        {.codec_specific_params = {}, .bis_index = i});
        {.codec_specific_params =
             codec_config.GetBisCodecSpecData(i + 1).RawPacket(),
         .bis_index = static_cast<uint8_t>(i + 1)});
  }

  return announcement;