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

Commit 36a6b3b1 authored by Jeremy Wu's avatar Jeremy Wu Committed by Gerrit Code Review
Browse files

Merge "Floss: wrap HFP LC3 codec libraries with codec server" into main

parents 23639f1a 4168258c
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
#
#  Copyright 2023 The Android Open Source Project
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at:
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#

source_set("libcodec_server_hfp_lc3"){
  configs += [ "//bt/system/stack/mmc:target_defaults" ]
  include_dirs = [
    "//bt/system",
    "//bt/system/include",
    "//bt/system/stack",
    "//bt/system/stack/include",
  ]
  deps = [
    "//bt/system/stack/mmc/proto:mmc_config_proto",
    "//bt/system/embdrv/lc3:liblc3",
    "//bt/system/osi",
  ]
  sources = [
    "hfp_lc3_mmc_encoder.cc",
    "hfp_lc3_mmc_decoder.cc",
  ]
}
+93 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mmc/codec_server/hfp_lc3_mmc_decoder.h"

#include <base/logging.h>
#include <errno.h>

#include "embdrv/lc3/include/lc3.h"
#include "mmc/codec_server/lc3_utils.h"
#include "mmc/proto/mmc_config.pb.h"
#include "osi/include/allocator.h"

namespace mmc {

HfpLc3Decoder::HfpLc3Decoder() : hfp_lc3_decoder_mem_(nullptr) {}

HfpLc3Decoder::~HfpLc3Decoder() { cleanup(); }

int HfpLc3Decoder::init(ConfigParam config) {
  cleanup();

  if (!config.has_hfp_lc3_decoder_param()) {
    LOG(ERROR) << "HFP LC3 decoder params are not set";
    return -EINVAL;
  }

  param_ = config.hfp_lc3_decoder_param();
  int dt_us = param_.dt_us();
  int sr_hz = param_.sr_hz();
  int sr_pcm_hz = param_.sr_pcm_hz();
  const unsigned dec_size = lc3_decoder_size(dt_us, sr_pcm_hz);

  hfp_lc3_decoder_mem_ = osi_malloc(dec_size);

  hfp_lc3_decoder_ =
      lc3_setup_decoder(dt_us, sr_hz, sr_pcm_hz, hfp_lc3_decoder_mem_);

  if (hfp_lc3_decoder_ == nullptr) {
    LOG(ERROR) << "Wrong parameters provided";
    return -EINVAL;
  }

  return HFP_LC3_PKT_FRAME_LEN;
}

void HfpLc3Decoder::cleanup() {
  if (hfp_lc3_decoder_mem_) {
    osi_free_and_reset((void**)&hfp_lc3_decoder_mem_);
    LOG(INFO) << "Released the decoder instance";
  }
}

int HfpLc3Decoder::transcode(uint8_t* i_buf, int i_len, uint8_t* o_buf,
                             int o_len) {
  if (o_buf == nullptr || o_len < HFP_LC3_PCM_BYTES + 1) {
    LOG(ERROR) << "Output buffer size is less than LC3 frame size";
    return -EINVAL;
  }

  // Check header to decide whether it's PLC.
  uint8_t* in_frame =
      (i_buf[0] || i_buf[1]) ? i_buf + HFP_LC3_H2_HEADER_LEN : nullptr;

  // First byte is reserved to indicate PLC.
  uint8_t* out_frame = o_buf + 1;

  /* Note this only fails when wrong parameters are supplied. */
  int rc = lc3_decode(hfp_lc3_decoder_, in_frame, HFP_LC3_PKT_FRAME_LEN,
                      MapLc3PcmFmt(param_.fmt()), out_frame, param_.stride());

  if (rc != 0 && rc != 1) {
    LOG(WARNING) << "Wrong decode parameters";
    std::fill(o_buf, o_buf + o_len, 0);
  } else
    o_buf[0] = rc;
  return HFP_LC3_PCM_BYTES + 1;
}

}  // namespace mmc
+62 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MMC_CODEC_SERVER_HFP_LC3_MMC_DECODER_H_
#define MMC_CODEC_SERVER_HFP_LC3_MMC_DECODER_H_

#include "embdrv/lc3/include/lc3.h"
#include "mmc/mmc_interface/mmc_interface.h"
#include "mmc/proto/mmc_config.pb.h"

namespace mmc {

// Implementation of MmcInterface.
// HfpLc3Decoder wraps lc3 decode libraries.
class HfpLc3Decoder : public MmcInterface {
 public:
  explicit HfpLc3Decoder();
  ~HfpLc3Decoder();

  // HfpLc3Decoder is neither copyable nor movable.
  HfpLc3Decoder(const HfpLc3Decoder&) = delete;
  HfpLc3Decoder& operator=(const HfpLc3Decoder&) = delete;

  // Inits decoder instance.
  //
  // Returns:
  //   Input packet size accepted by the decoder, if init succeeded.
  //   Negative errno on error, otherwise.
  int init(ConfigParam config) override;

