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

Commit 7c6c38b3 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Automerger Merge Worker
Browse files

leaudio: Improve offloader behaviour am: 9275204c am: b97a2d4f

parents 43dac79c b97a2d4f
Loading
Loading
Loading
Loading
+42 −20
Original line number Diff line number Diff line
@@ -2551,13 +2551,6 @@ class LeAudioClientImpl : public LeAudioClient {
          lc3_setup_encoder(dt_us, sr_hz, af_hz, lc3_encoder_left_mem);
      lc3_encoder_right =
          lc3_setup_encoder(dt_us, sr_hz, af_hz, lc3_encoder_right_mem);

    } else if (CodecManager::GetInstance()->GetCodecLocation() ==
               le_audio::types::CodecLocation::ADSP) {
      CodecManager::GetInstance()->UpdateActiveSourceAudioConfig(
          *stream_conf, remote_delay_ms,
          std::bind(&LeAudioUnicastClientAudioSource::UpdateAudioConfigToHal,
                    leAudioClientAudioSource, std::placeholders::_1));
    }

    leAudioClientAudioSource->UpdateRemoteDelay(remote_delay_ms);
@@ -2617,14 +2610,7 @@ class LeAudioClientImpl : public LeAudioClient {
          lc3_setup_decoder(dt_us, sr_hz, af_hz, lc3_decoder_left_mem);
      lc3_decoder_right =
          lc3_setup_decoder(dt_us, sr_hz, af_hz, lc3_decoder_right_mem);
    } else if (CodecManager::GetInstance()->GetCodecLocation() ==
               le_audio::types::CodecLocation::ADSP) {
      CodecManager::GetInstance()->UpdateActiveSinkAudioConfig(
          *stream_conf, remote_delay_ms,
          std::bind(&LeAudioUnicastClientAudioSink::UpdateAudioConfigToHal,
                    leAudioClientAudioSink, std::placeholders::_1));
    }

    leAudioClientAudioSink->UpdateRemoteDelay(remote_delay_ms);
    leAudioClientAudioSink->ConfirmStreamingRequest();
    audio_receiver_state_ = AudioState::STARTED;
