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

Commit 62ea5bdd authored by En-Shuo Hsu's avatar En-Shuo Hsu Committed by Gerrit Code Review
Browse files

Merge changes Ie601f3f2,Ifd047a80

* changes:
  floss: Support playback for various SCO packet
  floss: Support recording for various SCO packet
parents 4560b3f9 48fdc3e7
Loading
Loading
Loading
Loading
+39 −95
Original line number Diff line number Diff line
@@ -33,8 +33,6 @@
#include "device/include/controller.h"
#include "embdrv/sbc/decoder/include/oi_codec_sbc.h"
#include "embdrv/sbc/decoder/include/oi_status.h"
#include "hfp_msbc_decoder.h"
#include "hfp_msbc_encoder.h"
#include "osi/include/allocator.h"
#include "osi/include/log.h"
#include "osi/include/osi.h"
@@ -94,30 +92,6 @@ static int16_t btm_pcm_buf[BTM_SCO_DATA_SIZE_MAX] = {0};
 * They are only used for WBS and the unit is byte. */
static size_t btm_pcm_buf_read_offset = 0;
static size_t btm_pcm_buf_write_offset = 0;

/* Per Bluetooth Core v5.0 and HFP 1.7 specification. */
#define BTM_MSBC_H2_HEADER_0 0x01
#define BTM_MSBC_H2_HEADER_LEN 2
#define BTM_MSBC_PKT_LEN 60
#define BTM_MSBC_PKT_FRAME_LEN 57 /* Packet length without the header */
#define BTM_MSBC_CODE_SIZE 240

/* The pre-computed zero input bit stream of mSBC codec, per HFP 1.7 spec.
 * This mSBC frame will be decoded into all-zero input PCM. */
static const uint8_t btm_msbc_zero_packet[] = {
    0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77, 0x6d, 0xb6, 0xdd,
    0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6,
    0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d,
    0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77,
    0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c};

static const uint8_t btm_msbc_zero_frames[BTM_MSBC_CODE_SIZE] = {0};

/* Second octet of H2 header is composed by 4 bits fixed 0x8 and 4 bits
 * sequence number 0000, 0011, 1100, 1111. */
static const uint8_t btm_h2_header_frames_count[] = {0x08, 0x38, 0xc8, 0xf8};

static uint8_t btm_msbc_num_out_frames;
/******************************************************************************/
/*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
/******************************************************************************/
@@ -210,15 +184,6 @@ static tSCO_CONN* btm_get_active_sco() {
  return nullptr;
}

static bool verify_h2_header_seq_num(const uint8_t num) {
  for (int i = 0; i < 4; i++) {
    if (num == btm_h2_header_frames_count[i]) {
      return true;
    }
  }
  return false;
}