  // Releases decoder instance.
  void cleanup() override;

  // Decodes data from |i_buf| and stores the result in |o_buf|.
  //
  // Returns:
  //   Decoded data length, if decode succeeded.
  //   Negative errno on error, otherwise.
  int transcode(uint8_t* i_buf, int i_len, uint8_t* o_buf, int o_len) override;

 private:
  void* hfp_lc3_decoder_mem_;
  lc3_decoder_t hfp_lc3_decoder_;
  Lc3Param param_;
};

}  // namespace mmc

#endif  // MMC_CODEC_SERVER_HFP_LC3_MMC_DECODER_H_
+88 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mmc/codec_server/hfp_lc3_mmc_encoder.h"

#include <base/logging.h>
#include <errno.h>

#include <algorithm>

#include "embdrv/lc3/include/lc3.h"
#include "mmc/codec_server/lc3_utils.h"
#include "mmc/proto/mmc_config.pb.h"
#include "osi/include/allocator.h"

namespace mmc {

HfpLc3Encoder::HfpLc3Encoder() : hfp_lc3_encoder_mem_(nullptr) {}

HfpLc3Encoder::~HfpLc3Encoder() { cleanup(); }

int HfpLc3Encoder::init(ConfigParam config) {
  cleanup();

  if (!config.has_hfp_lc3_encoder_param()) {
    LOG(ERROR) << "HFP LC3 encoder params are not set";
    return -EINVAL;
  }

  param_ = config.hfp_lc3_encoder_param();
  int dt_us = param_.dt_us();
  int sr_hz = param_.sr_hz();
  int sr_pcm_hz = param_.sr_pcm_hz();
  const unsigned enc_size = lc3_encoder_size(dt_us, sr_pcm_hz);

  hfp_lc3_encoder_mem_ = osi_malloc(enc_size);

  hfp_lc3_encoder_ =
      lc3_setup_encoder(dt_us, sr_hz, sr_pcm_hz, hfp_lc3_encoder_mem_);

  if (hfp_lc3_encoder_ == nullptr) {
    LOG(ERROR) << "Wrong parameters provided";
    return -EINVAL;
  }

  return HFP_LC3_PCM_BYTES;
}

void HfpLc3Encoder::cleanup() {
  if (hfp_lc3_encoder_mem_) {
    osi_free_and_reset((void**)&hfp_lc3_encoder_mem_);
    LOG(INFO) << "Released the encoder instance";
  }
}

int HfpLc3Encoder::transcode(uint8_t* i_buf, int i_len, uint8_t* o_buf,
                             int o_len) {
  if (i_buf == nullptr || o_buf == nullptr) {
    LOG(ERROR) << "Buffer is null";
    return -EINVAL;
  }

  /* Note this only fails when wrong parameters are supplied. */
  int rc = lc3_encode(hfp_lc3_encoder_, MapLc3PcmFmt(param_.fmt()), i_buf,
                      param_.stride(), HFP_LC3_PKT_FRAME_LEN, o_buf);

  if (rc != 0) {
    LOG(WARNING) << "Wrong encode parameters";
    std::fill(o_buf, o_buf + o_len, 0);
  }

  return HFP_LC3_PKT_FRAME_LEN;
}

}  // namespace mmc
+62 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MMC_CODEC_SERVER_HFP_LC3_MMC_ENCODER_H_
#define MMC_CODEC_SERVER_HFP_LC3_MMC_ENCODER_H_

#include "embdrv/lc3/include/lc3.h"
#include "mmc/mmc_interface/mmc_interface.h"
#include "mmc/proto/mmc_config.pb.h"

namespace mmc {

// Implementation of MmcInterface.
// HfpLc3Encoder wraps lc3 encode libraries.
class HfpLc3Encoder : public MmcInterface {
 public:
  explicit HfpLc3Encoder();
  ~HfpLc3Encoder();

  // HfpLc3Encoder is neither copyable nor movable.
  HfpLc3Encoder(const HfpLc3Encoder&) = delete;
  HfpLc3Encoder& operator=(const HfpLc3Encoder&) = delete;

  // Inits encoder instance.
  //
  // Returns:
  //   Input pcm frame size accepted by the encoder, if init succeeded.
  //   Negative errno on error, otherwise.
  int init(ConfigParam config) override;

  // Releases encoder instance.
  void cleanup() override;

  // Encodes data from |i_buf|, and stores the result to |o_buf|.
  //
  // Returns:
  //   Encoded data length, if encode succeeded.
  //   Negative errno on error, otherwise.
  int transcode(uint8_t* i_buf, int i_len, uint8_t* o_buf, int o_len) override;

 private:
  void* hfp_lc3_encoder_mem_;
  lc3_encoder_t hfp_lc3_encoder_;
  Lc3Param param_;
};

}  // namespace mmc

#endif  // MMC_CODEC_SERVER_HFP_LC3_MMC_ENCODER_H_
Loading