// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/media/sounds/soundplayer/opus_decoder.h"

#include <endian.h>
#include <lib/fit/defer.h>
#include <lib/syslog/cpp/macros.h>

#include <memory>

#include "third_party/opus/include/opus.h"

namespace soundplayer {
namespace {

// Creates a 64-bit value from 8 bytes. Used for Opus signature value.
static inline constexpr uint64_t make_eightcc(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e,
                                              uint8_t f, uint8_t g, uint8_t h) {
  return htole64((static_cast<uint64_t>(h) << 56) | (static_cast<uint64_t>(g) << 48) |
                 (static_cast<uint64_t>(f) << 40) | (static_cast<uint64_t>(e) << 32) |
                 (static_cast<uint64_t>(d) << 24) | (static_cast<uint64_t>(c) << 16) |
                 (static_cast<uint64_t>(b) << 8) | static_cast<uint64_t>(a));
}

static constexpr uint64_t kIdHeaderSignature = make_eightcc('O', 'p', 'u', 's', 'H', 'e', 'a', 'd');
static constexpr uint64_t kCommentHeaderSignature =
    make_eightcc('O', 'p', 'u', 's', 'T', 'a', 'g', 's');
static constexpr uint8_t kSupportedVersion = 1;
static constexpr uint8_t kSupportedMappingFamily = 0;
static constexpr uint32_t kOutputFramesPerSecond = 48000;
static constexpr size_t kOutputBufferMaxFrameCount = 5760;  // 120ms at 48k

struct IdHeader {
  uint64_t signature_;  // 'OpusHead' (kIdHeaderSignature)
  uint8_t version_;
  uint8_t channel_count_;
  uint16_t preskip_;
  uint32_t input_sample_rate_;
  uint16_t output_gain_;
  uint8_t mapping_family_;
} __PACKED;

struct CommentHeader {
  uint64_t signature_;  // 'OpusTags' (kCommentHeaderSignature)
  // Variable stuff follows. Not used.
} __PACKED;

}  // namespace

// static
bool OpusDecoder::CheckHeaderPacket(const uint8_t* data, size_t size) {
  if (size < sizeof(IdHeader)) {
    // Header too small.
    return false;
  }

  auto& header = *reinterpret_cast<const IdHeader*>(data);
  if (header.signature_ != kIdHeaderSignature) {
    // Signature not found.
    return false;
  }

  if (header.version_ != kSupportedVersion) {
    // Unsupported version.
    return false;
  }

  if (header.channel_count_ != 1 && header.channel_count_ != 2) {
    // Unsupported channel count.
    return false;
  }

  if (header.mapping_family_ != kSupportedMappingFamily) {
    // Unsupported mapping family.
    return false;
  }

  return true;
}

bool OpusDecoder::ProcessPacket(const uint8_t* data, size_t size, bool first, bool last,
                                DiscardableSound& sound) {
  if (first) {
    second_packet_processed_ = false;
    total_frame_count_ = 0;
    output_buffers_.clear();
    return ProcessIdHeader(data, size);
  }

  if (!second_packet_processed_) {
    second_packet_processed_ = true;
    return ProcessCommentHeader(data, size);
  }

  FX_DCHECK(decoder_);

  auto output_buffer = std::make_unique<int16_t[]>(kOutputBufferMaxFrameCount * channels_);

  int decoded_frame_count_or_error =
      opus_decode(decoder_.get(), data, size, output_buffer.get(), kOutputBufferMaxFrameCount, 0);
  if (decoded_frame_count_or_error < 0) {
    // Decode failed.
    FX_LOGS(WARNING) << "opus_decode failed, error " << decoded_frame_count_or_error;
    return false;
  }

  HandleOutputBuffer(std::move(output_buffer), static_cast<uint32_t>(decoded_frame_count_or_error));

  if (last) {
    return HandleEndOfStream(sound);
  }

  return true;
}

bool OpusDecoder::ProcessIdHeader(const uint8_t* data, size_t size) {
  // |CheckHeaderPacket| approved the header previously, so we can just DCHECK what was checked
  // there.
  FX_DCHECK(size >= sizeof(IdHeader));

  auto& header = *reinterpret_cast<const IdHeader*>(data);
  FX_DCHECK(header.signature_ == kIdHeaderSignature);
  FX_DCHECK(header.version_ == kSupportedVersion);
  FX_DCHECK(header.channel_count_ == 1 || header.channel_count_ == 2);
  FX_DCHECK(header.mapping_family_ == kSupportedMappingFamily);

  channels_ = header.channel_count_;
  preskip_ = header.preskip_;
  input_frames_per_second_ = header.input_sample_rate_;

  int error;
  decoder_ = std::unique_ptr<::OpusDecoder, DecoderDeleter>(
      opus_decoder_create(kOutputFramesPerSecond, channels_, &error));
  if (!decoder_) {
    FX_LOGS(ERROR) << "opus_decoder_create failed, error " << error;
    return false;
  }

  return true;
}

bool OpusDecoder::ProcessCommentHeader(const uint8_t* data, size_t size) {
  if (size < sizeof(CommentHeader)) {
    // Header too small.
    return false;
  }

  auto& header = *reinterpret_cast<const CommentHeader*>(data);
  if (header.signature_ != kCommentHeaderSignature) {
    // Signature not found.
    return false;
  }

  // If metadata from the comment header is needed, parse it here.

  return true;
}

void OpusDecoder::HandleOutputBuffer(std::unique_ptr<int16_t[]> buffer, uint32_t frame_count) {
  output_buffers_.emplace_back(std::move(buffer), frame_count);
  total_frame_count_ += frame_count;
}

bool OpusDecoder::HandleEndOfStream(DiscardableSound& sound) {
  size_t frame_size = sizeof(int16_t) * channels_;
  size_t vmo_size = (total_frame_count_ - preskip_) * frame_size;

  zx_status_t status = sound.SetSize(vmo_size);
  if (status != ZX_OK) {
    return false;
  }

  uint16_t preskip_remaining = preskip_;
  uint64_t offset = 0;
  auto& vmo = sound.LockForWrite();
  auto unlocker = fit::defer([&sound]() { sound.Unlock(); });

  for (auto& output_buffer : output_buffers_) {
    if (preskip_remaining >= output_buffer.frame_count_) {
      preskip_remaining -= output_buffer.frame_count_;
      continue;
    }

    size_t size = (output_buffer.frame_count_ - preskip_remaining) * frame_size;
    status = vmo.write(output_buffer.samples_.get() + preskip_remaining * channels_, offset, size);
    if (status != ZX_OK) {
      FX_PLOGS(WARNING, status) << "zx::vmo::write failed";
      return false;
    }

    offset += size;
    preskip_remaining = 0;
  }

  sound.SetStreamType(
      fuchsia::media::AudioStreamType{.sample_format = fuchsia::media::AudioSampleFormat::SIGNED_16,
                                      .channels = channels_,
                                      .frames_per_second = kOutputFramesPerSecond});

  output_buffers_.clear();
  return true;
}

}  // namespace soundplayer