/*******************************************************************************
 *
 * Function         btm_route_sco_data
@@ -261,40 +226,20 @@ void btm_route_sco_data(BT_HDR* p_msg) {
  }

  const uint8_t* decoded = nullptr;
  size_t written = 0;
  size_t written = 0, rc = 0;
  if (active_sco->is_wbs()) {
    /* TODO(b/235901463): Support packet size != BTM_MSBC_PKT_LEN */
    if (data_len != BTM_MSBC_PKT_LEN) {
      LOG_ERROR("Received invalid mSBC packet with invalid length:%hhu",
                data_len);
      osi_free(p_msg);
      return;
    }
    rc = bluetooth::audio::sco::wbs::enqueue_packet(payload, data_len);
    if (rc != data_len) LOG_DEBUG("Failed to enqueue packet");

    uint8_t h2_header;
    STREAM_TO_UINT8(h2_header, payload);
    if (h2_header != BTM_MSBC_H2_HEADER_0) {
      LOG_ERROR("Received invalid mSBC packet with invalid h2 header:%x",
                h2_header);
      osi_free(p_msg);
      return;
    }

    uint8_t seq_num;
    STREAM_TO_UINT8(seq_num, payload);
    if (!verify_h2_header_seq_num(seq_num)) {
      LOG_ERROR("Received invalid mSBC packet with invalid sequence number :%x",
                seq_num);
      osi_free(p_msg);
      return;
    while (rc) {
      rc = bluetooth::audio::sco::wbs::decode(&decoded);
      if (rc == 0) {
        LOG_DEBUG("Failed to decode frames");
        break;
      }

    if (!hfp_msbc_decoder_decode_packet(p_msg, &decoded)) {
      LOG_ERROR("Decode mSBC packet failed");
      decoded = btm_msbc_zero_frames;
      written += bluetooth::audio::sco::write(decoded, rc);
    }

    written = bluetooth::audio::sco::write(decoded, BTM_MSBC_CODE_SIZE);
  } else {
    written = bluetooth::audio::sco::write(payload, data_len);
  }
@@ -303,6 +248,7 @@ void btm_route_sco_data(BT_HDR* p_msg) {
  /* For Chrome OS, we send the outgoing data after receiving an incoming one.
   * server, so that we can keep the data read/write rate balanced */
  size_t read = 0, avail = 0;
  const uint8_t* encoded = nullptr;
  if (active_sco->is_wbs()) {
    while (written) {
      avail = BTM_SCO_DATA_SIZE_MAX - btm_pcm_buf_write_offset;
@@ -343,35 +289,34 @@ void btm_route_sco_data(BT_HDR* p_msg) {
      }

      btm_pcm_buf_write_offset += read;
      if (btm_pcm_buf_write_offset - btm_pcm_buf_read_offset <
          BTM_MSBC_CODE_SIZE) {
        continue;
      }
      rc = bluetooth::audio::sco::wbs::encode(
          &btm_pcm_buf[btm_pcm_buf_read_offset / sizeof(*btm_pcm_buf)],
          btm_pcm_buf_write_offset - btm_pcm_buf_read_offset);

      uint8_t encoded[BTM_MSBC_PKT_LEN] = {
          BTM_MSBC_H2_HEADER_0,
          btm_h2_header_frames_count[btm_msbc_num_out_frames % 4]};
      uint32_t encoded_size;
      encoded_size = hfp_msbc_encode_frames(btm_pcm_buf, encoded + 2);
      if (encoded_size != BTM_MSBC_PKT_FRAME_LEN) {
        LOG_WARN("Encode invalid packet size: %lu",
                 (unsigned long)encoded_size);
        std::copy(std::begin(btm_msbc_zero_packet),
                  std::end(btm_msbc_zero_packet),
                  &encoded[BTM_MSBC_H2_HEADER_LEN]);
      }

      auto data = std::vector<uint8_t>(encoded, encoded + BTM_MSBC_PKT_LEN);
      btm_send_sco_packet(std::move(data));
      btm_msbc_num_out_frames++;
      if (!rc)
        LOG_DEBUG(
            "Failed to encode data starting at ReadOffset:%lu to "
            "WriteOffset:%lu",
            (unsigned long)btm_pcm_buf_read_offset,
            (unsigned long)btm_pcm_buf_write_offset);

      /* The offsets should reset some time as the buffer length should always
       * divisible by BTM_MSBC_CODE_SIZE(240) */
      btm_pcm_buf_read_offset += BTM_MSBC_CODE_SIZE;
       * divisible by BTM_MSBC_CODE_SIZE(240) and wbs::encode only returns
       * BTM_MSBC_CODE_SIZE or 0 */
      btm_pcm_buf_read_offset += rc;
      if (btm_pcm_buf_write_offset == btm_pcm_buf_read_offset) {
        btm_pcm_buf_write_offset = 0;
        btm_pcm_buf_read_offset = 0;
      }

      /* Send all of the available SCO packets buffered in the queue */
      while (1) {
        rc = bluetooth::audio::sco::wbs::dequeue_packet(&encoded);
        if (!rc) break;

        auto data = std::vector<uint8_t>(encoded, encoded + rc);
        btm_send_sco_packet(std::move(data));
      }
    }
  } else {
    while (written) {
@@ -910,6 +855,7 @@ void btm_sco_connected(const RawAddress& bda, uint16_t hci_handle,
  uint16_t xx;
  bool spt = false;
  tBTM_CHG_ESCO_PARAMS parms = {};
  int codec;

  for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) {
    if (((p->state == SCO_ST_CONNECTING) || (p->state == SCO_ST_LISTENING) ||
@@ -944,19 +890,18 @@ void btm_sco_connected(const RawAddress& bda, uint16_t hci_handle,

      (*p->p_conn_cb)(xx);

      codec = hfp_hal_interface::esco_coding_to_codec(
          p->esco.setup.transmit_coding_format.coding_format);
      hfp_hal_interface::notify_sco_connection_change(
          bda, /*is_connected=*/true,
          hfp_hal_interface::esco_coding_to_codec(
              p->esco.setup.transmit_coding_format.coding_format));
          bda, /*is_connected=*/true, codec);

      /* In-band (non-offload) data path */
      if (p->is_inband()) {
        if (p->is_wbs()) {
          btm_pcm_buf_read_offset = 0;
          btm_pcm_buf_write_offset = 0;
          btm_msbc_num_out_frames = 0;
          hfp_msbc_decoder_init();
          hfp_msbc_encoder_init();
          bluetooth::audio::sco::wbs::init(
              hfp_hal_interface::get_packet_size(codec));
        }

        std::fill(std::begin(btm_pcm_buf), std::end(btm_pcm_buf), 0);
@@ -1187,8 +1132,7 @@ void btm_sco_on_disconnected(uint16_t hci_handle, tHCI_REASON reason) {

  if (p_sco->is_inband()) {
    if (p_sco->is_wbs()) {
      hfp_msbc_decoder_cleanup();
      hfp_msbc_encoder_cleanup();
      bluetooth::audio::sco::wbs::cleanup();
    }

    bluetooth::audio::sco::cleanup();
+55 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@
#include "device/include/esco_parameters.h"
#include "stack/include/btm_api_types.h"

#define BTM_MSBC_CODE_SIZE 240

constexpr uint16_t kMaxScoLinks = static_cast<uint16_t>(BTM_MAX_SCO_LINKS);

/* SCO-over-HCI audio related definitions */
@@ -44,6 +46,59 @@ size_t read(uint8_t* p_buf, uint32_t len);
size_t write(const uint8_t* buf, uint32_t len);
}  // namespace bluetooth::audio::sco

/* SCO-over-HCI audio HFP WBS related definitions */
namespace bluetooth::audio::sco::wbs {

/* Initialize struct used for storing WBS related information.
 * Args:
 *    pkt_size - Length of the SCO packet. It is determined based on the BT-USB
 *    adapter's capability and alt mode setting. The value should be queried
 *    from HAL interface. It will be used to determine the size of the SCO
 *    packet buffer.
 */
void init(size_t pkt_size);

/* Clean up when the SCO connection is done */
void cleanup();

/* Try to enqueue a packet to a buffer.
 * Args:
 *    data - Pointer to received packet data bytes.
 *    pkt_size - Length of input packet. Passing packet with inconsistent size
 *        from the pkt_size set in init() will trigger a reset of the buffer.
 * Returns:
 *    The length of enqueued bytes. 0 if failed.
 */
size_t enqueue_packet(const uint8_t* data, size_t pkt_size);

/* Try to decode mSBC frames from the packets in the buffer.
 * Args:
 *    output - Pointer to the decoded PCM bytes caller can read from.
 * Returns:
 *    The length of decoded bytes. 0 if failed.
 */
size_t decode(const uint8_t** output);

/* Try to encode PCM data into one SCO packet and put the packets in the buffer.
 * Args:
 *    data - Pointer to the input PCM bytes for the encoder to encode.
 *    len - Length of the input data.
 * Returns:
 *    The length of input data that is encoded. 0 if failed.
 */
size_t encode(int16_t* data, size_t len);

/* Dequeue a SCO packet with encoded mSBC data if possible. The length of the
 * packet is determined by the pkt_size set by the init().
 * Args:
 *    output - Pointer to output mSBC packets encoded by the encoder.
 * Returns:
 *    The length of dequeued packet. 0 if failed.
 */
size_t dequeue_packet(const uint8_t** output);

}  // namespace bluetooth::audio::sco::wbs

/* Define the structures needed by sco */
typedef enum : uint16_t {
  SCO_ST_UNUSED = 0,
+336 −0
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@

#include <memory>

#include "hfp_msbc_decoder.h"
#include "hfp_msbc_encoder.h"
#include "osi/include/allocator.h"
#include "osi/include/log.h"
#include "stack/btm/btm_sco.h"
#include "udrv/include/uipc.h"
@@ -30,6 +33,13 @@
// TODO(b/198260375): Make SCO data owner group configurable.
#define SCO_HOST_DATA_GROUP "bluetooth-audio"

/* Per Bluetooth Core v5.0 and HFP 1.7 specification. */
#define BTM_MSBC_H2_HEADER_0 0x01
#define BTM_MSBC_H2_HEADER_LEN 2
#define BTM_MSBC_PKT_LEN 60
#define BTM_MSBC_PKT_FRAME_LEN 57 /* Packet length without the header */
#define BTM_MSBC_SYNC_WORD 0xAD

namespace {

std::unique_ptr<tUIPC_STATE> sco_uipc = nullptr;
@@ -97,6 +107,332 @@ size_t write(const uint8_t* p_buf, uint32_t len) {
  return UIPC_Send(*sco_uipc, UIPC_CH_ID_AV_AUDIO, 0, p_buf, len) ? len : 0;
}

namespace wbs {

/* Second octet of H2 header is composed by 4 bits fixed 0x8 and 4 bits
 * sequence number 0000, 0011, 1100, 1111. */
static const uint8_t btm_h2_header_frames_count[] = {0x08, 0x38, 0xc8, 0xf8};

/* Supported SCO packet sizes for mSBC. The wideband speech mSBC frame parsing
 * code ties to limited packet size values. Specifically list them out
 * to check against when setting packet size. The first entry is the default
 * value as a fallback. */
constexpr size_t btm_wbs_supported_pkt_size[] = {BTM_MSBC_PKT_LEN, 72, 0};
/* Buffer size should be set to least common multiple of SCO packet size and
 * BTM_MSBC_PKT_LEN for optimizing buffer copy. */
constexpr size_t btm_wbs_msbc_buffer_size[] = {BTM_MSBC_PKT_LEN, 360, 0};

/* The pre-computed zero input bit stream of mSBC codec, per HFP 1.7 spec.
 * This mSBC frame will be decoded into all-zero input PCM. */
static const uint8_t btm_msbc_zero_packet[] = {
    0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77, 0x6d, 0xb6, 0xdd,
    0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, 0xb6,
    0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d,
    0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77,
    0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c};

static const uint8_t btm_msbc_zero_frames[BTM_MSBC_CODE_SIZE] = {0};

/* Define the structure that contains mSBC data */
typedef struct {
  size_t packet_size;   /* SCO mSBC packet size supported by lower layer */
  bool check_alignment; /* True to wait for mSBC packet to align */
  size_t buf_size; /* The size of the buffer, determined by the packet_size. */

  uint8_t* msbc_decode_buf; /* Buffer to store mSBC packets to decode */
  size_t decode_buf_wo;     /* Write offset of the decode buffer */
  size_t decode_buf_ro;     /* Read offset of the decode buffer */

  uint8_t* msbc_encode_buf; /* Buffer to store the encoded SCO packets */
  size_t encode_buf_wo;     /* Write offset of the encode buffer */
  size_t encode_buf_ro;     /* Read offset of the encode buffer */

  uint8_t num_encoded_msbc_pkts; /* Number of the encoded mSBC packets */
  static size_t get_supported_packet_size(size_t pkt_size,
                                          size_t* buffer_size) {
    int i;
    for (i = 0; btm_wbs_supported_pkt_size[i] != 0 &&
                btm_wbs_supported_pkt_size[i] != pkt_size;
         i++)
      ;
    /* In case of unsupported value, error log and fallback to
     * BTM_MSBC_PKT_LEN(60). */
    if (btm_wbs_supported_pkt_size[i] == 0) {
      LOG_WARN("Unsupported packet size %lu", (unsigned long)pkt_size);
      i = 0;
    }

    if (buffer_size) {
      *buffer_size = btm_wbs_msbc_buffer_size[i];
    }
    return btm_wbs_supported_pkt_size[i];
  }

  bool verify_h2_header_seq_num(const uint8_t num) {
    for (int i = 0; i < 4; i++) {
      if (num == btm_h2_header_frames_count[i]) {
        return true;
      }
    }
    return false;
  }

 public:
  void init(size_t pkt_size) {
    decode_buf_wo = 0;
    decode_buf_ro = 0;
    encode_buf_wo = 0;
    encode_buf_ro = 0;

    pkt_size = get_supported_packet_size(pkt_size, &buf_size);
    if (pkt_size != BTM_MSBC_PKT_LEN) check_alignment = true;
    if (pkt_size == packet_size) return;
    packet_size = pkt_size;

    if (msbc_decode_buf) osi_free(msbc_decode_buf);
    msbc_decode_buf = (uint8_t*)osi_calloc(buf_size);

    if (msbc_encode_buf) osi_free(msbc_encode_buf);
    msbc_encode_buf = (uint8_t*)osi_calloc(buf_size);
  }

  void deinit() {
    if (msbc_decode_buf) osi_free(msbc_decode_buf);
    if (msbc_encode_buf) osi_free(msbc_encode_buf);
  }

  size_t decodable() { return decode_buf_wo - decode_buf_ro; }

  void mark_pkt_decoded() {
    if (decode_buf_ro + BTM_MSBC_PKT_LEN > decode_buf_wo) {
      LOG_ERROR("Trying to mark read offset beyond write offset.");
      return;
    }

    decode_buf_ro += BTM_MSBC_PKT_LEN;
    if (decode_buf_ro == decode_buf_wo) {
      decode_buf_ro = 0;
      decode_buf_wo = 0;
    }
  }

  size_t write(const uint8_t* input, size_t len) {
    if (len > buf_size - decode_buf_wo) {
      return 0;
    }

    std::copy(input, input + len, msbc_decode_buf + decode_buf_wo);
    decode_buf_wo += len;
    return len;
  }

  const uint8_t* find_msbc_pkt_head() {
    size_t rp = 0;
    while (decode_buf_wo - decode_buf_ro - rp >= BTM_MSBC_PKT_LEN) {
      if ((msbc_decode_buf[decode_buf_ro + rp] != BTM_MSBC_H2_HEADER_0) ||
          (!verify_h2_header_seq_num(
              msbc_decode_buf[decode_buf_ro + rp + 1])) ||
          (msbc_decode_buf[decode_buf_ro + rp + 2] != BTM_MSBC_SYNC_WORD)) {
        rp++;
        continue;
      }
      return &msbc_decode_buf[decode_buf_ro + rp];
    }

    return nullptr;
  }

  /* Fill in the mSBC header and update the buffer's write offset to guard the
   * buffer space to be written. Return a pointer to the start of mSBC packet's
   * body for the caller to fill the encoded mSBC data if there is enough space
   * in the buffer to fill in a new packet, otherwise return a nullptr. */
  uint8_t* fill_msbc_pkt_template() {
    uint8_t* wp = &msbc_encode_buf[encode_buf_wo];
    if (buf_size - encode_buf_wo < BTM_MSBC_PKT_LEN) {
      LOG_DEBUG("Packet queue can't accommodate more packets.");
      return nullptr;
    }

    wp[0] = BTM_MSBC_H2_HEADER_0;
    wp[1] = btm_h2_header_frames_count[num_encoded_msbc_pkts % 4];
    encode_buf_wo += BTM_MSBC_PKT_LEN;

    num_encoded_msbc_pkts++;
    return wp + BTM_MSBC_H2_HEADER_LEN;
  }

  size_t mark_pkt_dequeued() {
    LOG_DEBUG(
        "Try to mark an encoded packet dequeued: ro:%lu wo:%lu pkt_size:%lu",
        (unsigned long)encode_buf_ro, (unsigned long)encode_buf_wo,
        (unsigned long)packet_size);

    if (encode_buf_wo - encode_buf_ro < packet_size) return 0;

    encode_buf_ro += packet_size;
    if (encode_buf_ro == encode_buf_wo) {
      encode_buf_ro = 0;
      encode_buf_wo = 0;
    }

    return packet_size;
  }

  const uint8_t* sco_pkt_read_ptr() {
    if (encode_buf_wo - encode_buf_ro < packet_size) {
      LOG_DEBUG("Insufficient data as a SCO packet to read.");
      return nullptr;
    }

    return &msbc_encode_buf[encode_buf_ro];
  }

} tBTM_MSBC_INFO;

static tBTM_MSBC_INFO* msbc_info = nullptr;

void init(size_t pkt_size) {
  hfp_msbc_decoder_init();
  hfp_msbc_encoder_init();

  if (msbc_info) {
    LOG_WARN("Re-initiating mSBC buffer that is active or not cleaned");
    msbc_info->deinit();
    osi_free(msbc_info);
  }

  msbc_info = (tBTM_MSBC_INFO*)osi_calloc(sizeof(*msbc_info));
  msbc_info->init(pkt_size);
}

void cleanup() {
  hfp_msbc_decoder_cleanup();
  hfp_msbc_encoder_cleanup();

  if (msbc_info == nullptr) return;

  msbc_info->deinit();
  osi_free(msbc_info);
  msbc_info = nullptr;
}

size_t enqueue_packet(const uint8_t* data, size_t pkt_size) {
  if (msbc_info == nullptr) {
    LOG_WARN("mSBC buffer uninitialized or cleaned");
    return 0;
  }

  if (pkt_size != msbc_info->packet_size) {
    LOG_WARN(
        "Ignoring the coming packet with size %lu that is inconsistent with "
        "the HAL reported packet size %lu",
        (unsigned long)pkt_size, (unsigned long)msbc_info->packet_size);
    return 0;
  }

  if (msbc_info->check_alignment) {
    if (data[0] != BTM_MSBC_H2_HEADER_0 || data[2] != BTM_MSBC_SYNC_WORD) {
      LOG_DEBUG("Waiting for valid mSBC frame head");
      return 0;
    }
    msbc_info->check_alignment = false;
  }

  if (msbc_info->write(data, pkt_size) != pkt_size) {
    LOG_DEBUG("Fail to write packet with size %lu to buffer",
              (unsigned long)pkt_size);
    return 0;
  }

  return pkt_size;
}

size_t decode(const uint8_t** out_data) {
  const uint8_t* frame_head = nullptr;

  if (msbc_info == nullptr) {
    LOG_WARN("mSBC buffer uninitialized or cleaned");
    return 0;
  }

  if (msbc_info->decodable() < BTM_MSBC_PKT_LEN) {
    LOG_DEBUG("No complete mSBC packet to decode");
    return 0;
  }

  frame_head = msbc_info->find_msbc_pkt_head();
  if (frame_head == nullptr) {
    LOG_DEBUG("No valid mSBC packet to decode %lu, %lu",
              (unsigned long)msbc_info->decode_buf_ro,
              (unsigned long)msbc_info->decode_buf_wo);
    /* Done with parsing the raw bytes just read. If mSBC frame head not found,
     * we shall handle it as packet loss. */
    goto packet_loss;
  }

  if (!hfp_msbc_decoder_decode_packet(frame_head, out_data)) {
    LOG_DEBUG("Decoding mSBC packet failed");
    goto packet_loss;
  }

  msbc_info->mark_pkt_decoded();
  return BTM_MSBC_CODE_SIZE;

packet_loss:
  *out_data = btm_msbc_zero_frames;
  msbc_info->mark_pkt_decoded();
  return BTM_MSBC_CODE_SIZE;
}

size_t encode(int16_t* data, size_t len) {
  uint8_t* pkt_body = nullptr;
  uint32_t encoded_size = 0;
  if (msbc_info == nullptr) {
    LOG_WARN("mSBC buffer uninitialized or cleaned");
    return 0;
  }

  if (len < BTM_MSBC_CODE_SIZE) {
    LOG_DEBUG(
        "PCM frames with size %lu is insufficient to be encoded into a mSBC "
        "packet",
        (unsigned long)len);
    return 0;
  }

  pkt_body = msbc_info->fill_msbc_pkt_template();
  if (pkt_body == nullptr) {
    LOG_DEBUG("Failed to fill the template to fill the mSBC packet");
    return 0;
  }

  encoded_size = hfp_msbc_encode_frames(data, pkt_body);
  if (encoded_size != BTM_MSBC_PKT_FRAME_LEN) {
    LOG_WARN("Encoding invalid packet size: %lu", (unsigned long)encoded_size);
    std::copy(std::begin(btm_msbc_zero_packet), std::end(btm_msbc_zero_packet),
              pkt_body);
  }

  return BTM_MSBC_CODE_SIZE;
}

size_t dequeue_packet(const uint8_t** output) {
  if (msbc_info == nullptr) {
    LOG_WARN("mSBC buffer uninitialized or cleaned");
    return 0;
  }

  *output = msbc_info->sco_pkt_read_ptr();
  if (*output == nullptr) {
    LOG_DEBUG("Insufficient data to dequeue.");
    return 0;
  }

  return msbc_info->mark_pkt_dequeued();
}

}  // namespace wbs

}  // namespace sco
}  // namespace audio
}  // namespace bluetooth
+9 −12
Original line number Diff line number Diff line
@@ -25,7 +25,8 @@
#include "embdrv/sbc/decoder/include/oi_codec_sbc.h"
#include "embdrv/sbc/decoder/include/oi_status.h"
#include "osi/include/log.h"
#include "stack/include/bt_hdr.h"

#define HFP_MSBC_PKT_LEN 60

typedef struct {
  OI_CODEC_SBC_DECODER_CONTEXT decoder_context;
@@ -59,19 +60,15 @@ void hfp_msbc_decoder_cleanup(void) {
  memset(&hfp_msbc_decoder, 0, sizeof(hfp_msbc_decoder));
}

bool hfp_msbc_decoder_decode_packet(BT_HDR* p_buf, const uint8_t** out_buf) {
// Get the HFP MSBC encoded maximum frame size
bool hfp_msbc_decoder_decode_packet(const uint8_t* i_buf,
                                    const uint8_t** o_buf) {
  const OI_BYTE* oi_data;
  uint32_t oi_size, out_avail;
  int16_t* out_ptr;

  // TODO(b/232463744): Query the HFP HAL for the packet size.
  if (p_buf->len != 63) {
    LOG_ERROR("%s: Invalid packet", __func__);
    return false;
  }

  oi_data = p_buf->data + p_buf->offset;
  oi_size = p_buf->len;
  oi_data = i_buf;
  oi_size = HFP_MSBC_PKT_LEN;
  out_avail = sizeof(hfp_msbc_decoder.decode_buf);
  out_ptr = hfp_msbc_decoder.decode_buf;

@@ -79,11 +76,11 @@ bool hfp_msbc_decoder_decode_packet(BT_HDR* p_buf, const uint8_t** out_buf) {
      OI_CODEC_SBC_DecodeFrame(&hfp_msbc_decoder.decoder_context, &oi_data,
                               &oi_size, out_ptr, &out_avail);
  if (!OI_SUCCESS(status) || out_avail != 240 || oi_size != 0) {
    LOG_ERROR("%s: Decoding failure: %d, %lu, %lu", __func__, status,
    LOG_ERROR("Decoding failure: %d, %lu, %lu", status,
              (unsigned long)out_avail, (unsigned long)oi_size);
    return false;
  }

  *out_buf = (const uint8_t*)&hfp_msbc_decoder.decode_buf;
  *o_buf = (const uint8_t*)&hfp_msbc_decoder.decode_buf;
  return true;
}
+0 −1
Original line number Diff line number Diff line
@@ -43,7 +43,6 @@ void hfp_msbc_encoder_init(void) {

void hfp_msbc_encoder_cleanup(void) { hfp_msbc_encoder = {}; }

// Get the HFP MSBC encoded maximum frame size
uint32_t hfp_msbc_encode_frames(int16_t* input, uint8_t* output) {
  return SBC_Encode(&hfp_msbc_encoder.sbc_encoder_params, input, output);
}
Loading