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

Commit 47bdf87b authored by Jakub Pawłowski's avatar Jakub Pawłowski Committed by Automerger Merge Worker
Browse files

Merge "LE Audio stereo recording" am: c844ad64 am: 558cd456

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/2007194

Change-Id: I342209b92d2061e733ed285888dff86a38080447
parents 610dad16 558cd456
Loading
Loading
Loading
Loading
+186 −29
Original line number Original line Diff line number Diff line
@@ -174,8 +174,10 @@ class LeAudioClientImpl : public LeAudioClient {
        current_sink_codec_config({0, 0, 0, 0}),
        current_sink_codec_config({0, 0, 0, 0}),
        lc3_encoder_left_mem(nullptr),
        lc3_encoder_left_mem(nullptr),
        lc3_encoder_right_mem(nullptr),
        lc3_encoder_right_mem(nullptr),
        lc3_decoder_mem(nullptr),
        lc3_decoder_left_mem(nullptr),
        lc3_decoder(nullptr),
        lc3_decoder_right_mem(nullptr),
        lc3_decoder_left(nullptr),
        lc3_decoder_right(nullptr),
        audio_source_instance_(nullptr),
        audio_source_instance_(nullptr),
        audio_sink_instance_(nullptr),
        audio_sink_instance_(nullptr),
        suspend_timeout_(alarm_new("LeAudioSuspendTimeout")) {
        suspend_timeout_(alarm_new("LeAudioSuspendTimeout")) {
@@ -2120,7 +2122,6 @@ class LeAudioClientImpl : public LeAudioClient {
                     uint32_t timestamp) {
                     uint32_t timestamp) {
    /* Get only one channel for MONO microphone */
    /* Get only one channel for MONO microphone */
    /* Gather data for channel */
    /* Gather data for channel */

    if ((active_group_id_ == bluetooth::groups::kGroupUnknown) ||
    if ((active_group_id_ == bluetooth::groups::kGroupUnknown) ||
        (audio_sender_state_ != AudioState::STARTED))
        (audio_sender_state_ != AudioState::STARTED))
      return;
      return;
@@ -2133,17 +2134,31 @@ class LeAudioClientImpl : public LeAudioClient {


    auto stream_conf = group->stream_conf;
    auto stream_conf = group->stream_conf;


    uint16_t required_for_channel_byte_count =
    uint16_t left_cis_handle = 0;
        stream_conf.source_octets_per_codec_frame;
    uint16_t right_cis_handle = 0;
    size_t required_byte_count = current_sink_codec_config.num_channels *
    for (auto [cis_handle, audio_location] : stream_conf.source_streams) {
                                 required_for_channel_byte_count;
      if (audio_location & le_audio::codec_spec_conf::kLeAudioLocationAnyLeft) {
        left_cis_handle = cis_handle;
      }
      if (audio_location &
          le_audio::codec_spec_conf::kLeAudioLocationAnyRight) {
        right_cis_handle = cis_handle;
      }
    }


    if (required_byte_count != size) {
    bool is_left = true;
      LOG(ERROR) << "Insufficient data for decoding and send, required: "
    if (cis_conn_hdl == left_cis_handle) {
                 << int(required_byte_count) << ", received: " << int(size);
      is_left = true;
    } else if (cis_conn_hdl == right_cis_handle) {
      is_left = false;
    } else {
      LOG_ERROR("Received data for unknown handle: %04x", cis_conn_hdl);
      return;
      return;
    }
    }


    uint16_t required_for_channel_byte_count =
        stream_conf.source_octets_per_codec_frame;

    int dt_us = current_sink_codec_config.data_interval_us;
    int dt_us = current_sink_codec_config.data_interval_us;
    int af_hz = audio_framework_sink_config.sample_rate;
    int af_hz = audio_framework_sink_config.sample_rate;


@@ -2165,19 +2180,146 @@ class LeAudioClientImpl : public LeAudioClient {


    std::vector<int16_t> pcm_data_decoded(pcm_size, 0);
    std::vector<int16_t> pcm_data_decoded(pcm_size, 0);


    auto err = lc3_decode(lc3_decoder, data, size, pcm_data_decoded.data(),
    int err = 0;

    if (required_for_channel_byte_count != size) {
      LOG(INFO) << "Insufficient data for decoding and send, required: "
                << int(required_for_channel_byte_count)
                << ", received: " << int(size) << ", will do PLC";
      size = 0;
      data = nullptr;
    }

    lc3_decoder_t decoder_to_use =
        is_left ? lc3_decoder_left : lc3_decoder_right;

    err = lc3_decode(decoder_to_use, data, size, pcm_data_decoded.data(),
                     1 /* pitch */);
                     1 /* pitch */);


    /* TODO: How handle failing decoding ? */
    if (err < 0) {
    if (err < 0) {
      LOG(ERROR) << " error while decoding error code: "
      LOG(ERROR) << " bad decoding parameters: " << static_cast<int>(err);
                 << static_cast<int>(err);
      return;
    }

    /* AF == Audio Framework */
    bool af_is_stereo = (audio_framework_sink_config.num_channels == 2);

    if (!left_cis_handle || !right_cis_handle) {
      /* mono or just one device connected */
      SendAudioDataToAF(false /* bt_got_stereo */, af_is_stereo,
                        &pcm_data_decoded, nullptr);
      return;
      return;
    }
    }


    uint16_t to_write = sizeof(int16_t) * pcm_data_decoded.size();
    /* both devices are connected */
    uint16_t written = LeAudioClientAudioSink::SendData(
    if (cached_channel_timestamp_ == 0) {
        (uint8_t*)pcm_data_decoded.data(), to_write);
      /* First packet received, cache it. We need both channel data to send it
       * to AF. */
      cached_channel_data_ = pcm_data_decoded;
      cached_channel_timestamp_ = timestamp;
      cached_channel_is_left_ = is_left;
      return;
    }

    /* We received either data for the other audio channel, or another
     * packet for same channel */

    if (cached_channel_is_left_ != is_left) {
      /* It's data for the 2nd channel */
      if (timestamp == cached_channel_timestamp_) {
        /* Ready to mix data and send out to AF */
        if (is_left) {
          SendAudioDataToAF(true /* bt_got_stereo */, af_is_stereo,
                            &cached_channel_data_, &pcm_data_decoded);
        } else {
          SendAudioDataToAF(true /* bt_got_stereo */, af_is_stereo,
                            &pcm_data_decoded, &cached_channel_data_);
        }

        cached_channel_timestamp_ = 0;
        return;
      }

      /* 2nd Channel is in the future compared to the cached data.
       Send the cached data to AF, and keep the new channel data in cache.
       This should happen only during stream setup */

      if (cached_channel_is_left_) {
        SendAudioDataToAF(false /* bt_got_stereo */, af_is_stereo,
                          &cached_channel_data_, nullptr);
      } else {
        SendAudioDataToAF(false /* bt_got_stereo */, af_is_stereo, nullptr,
                          &cached_channel_data_);
      }

      cached_channel_data_ = pcm_data_decoded;
      cached_channel_timestamp_ = timestamp;
      cached_channel_is_left_ = is_left;
      return;
    }

    /* Data for same channel received. 2nd channel is down/not sending
     * data */

    /* Send the cached data out */
    if (cached_channel_is_left_) {
      SendAudioDataToAF(false /* bt_got_stereo */, af_is_stereo,
                        &cached_channel_data_, nullptr);
    } else {
      SendAudioDataToAF(false /* bt_got_stereo */, af_is_stereo, nullptr,
                        &cached_channel_data_);
    }

    /* Cache the data in case 2nd channel connects */
    cached_channel_data_ = pcm_data_decoded;
    cached_channel_timestamp_ = timestamp;
    cached_channel_is_left_ = is_left;
  }

  void SendAudioDataToAF(bool bt_got_stereo, bool af_is_stereo,
                         std::vector<int16_t>* left,
                         std::vector<int16_t>* right) {
    uint16_t to_write = 0;
    uint16_t written = 0;
    if (!bt_got_stereo && !af_is_stereo) {
      std::vector<int16_t>* mono = left ? left : right;
      /* mono audio over bluetooth, audio framework expects mono */
      to_write = sizeof(int16_t) * mono->size();
      written =
          LeAudioClientAudioSink::SendData((uint8_t*)mono->data(), to_write);
    } else if (bt_got_stereo && af_is_stereo) {
      /* stero audio over bluetooth, audio framework expects stereo */
      std::vector<uint16_t> mixed(left->size() * 2);

      for (size_t i = 0; i < left->size(); i++) {
        mixed[2 * i] = (*left)[i];
        mixed[2 * i + 1] = (*right)[i];
      }
      to_write = sizeof(int16_t) * mixed.size();
      written =
          LeAudioClientAudioSink::SendData((uint8_t*)mixed.data(), to_write);
    } else if (bt_got_stereo && !af_is_stereo) {
      /* stero audio over bluetooth, audio framework expects mono */
      std::vector<uint16_t> mixed(left->size() * 2);

      for (size_t i = 0; i < left->size(); i++) {
        (*left)[i] = ((*left)[i] + (*right)[i]) / 2;
      }
      to_write = sizeof(int16_t) * left->size();
      written =
          LeAudioClientAudioSink::SendData((uint8_t*)left->data(), to_write);
    } else if (!bt_got_stereo && af_is_stereo) {
      /* mono audio over bluetooth, audio framework expects stereo */
      std::vector<uint16_t> mixed(left ? left->size() * 2 : right->size() * 2);

      for (size_t i = 0; i < left->size(); i++) {
        mixed[2 * i] = left ? (*left)[i] : 0;
        mixed[2 * i + 1] = right ? (*right)[i] : 0;
      }
      to_write = sizeof(int16_t) * mixed.size();
      written =
          LeAudioClientAudioSink::SendData((uint8_t*)mixed.data(), to_write);
    }


    /* TODO: What to do if not all data sinked ? */
    /* TODO: What to do if not all data sinked ? */
    if (written != to_write) LOG(ERROR) << __func__ << ", not all data sinked";
    if (written != to_write) LOG(ERROR) << __func__ << ", not all data sinked";
@@ -2257,22 +2399,29 @@ class LeAudioClientImpl : public LeAudioClient {
    uint16_t remote_delay_ms =
    uint16_t remote_delay_ms =
        group->GetRemoteDelay(le_audio::types::kLeAudioDirectionSource);
        group->GetRemoteDelay(le_audio::types::kLeAudioDirectionSource);


    cached_channel_timestamp_ = 0;
    if (CodecManager::GetInstance()->GetCodecLocation() ==
    if (CodecManager::GetInstance()->GetCodecLocation() ==
        le_audio::types::CodecLocation::HOST) {
        le_audio::types::CodecLocation::HOST) {
      if (lc3_decoder_mem) {
      if (lc3_decoder_left_mem) {
        LOG(WARNING)
        LOG(WARNING)
            << " The decoder instance should have been already released.";
            << " The decoder instance should have been already released.";
        free(lc3_decoder_mem);
        free(lc3_decoder_left_mem);
        lc3_decoder_mem = nullptr;
        lc3_decoder_left_mem = nullptr;
        free(lc3_decoder_right_mem);
        lc3_decoder_right_mem = nullptr;
      }
      }


      int dt_us = current_sink_codec_config.data_interval_us;
      int dt_us = current_sink_codec_config.data_interval_us;
      int sr_hz = current_sink_codec_config.sample_rate;
      int sr_hz = current_sink_codec_config.sample_rate;
      int af_hz = audio_framework_sink_config.sample_rate;
      int af_hz = audio_framework_sink_config.sample_rate;
      unsigned dec_size = lc3_decoder_size(dt_us, af_hz);
      unsigned dec_size = lc3_decoder_size(dt_us, af_hz);
      lc3_decoder_mem = malloc(dec_size);
      lc3_decoder_left_mem = malloc(dec_size);
      lc3_decoder_right_mem = malloc(dec_size);


      lc3_decoder = lc3_setup_decoder(dt_us, sr_hz, af_hz, lc3_decoder_mem);
      lc3_decoder_left =
          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() ==
    } else if (CodecManager::GetInstance()->GetCodecLocation() ==
               le_audio::types::CodecLocation::ADSP) {
               le_audio::types::CodecLocation::ADSP) {
      CodecManager::GetInstance()->UpdateActiveSinkAudioConfig(*stream_conf,
      CodecManager::GetInstance()->UpdateActiveSinkAudioConfig(*stream_conf,
@@ -2295,10 +2444,11 @@ class LeAudioClientImpl : public LeAudioClient {
      lc3_encoder_right_mem = nullptr;
      lc3_encoder_right_mem = nullptr;
    }
    }


    if (lc3_decoder_mem) {
    if (lc3_decoder_left_mem) {
      LOG(INFO) << __func__ << " stopping sink";
      free(lc3_decoder_left_mem);
      free(lc3_decoder_mem);
      lc3_decoder_left_mem = nullptr;
      lc3_decoder_mem = nullptr;
      free(lc3_decoder_left_mem);
      lc3_decoder_right_mem = nullptr;
    }
    }
  }
  }


@@ -3189,8 +3339,11 @@ class LeAudioClientImpl : public LeAudioClient {
  lc3_encoder_t lc3_encoder_left;
  lc3_encoder_t lc3_encoder_left;
  lc3_encoder_t lc3_encoder_right;
  lc3_encoder_t lc3_encoder_right;


  void* lc3_decoder_mem;
  void* lc3_decoder_left_mem;
  lc3_decoder_t lc3_decoder;
  void* lc3_decoder_right_mem;

  lc3_decoder_t lc3_decoder_left;
  lc3_decoder_t lc3_decoder_right;


  std::vector<uint8_t> encoded_data;
  std::vector<uint8_t> encoded_data;
  const void* audio_source_instance_;
  const void* audio_source_instance_;
@@ -3200,6 +3353,10 @@ class LeAudioClientImpl : public LeAudioClient {
      "persist.bluetooth.leaudio.audio.suspend.timeoutms";
      "persist.bluetooth.leaudio.audio.suspend.timeoutms";
  alarm_t* suspend_timeout_;
  alarm_t* suspend_timeout_;


  std::vector<int16_t> cached_channel_data_;
  uint32_t cached_channel_timestamp_ = 0;
  uint32_t cached_channel_is_left_;

  void ClientAudioIntefraceRelease() {
  void ClientAudioIntefraceRelease() {
    if (audio_source_instance_) {
    if (audio_source_instance_) {
      LeAudioClientAudioSource::Stop();
      LeAudioClientAudioSource::Stop();