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

Commit fa14757d authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Simplify stream configuration

With this patch, group->stream_conf is modified only when CIS is created
or removed. There is no need to recreated it when getting configuration.

This is a preparation for offloader handling
Bug: 231084798
Sponsor: @siyuanh
Test: atest BluetoothInstrumentationTests
Tag: #feature

Merged-In: Ibfaf95387f15893c7bb6c5c19669695c0a478b5e
Change-Id: Ibfaf95387f15893c7bb6c5c19669695c0a478b5e
(cherry picked from commit cd703c6e)
parent 66cb6df0
Loading
Loading
Loading
Loading
+16 −101
Original line number Diff line number Diff line
@@ -2241,109 +2241,19 @@ class LeAudioClientImpl : public LeAudioClient {
                                           chan_encoded.size());
  }

  struct le_audio::stream_configuration* GetStreamConfigurationByDirection(
      LeAudioDeviceGroup* group, uint8_t direction) {
    struct le_audio::stream_configuration* stream_conf = &group->stream_conf;
    uint32_t sample_freq_hz = 0;
    uint32_t frame_duration_us = 0;
    uint32_t audio_channel_allocation = 0;
    uint16_t octets_per_frame = 0;
    uint16_t codec_frames_blocks_per_sdu = 0;

    LOG(INFO) << __func__ << " group_id: " << group->group_id_;

    /* This contains pair of cis handle and audio location */
    std::vector<std::pair<uint16_t, uint32_t>> streams;

    for (auto* device = group->GetFirstActiveDevice(); device != nullptr;
         device = group->GetNextActiveDevice(device)) {
      auto* ase = device->GetFirstActiveAseByDirection(direction);

      for (; ase != nullptr;
           ase = device->GetNextActiveAseWithSameDirection(ase)) {
        streams.emplace_back(std::make_pair(
            ase->cis_conn_hdl, *ase->codec_config.audio_channel_allocation));
        audio_channel_allocation |= *ase->codec_config.audio_channel_allocation;
        if (sample_freq_hz == 0) {
          sample_freq_hz = ase->codec_config.GetSamplingFrequencyHz();
        } else {
          LOG_ASSERT(sample_freq_hz ==
                     ase->codec_config.GetSamplingFrequencyHz())
              << __func__ << " sample freq mismatch: " << +sample_freq_hz
              << " != " << ase->codec_config.GetSamplingFrequencyHz();
        }

        if (frame_duration_us == 0) {
          frame_duration_us = ase->codec_config.GetFrameDurationUs();
        } else {
          LOG_ASSERT(frame_duration_us ==
                     ase->codec_config.GetFrameDurationUs())
              << __func__ << " frame duration mismatch: " << +frame_duration_us
              << " != " << ase->codec_config.GetFrameDurationUs();
        }

        if (octets_per_frame == 0) {
          octets_per_frame = *ase->codec_config.octets_per_codec_frame;
        } else {
          LOG_ASSERT(octets_per_frame ==
                     ase->codec_config.octets_per_codec_frame)
              << __func__ << " octets per frame mismatch: " << +octets_per_frame
              << " != " << *ase->codec_config.octets_per_codec_frame;
  const struct le_audio::stream_configuration* GetStreamSinkConfiguration(
      LeAudioDeviceGroup* group) {
    const struct le_audio::stream_configuration* stream_conf =
        &group->stream_conf;
    LOG_INFO("group_id: %d", group->group_id_);
    if (stream_conf->sink_streams.size() == 0) {
      return nullptr;
    }

        if (codec_frames_blocks_per_sdu == 0) {
          codec_frames_blocks_per_sdu =
              *ase->codec_config.codec_frames_blocks_per_sdu;
        } else {
          LOG_ASSERT(codec_frames_blocks_per_sdu ==
                     ase->codec_config.codec_frames_blocks_per_sdu)
              << __func__ << " codec_frames_blocks_per_sdu: "
              << +codec_frames_blocks_per_sdu
              << " != " << *ase->codec_config.codec_frames_blocks_per_sdu;
        }

        LOG(INFO) << __func__ << " Added CIS: " << +ase->cis_conn_hdl
                  << " to stream. Allocation: "
                  << +(*ase->codec_config.audio_channel_allocation)
                  << " sample_freq: " << +sample_freq_hz
                  << " frame_duration: " << +frame_duration_us
                  << " octects per frame: " << +octets_per_frame
                  << " codec_frame_blocks_per_sdu: "
                  << +codec_frames_blocks_per_sdu;
      }
    }

    if (streams.empty()) return nullptr;

    if (direction == le_audio::types::kLeAudioDirectionSource) {
      stream_conf->source_streams = std::move(streams);
      stream_conf->source_sample_frequency_hz = sample_freq_hz;
      stream_conf->source_frame_duration_us = frame_duration_us;
      stream_conf->source_audio_channel_allocation = audio_channel_allocation;
      stream_conf->source_octets_per_codec_frame = octets_per_frame;
      stream_conf->source_codec_frames_blocks_per_sdu =
          codec_frames_blocks_per_sdu;
    } else if (direction == le_audio::types::kLeAudioDirectionSink) {
      stream_conf->sink_streams = std::move(streams);
      stream_conf->sink_sample_frequency_hz = sample_freq_hz;
      stream_conf->sink_frame_duration_us = frame_duration_us;
      stream_conf->sink_audio_channel_allocation = audio_channel_allocation;
      stream_conf->sink_octets_per_codec_frame = octets_per_frame;
      stream_conf->sink_codec_frames_blocks_per_sdu =
          codec_frames_blocks_per_sdu;
    }

    LOG(INFO) << __func__ << " configuration: " << stream_conf->conf->name;

    LOG_INFO("configuration: %s", stream_conf->conf->name.c_str());
    return stream_conf;
  }

  struct le_audio::stream_configuration* GetStreamSinkConfiguration(
      LeAudioDeviceGroup* group) {
    return GetStreamConfigurationByDirection(
        group, le_audio::types::kLeAudioDirectionSink);
  }

  void OnAudioDataReady(const std::vector<uint8_t>& data) {
    if ((active_group_id_ == bluetooth::groups::kGroupUnknown) ||
        (audio_sender_state_ != AudioState::STARTED))
@@ -2657,10 +2567,15 @@ class LeAudioClientImpl : public LeAudioClient {
    return true;
  }

  struct le_audio::stream_configuration* GetStreamSourceConfiguration(
  const struct le_audio::stream_configuration* GetStreamSourceConfiguration(
      LeAudioDeviceGroup* group) {
    return GetStreamConfigurationByDirection(
        group, le_audio::types::kLeAudioDirectionSource);
    const struct le_audio::stream_configuration* stream_conf =
        &group->stream_conf;
    if (stream_conf->source_streams.size() == 0) {
      return nullptr;
    }
    LOG_INFO("configuration: %s", stream_conf->conf->name.c_str());
    return stream_conf;
  }

  void StartReceivingAudio(int group_id) {
+26 −0
Original line number Diff line number Diff line
@@ -106,9 +106,35 @@ 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_audio_channel_allocation = 0;
  stream_conf.sink_num_of_channels = 0;
  stream_conf.sink_num_of_devices = 0;
  stream_conf.sink_sample_frequency_hz = 0;
  stream_conf.sink_codec_frames_blocks_per_sdu = 0;
  stream_conf.sink_octets_per_codec_frame = 0;
  stream_conf.sink_frame_duration_us = 0;
}

void LeAudioDeviceGroup::ClearSourcesFromConfiguration(void) {
  LOG_INFO("Group %p, group_id %d", this, group_id_);
  stream_conf.source_streams.clear();
  stream_conf.source_audio_channel_allocation = 0;
  stream_conf.source_num_of_channels = 0;
  stream_conf.source_num_of_devices = 0;
  stream_conf.source_sample_frequency_hz = 0;
  stream_conf.source_codec_frames_blocks_per_sdu = 0;
  stream_conf.source_octets_per_codec_frame = 0;
  stream_conf.source_frame_duration_us = 0;
}

void LeAudioDeviceGroup::CigClearCis(void) {
  LOG_INFO("group_id: %d", group_id_);
  cises_.clear();
  ClearSinksFromConfiguration();
  ClearSourcesFromConfiguration();
}

void LeAudioDeviceGroup::Cleanup(void) {
+2 −0
Original line number Diff line number Diff line
@@ -223,6 +223,8 @@ class LeAudioDeviceGroup {
  bool Activate(types::LeAudioContextType context_type);
  void Deactivate(void);
  void CigClearCis(void);
  void ClearSinksFromConfiguration(void);
  void ClearSourcesFromConfiguration(void);
  void Cleanup(void);
  LeAudioDevice* GetFirstDevice(void);
  LeAudioDevice* GetFirstDeviceWithActiveContext(
+73 −0
Original line number Diff line number Diff line
@@ -772,6 +772,42 @@ class UnicastTestNoInit : public Test {
                  stream_conf->source_num_of_devices++;
                  stream_conf->source_num_of_channels +=
                      ase.codec_config.channel_count;
                  stream_conf->source_audio_channel_allocation |=
                      *ase.codec_config.audio_channel_allocation;

                  if (stream_conf->source_sample_frequency_hz == 0) {
                    stream_conf->source_sample_frequency_hz =
                        ase.codec_config.GetSamplingFrequencyHz();
                  } else {
                    ASSERT_LOG(stream_conf->source_sample_frequency_hz ==
                                   ase.codec_config.GetSamplingFrequencyHz(),
                               "sample freq mismatch: %d!=%d",
                               stream_conf->source_sample_frequency_hz,
                               ase.codec_config.GetSamplingFrequencyHz());
                  }

                  if (stream_conf->source_octets_per_codec_frame == 0) {
                    stream_conf->source_octets_per_codec_frame =
                        *ase.codec_config.octets_per_codec_frame;
                  } else {
                    ASSERT_LOG(stream_conf->source_octets_per_codec_frame ==
                                   *ase.codec_config.octets_per_codec_frame,
                               "octets per frame mismatch: %d!=%d",
                               stream_conf->source_octets_per_codec_frame,
                               *ase.codec_config.octets_per_codec_frame);
                  }

                  if (stream_conf->source_codec_frames_blocks_per_sdu == 0) {
                    stream_conf->source_codec_frames_blocks_per_sdu =
                        *ase.codec_config.codec_frames_blocks_per_sdu;
                  } else {
                    ASSERT_LOG(
                        stream_conf->source_codec_frames_blocks_per_sdu ==
                            *ase.codec_config.codec_frames_blocks_per_sdu,
                        "codec_frames_blocks_per_sdu: %d!=%d",
                        stream_conf->source_codec_frames_blocks_per_sdu,
                        *ase.codec_config.codec_frames_blocks_per_sdu);
                  }

                  LOG_INFO(
                      " Added Source Stream Configuration. CIS Connection "
@@ -800,6 +836,43 @@ class UnicastTestNoInit : public Test {
                  stream_conf->sink_num_of_channels +=
                      ase.codec_config.channel_count;

                  stream_conf->sink_audio_channel_allocation |=
                      *ase.codec_config.audio_channel_allocation;

                  if (stream_conf->sink_sample_frequency_hz == 0) {
                    stream_conf->sink_sample_frequency_hz =
                        ase.codec_config.GetSamplingFrequencyHz();
                  } else {
                    ASSERT_LOG(stream_conf->sink_sample_frequency_hz ==
                                   ase.codec_config.GetSamplingFrequencyHz(),
                               "sample freq mismatch: %d!=%d",
                               stream_conf->sink_sample_frequency_hz,
                               ase.codec_config.GetSamplingFrequencyHz());
                  }

                  if (stream_conf->sink_octets_per_codec_frame == 0) {
                    stream_conf->sink_octets_per_codec_frame =
                        *ase.codec_config.octets_per_codec_frame;
                  } else {
                    ASSERT_LOG(stream_conf->sink_octets_per_codec_frame ==
                                   *ase.codec_config.octets_per_codec_frame,
                               "octets per frame mismatch: %d!=%d",
                               stream_conf->sink_octets_per_codec_frame,
                               *ase.codec_config.octets_per_codec_frame);
                  }

                  if (stream_conf->sink_codec_frames_blocks_per_sdu == 0) {
                    stream_conf->sink_codec_frames_blocks_per_sdu =
                        *ase.codec_config.codec_frames_blocks_per_sdu;
                  } else {
                    ASSERT_LOG(
                        stream_conf->sink_codec_frames_blocks_per_sdu ==
                            *ase.codec_config.codec_frames_blocks_per_sdu,
                        "codec_frames_blocks_per_sdu: %d!=%d",
                        stream_conf->sink_codec_frames_blocks_per_sdu,
                        *ase.codec_config.codec_frames_blocks_per_sdu);
                  }

                  LOG_INFO(
                      " Added Sink Stream Configuration. CIS Connection "
                      "Handle: %d"
+140 −49
Original line number Diff line number Diff line
@@ -448,52 +448,7 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
      return;
    }

    uint16_t cis_conn_hdl = ase->cis_conn_hdl;
    auto* stream_conf = &group->stream_conf;
    if (ase->direction == le_audio::types::kLeAudioDirectionSink) {
      auto iter = std::find_if(
          stream_conf->sink_streams.begin(), stream_conf->sink_streams.end(),
          [cis_conn_hdl](auto& pair) { return cis_conn_hdl == pair.first; });

      if (iter == stream_conf->sink_streams.end()) {
        stream_conf->sink_streams.emplace_back(std::make_pair(
            ase->cis_conn_hdl, *ase->codec_config.audio_channel_allocation));

        stream_conf->sink_num_of_devices++;
        stream_conf->sink_num_of_channels += ase->codec_config.channel_count;

        LOG_INFO(
            " Added Sink Stream Configuration. CIS Connection Handle: %d"
            ", Audio Channel Allocation: %d"
            ", Sink Number Of Devices: %d"
            ", Sink Number Of Channels: %d",
            +ase->cis_conn_hdl, +(*ase->codec_config.audio_channel_allocation),
            +stream_conf->sink_num_of_devices,
            +stream_conf->sink_num_of_channels);
      }
    } else {
      auto iter = std::find_if(
          stream_conf->source_streams.begin(),
          stream_conf->source_streams.end(),
          [cis_conn_hdl](auto& pair) { return cis_conn_hdl == pair.first; });

      if (iter == stream_conf->source_streams.end()) {
        stream_conf->source_streams.emplace_back(std::make_pair(
            ase->cis_conn_hdl, *ase->codec_config.audio_channel_allocation));

        stream_conf->source_num_of_devices++;
        stream_conf->source_num_of_channels += ase->codec_config.channel_count;

        LOG_INFO(
            " Added Source Stream Configuration. CIS Connection Handle: %d"
            ", Audio Channel Allocation: %d"
            ", Source Number Of Devices: %d"
            ", Source Number Of Channels: %d",
            +ase->cis_conn_hdl, +(*ase->codec_config.audio_channel_allocation),
            +stream_conf->source_num_of_devices,
            +stream_conf->source_num_of_channels);
      }
    }
    AddCisToStreamConfiguration(group, ase);

    ase = leAudioDevice->GetFirstActiveAseByDataPathState(
        AudioStreamDataPathState::CIS_ESTABLISHED);
@@ -620,8 +575,6 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
      return;
    }

    RemoveCisFromStreamConfiguration(group, leAudioDevice, 0);

    /* mark ASEs as not used. */
    leAudioDevice->DeactivateAllAses();

@@ -900,12 +853,139 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
        INT_TO_PTR(group->group_id_));
  }

  void AddCisToStreamConfiguration(LeAudioDeviceGroup* group,
                                   const struct ase* ase) {
    uint16_t cis_conn_hdl = ase->cis_conn_hdl;
    LOG_INFO("Adding cis handle 0x%04x (%s) to stream list", cis_conn_hdl,
             ase->direction == le_audio::types::kLeAudioDirectionSink
                 ? "sink"
                 : "source");
    auto* stream_conf = &group->stream_conf;
    if (ase->direction == le_audio::types::kLeAudioDirectionSink) {
      auto iter = std::find_if(
          stream_conf->sink_streams.begin(), stream_conf->sink_streams.end(),
          [cis_conn_hdl](auto& pair) { return cis_conn_hdl == pair.first; });

      ASSERT_LOG(iter == stream_conf->sink_streams.end(),
                 "Stream is already there 0x%04x", cis_conn_hdl);

      stream_conf->sink_streams.emplace_back(std::make_pair(
          ase->cis_conn_hdl, *ase->codec_config.audio_channel_allocation));

      stream_conf->sink_num_of_devices++;
      stream_conf->sink_num_of_channels += ase->codec_config.channel_count;
      stream_conf->sink_audio_channel_allocation |=
          *ase->codec_config.audio_channel_allocation;

      if (stream_conf->sink_sample_frequency_hz == 0) {
        stream_conf->sink_sample_frequency_hz =
            ase->codec_config.GetSamplingFrequencyHz();
      } else {
        ASSERT_LOG(stream_conf->sink_sample_frequency_hz ==
                       ase->codec_config.GetSamplingFrequencyHz(),
                   "sample freq mismatch: %d!=%d",
                   stream_conf->sink_sample_frequency_hz,
                   ase->codec_config.GetSamplingFrequencyHz());
      }

      if (stream_conf->sink_octets_per_codec_frame == 0) {
        stream_conf->sink_octets_per_codec_frame =
            *ase->codec_config.octets_per_codec_frame;
      } else {
        ASSERT_LOG(stream_conf->sink_octets_per_codec_frame ==
                       *ase->codec_config.octets_per_codec_frame,
                   "octets per frame mismatch: %d!=%d",
                   stream_conf->sink_octets_per_codec_frame,
                   *ase->codec_config.octets_per_codec_frame);
      }

      if (stream_conf->sink_codec_frames_blocks_per_sdu == 0) {
        stream_conf->sink_codec_frames_blocks_per_sdu =
            *ase->codec_config.codec_frames_blocks_per_sdu;
      } else {
        ASSERT_LOG(stream_conf->sink_codec_frames_blocks_per_sdu ==
                       *ase->codec_config.codec_frames_blocks_per_sdu,
                   "codec_frames_blocks_per_sdu: %d!=%d",
                   stream_conf->sink_codec_frames_blocks_per_sdu,
                   *ase->codec_config.codec_frames_blocks_per_sdu);
      }

      LOG_INFO(
          " Added Sink Stream Configuration. CIS Connection Handle: %d"
          ", Audio Channel Allocation: %d"
          ", Sink Number Of Devices: %d"
          ", Sink Number Of Channels: %d",
          ase->cis_conn_hdl, *ase->codec_config.audio_channel_allocation,
          stream_conf->sink_num_of_devices, stream_conf->sink_num_of_channels);

    } else {
      /* Source case */
      auto iter = std::find_if(
          stream_conf->source_streams.begin(),
          stream_conf->source_streams.end(),
          [cis_conn_hdl](auto& pair) { return cis_conn_hdl == pair.first; });

      ASSERT_LOG(iter == stream_conf->source_streams.end(),
                 "Stream is already there 0x%04x", cis_conn_hdl);

      stream_conf->source_streams.emplace_back(std::make_pair(
          ase->cis_conn_hdl, *ase->codec_config.audio_channel_allocation));

      stream_conf->source_num_of_devices++;
      stream_conf->source_num_of_channels += ase->codec_config.channel_count;
      stream_conf->source_audio_channel_allocation |=
          *ase->codec_config.audio_channel_allocation;

      if (stream_conf->source_sample_frequency_hz == 0) {
        stream_conf->source_sample_frequency_hz =
            ase->codec_config.GetSamplingFrequencyHz();
      } else {
        ASSERT_LOG(stream_conf->source_sample_frequency_hz ==
                       ase->codec_config.GetSamplingFrequencyHz(),
                   "sample freq mismatch: %d!=%d",
                   stream_conf->source_sample_frequency_hz,
                   ase->codec_config.GetSamplingFrequencyHz());
      }

      if (stream_conf->source_octets_per_codec_frame == 0) {
        stream_conf->source_octets_per_codec_frame =
            *ase->codec_config.octets_per_codec_frame;
      } else {
        ASSERT_LOG(stream_conf->source_octets_per_codec_frame ==
                       *ase->codec_config.octets_per_codec_frame,
                   "octets per frame mismatch: %d!=%d",
                   stream_conf->source_octets_per_codec_frame,
                   *ase->codec_config.octets_per_codec_frame);
      }

      if (stream_conf->source_codec_frames_blocks_per_sdu == 0) {
        stream_conf->source_codec_frames_blocks_per_sdu =
            *ase->codec_config.codec_frames_blocks_per_sdu;
      } else {
        ASSERT_LOG(stream_conf->source_codec_frames_blocks_per_sdu ==
                       *ase->codec_config.codec_frames_blocks_per_sdu,
                   "codec_frames_blocks_per_sdu: %d!=%d",
                   stream_conf->source_codec_frames_blocks_per_sdu,
                   *ase->codec_config.codec_frames_blocks_per_sdu);
      }

      LOG_INFO(
          " Added Source Stream Configuration. CIS Connection Handle: %d"
          ", Audio Channel Allocation: %d"
          ", Source Number Of Devices: %d"
          ", Source Number Of Channels: %d",
          ase->cis_conn_hdl, *ase->codec_config.audio_channel_allocation,
          stream_conf->source_num_of_devices,
          stream_conf->source_num_of_channels);
    }
  }

  void RemoveCisFromStreamConfiguration(LeAudioDeviceGroup* group,
                                        LeAudioDevice* leAudioDevice,
                                        uint16_t cis_conn_hdl) {
    auto* stream_conf = &group->stream_conf;

    LOG_INFO(" CIS Connection Handle: %d", +cis_conn_hdl);
    LOG_INFO(" CIS Connection Handle: %d", cis_conn_hdl);

    if (!stream_conf->sink_streams.empty() ||
        !stream_conf->source_streams.empty()) {
@@ -923,6 +1003,7 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
                  stream_conf->sink_num_of_devices--;
                  stream_conf->sink_num_of_channels -=
                      ases_pair.sink->codec_config.channel_count;
                  stream_conf->sink_audio_channel_allocation &= ~pair.second;
                }
                return (ases_pair.sink && cis_conn_hdl == pair.first);
              }),
@@ -942,6 +1023,7 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
                  stream_conf->source_num_of_devices--;
                  stream_conf->source_num_of_channels -=
                      ases_pair.source->codec_config.channel_count;
                  stream_conf->source_audio_channel_allocation &= ~pair.second;
                }
                return (ases_pair.source && cis_conn_hdl == pair.first);
              }),
@@ -956,6 +1038,15 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
          stream_conf->source_num_of_devices,
          stream_conf->source_num_of_channels);
    }

    if (stream_conf->sink_num_of_channels == 0) {
      group->ClearSinksFromConfiguration();
    }

    if (stream_conf->source_num_of_channels == 0) {
      group->ClearSourcesFromConfiguration();
    }

    group->CigUnassignCis(leAudioDevice);
  }