@@ -3515,16 +3501,52 @@ class LeAudioClientImpl : public LeAudioClient {
    }
  }

  void updateOffloaderIfNeeded(LeAudioDeviceGroup* group) {
    if (CodecManager::GetInstance()->GetCodecLocation() !=
        le_audio::types::CodecLocation::ADSP) {
      return;
    }

    LOG_INFO("Group %p, group_id %d", group, group->group_id_);

    const auto* stream_conf = &group->stream_conf;

    if (stream_conf->sink_offloader_changed) {
      LOG_INFO("Update sink offloader streams");
      uint16_t remote_delay_ms =
          group->GetRemoteDelay(le_audio::types::kLeAudioDirectionSink);
      CodecManager::GetInstance()->UpdateActiveSourceAudioConfig(
          *stream_conf, remote_delay_ms,
          std::bind(&LeAudioUnicastClientAudioSource::UpdateAudioConfigToHal,
                    leAudioClientAudioSource, std::placeholders::_1));
      group->StreamOffloaderUpdated(le_audio::types::kLeAudioDirectionSink);
    }

    if (stream_conf->source_offloader_changed) {
      LOG_INFO("Update source offloader streams");
      uint16_t remote_delay_ms =
          group->GetRemoteDelay(le_audio::types::kLeAudioDirectionSource);
      CodecManager::GetInstance()->UpdateActiveSinkAudioConfig(
          *stream_conf, remote_delay_ms,
          std::bind(&LeAudioUnicastClientAudioSink::UpdateAudioConfigToHal,
                    leAudioClientAudioSink, std::placeholders::_1));
      group->StreamOffloaderUpdated(le_audio::types::kLeAudioDirectionSource);
    }
  }

  void StatusReportCb(int group_id, GroupStreamStatus status) {
    LOG(INFO) << __func__ << "status: " << static_cast<int>(status)
              << " audio_sender_state_: " << audio_sender_state_
              << " audio_receiver_state_: " << audio_receiver_state_;
    LOG_INFO("status: %d , audio_sender_state %s, audio_receiver_state %s",
             static_cast<int>(status),
             bluetooth::common::ToString(audio_sender_state_).c_str(),
             bluetooth::common::ToString(audio_receiver_state_).c_str());
    LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
    switch (status) {
      case GroupStreamStatus::STREAMING:
        LOG_ASSERT(group_id == active_group_id_)
            << __func__ << " invalid group id " << group_id
            << " active_group_id_ " << active_group_id_;
        ASSERT_LOG(group_id == active_group_id_, "invalid group id %d!=%d",
                   group_id, active_group_id_);

        updateOffloaderIfNeeded(group);

        if (audio_sender_state_ == AudioState::READY_TO_START)
          StartSendingAudio(group_id);
        if (audio_receiver_state_ == AudioState::READY_TO_START)
+2 −2
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ struct codec_manager_impl {
          update_receiver) {
    if (stream_conf.sink_streams.empty()) return;

    sink_config.stream_map = std::move(stream_conf.sink_streams);
    sink_config.stream_map = std::move(stream_conf.sink_offloader_streams);
    // TODO: set the default value 16 for now, would change it if we support
    // mode bits_per_sample
    sink_config.bits_per_sample = 16;
@@ -107,7 +107,7 @@ struct codec_manager_impl {
          update_receiver) {
    if (stream_conf.source_streams.empty()) return;

    source_config.stream_map = std::move(stream_conf.source_streams);
    source_config.stream_map = std::move(stream_conf.source_offloader_streams);
    // TODO: set the default value 16 for now, would change it if we support
    // mode bits_per_sample
    source_config.bits_per_sample = 16;
+104 −0
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ int LeAudioDeviceGroup::NumOfConnected(types::LeAudioContextType context_type) {
void LeAudioDeviceGroup::ClearSinksFromConfiguration(void) {
  LOG_INFO("Group %p, group_id %d", this, group_id_);
  stream_conf.sink_streams.clear();
  stream_conf.sink_offloader_streams.clear();
  stream_conf.sink_audio_channel_allocation = 0;
  stream_conf.sink_num_of_channels = 0;
  stream_conf.sink_num_of_devices = 0;
@@ -121,6 +122,7 @@ void LeAudioDeviceGroup::ClearSinksFromConfiguration(void) {
void LeAudioDeviceGroup::ClearSourcesFromConfiguration(void) {
  LOG_INFO("Group %p, group_id %d", this, group_id_);
  stream_conf.source_streams.clear();
  stream_conf.source_offloader_streams.clear();
  stream_conf.source_audio_channel_allocation = 0;
  stream_conf.source_num_of_channels = 0;
  stream_conf.source_num_of_devices = 0;
@@ -1618,6 +1620,108 @@ bool LeAudioDeviceGroup::IsMetadataChanged(
  return false;
}

void LeAudioDeviceGroup::StreamOffloaderUpdated(uint8_t direction) {
  if (direction == le_audio::types::kLeAudioDirectionSource) {
    stream_conf.source_offloader_changed = false;
  } else {
    stream_conf.sink_offloader_changed = false;
  }
}

void LeAudioDeviceGroup::CreateStreamVectorForOffloader(uint8_t direction) {
  if (CodecManager::GetInstance()->GetCodecLocation() !=
      le_audio::types::CodecLocation::ADSP) {
    return;
  }

  CisType cis_type;
  std::vector<std::pair<uint16_t, uint32_t>>* streams;
  std::vector<std::pair<uint16_t, uint32_t>>* offloader_streams;
  std::string tag;
  uint32_t available_allocations = 0;
  bool* changed_flag;
  if (direction == le_audio::types::kLeAudioDirectionSource) {
    changed_flag = &stream_conf.source_offloader_changed;
    cis_type = CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE;
    streams = &stream_conf.source_streams;
    offloader_streams = &stream_conf.source_offloader_streams;
    tag = "Source";
    available_allocations = AdjustAllocationForOffloader(
        stream_conf.source_audio_channel_allocation);
  } else {
    changed_flag = &stream_conf.sink_offloader_changed;
    cis_type = CisType::CIS_TYPE_UNIDIRECTIONAL_SINK;
    streams = &stream_conf.sink_streams;
    offloader_streams = &stream_conf.sink_offloader_streams;
    tag = "Sink";
    available_allocations =
        AdjustAllocationForOffloader(stream_conf.sink_audio_channel_allocation);
  }

  if (available_allocations == 0) {
    LOG_ERROR("There is no CIS connected");
    return;
  }

  if (offloader_streams->size() > 0) {
    /* We are here because of the CIS modification during streaming.
     * this makes sense only when downmixing is enabled so we can notify
     * offloader about connected / disconnected CISes. If downmixing is disabled
     * then there is not need to notify offloader as it has all the informations
     * already */
    if (!downmix_fallback_) {
      LOG_INFO("Downmixing disabled - nothing to do");
      return;
    }
  }

  offloader_streams->clear();
  *changed_flag = true;

  bool not_all_cises_connected = false;
  if (available_allocations != codec_spec_conf::kLeAudioLocationStereo) {
    not_all_cises_connected = true;
  }

  /* Note: For the offloader case we simplify allocation to only Left and Right.
   * If we need 2 CISes and only one is connected, the connected one will have
   * allocation set to stereo (left | right) and other one will have allocation
   * set to 0. Offloader in this case shall mix left and right and send it on
   * connected CIS. If there is only single CIS with stereo allocation, it means
   * that peer device support channel count 2 and offloader shall send two
   * channels in the single CIS.
   */

  for (auto& cis_entry : cises_) {
    if ((cis_entry.type == CisType::CIS_TYPE_BIDIRECTIONAL ||
         cis_entry.type == cis_type) &&
        cis_entry.conn_handle != 0) {
      uint32_t allocation = 0;
      for (const auto& s : *streams) {
        if (s.first == cis_entry.conn_handle) {
          allocation = AdjustAllocationForOffloader(s.second);
          if (not_all_cises_connected && downmix_fallback_) {
            /* Tell offloader to mix on this CIS.*/
            allocation = codec_spec_conf::kLeAudioLocationStereo;
          }
          break;
        }
      }

      if (allocation == 0 && !downmix_fallback_) {
        /* Take missing allocation for that one .*/
        allocation =
            codec_spec_conf::kLeAudioLocationStereo & ~available_allocations;
      }

      LOG_INFO("%s: Cis handle 0x%04x, allocation  0x%08x", tag.c_str(),
               cis_entry.conn_handle, allocation);
      offloader_streams->emplace_back(
          std::make_pair(cis_entry.conn_handle, allocation));
    }
  }
}

types::LeAudioContextType LeAudioDeviceGroup::GetCurrentContextType(void) {
  return active_context_type_;
}
+9 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include "gatt_api.h"
#include "le_audio_types.h"
#include "osi/include/alarm.h"
#include "osi/include/properties.h"
#include "raw_address.h"

namespace le_audio {
@@ -210,7 +211,9 @@ class LeAudioDeviceGroup {
        pending_update_available_contexts_(std::nullopt),
        target_state_(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE),
        current_state_(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE),
        context_type_(types::LeAudioContextType::UNINITIALIZED) {}
        context_type_(types::LeAudioContextType::UNINITIALIZED) {
    downmix_fallback_ = osi_property_get_bool(kDownmixFallback, false);
  }
  ~LeAudioDeviceGroup(void);

  void AddNode(const std::shared_ptr<LeAudioDevice>& leAudioDevice);
@@ -286,6 +289,8 @@ class LeAudioDeviceGroup {
  bool IsContextSupported(types::LeAudioContextType group_context_type);
  bool IsMetadataChanged(types::LeAudioContextType group_context_type,
                         int ccid);
  void CreateStreamVectorForOffloader(uint8_t direction);
  void StreamOffloaderUpdated(uint8_t direction);

  inline types::AseState GetState(void) const { return current_state_; }
  void SetState(types::AseState state) {
@@ -336,6 +341,9 @@ class LeAudioDeviceGroup {
           const set_configurations::AudioSetConfiguration*>
      active_context_to_configuration_map;

  static constexpr char kDownmixFallback[] =
      "persist.bluetooth.leaudio.offloader.downmix_fallback";
  bool downmix_fallback_;
  types::AseState target_state_;
  types::AseState current_state_;
  types::LeAudioContextType context_type_;
+15 −0
Original line number Diff line number Diff line
@@ -525,6 +525,21 @@ uint8_t GetMaxCodecFramesPerSduFromPac(const acs_ac_record* pac) {
  return 1;
}

uint32_t AdjustAllocationForOffloader(uint32_t allocation) {
  if ((allocation & codec_spec_conf::kLeAudioLocationAnyLeft) &&
      (allocation & codec_spec_conf::kLeAudioLocationAnyRight)) {
    return codec_spec_conf::kLeAudioLocationStereo;
  }
  if (allocation & codec_spec_conf::kLeAudioLocationAnyLeft) {
    return codec_spec_conf::kLeAudioLocationFrontLeft;
  }

  if (allocation & codec_spec_conf::kLeAudioLocationAnyRight) {
    return codec_spec_conf::kLeAudioLocationFrontRight;
  }
  return 0;
}

namespace types {
std::ostream& operator<<(std::ostream& os, const types::CigState& state) {
  static const char* char_value_[4] = {"NONE", "CREATING", "CREATED",
Loading