// Copyright 2018 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 "garnet/bin/mediaplayer/fidl/fidl_decoder.h"
#include <vector>
#include "garnet/bin/mediaplayer/fidl/fidl_type_conversions.h"
#include "garnet/bin/mediaplayer/graph/formatting.h"
#include "garnet/bin/mediaplayer/graph/types/audio_stream_type.h"
#include "lib/fidl/cpp/clone.h"
#include "lib/fidl/cpp/optional.h"

namespace media_player {
namespace {

static const char kAacAdtsMimeType[] = "audio/aac-adts";

// Creates oob_bytes from a packet payload of at least 4 bytes.
std::vector<uint8_t> MakeOobBytesFromAdtsHeader(const uint8_t* adts_header) {
  std::vector<uint8_t> asc(2);

  // TODO(dustingreen): Switch from ADTS to .mp4 and fix AAC decoder to not
  // require "AudioSpecificConfig()" when fed ADTS.  In other words, move the
  // stuff here into a shim around the AAC OMX decoder, just next to (above or
  // below) the OmxCodecRunner in the codec_runner_sw_omx isolate, probably.

  // For SoftAAC2.cpp, for no particularly good reason, a CODECCONFIG buffer is
  // expected, even when running in ADTS mode, despite all the relevant data
  // being available from the ADTS header.  The CODECCONFIG buffer has an
  // AudioSpecificConfig in it.  The AudioSpecificConfig has to be created based
  // on corresponding fields of the ADTS header - not that requiring this of
  // the codec client makes any sense whatsoever...
  //
  // TODO(dustingreen): maybe add a per-codec compensation layer to un-crazy the
  // quirks of each codec.  For example, when decoding ADTS, all the needed info
  // is there in the ADTS stream directly.  No reason to hassle the codec client
  // for a pointless translated form of the same info.  In contrast, when it's
  // an mp4 file (or mkv, or whatever modern container format), the codec config
  // info is relevant.  But we should only force a client to provide it if
  // it's really needed.

  uint8_t profile_ObjectType;        // name in AAC spec in adts_fixed_header
  uint8_t sampling_frequency_index;  // name in AAC spec in adts_fixed_header
  uint8_t channel_configuration;     // name in AAC spec in adts_fixed_header
  profile_ObjectType = (adts_header[2] >> 6) & 0x3;
  sampling_frequency_index = (adts_header[2] >> 2) & 0xf;
  FXL_DCHECK(sampling_frequency_index < 11);
  channel_configuration = (adts_header[2] & 0x1) << 2 | (adts_header[3] >> 6);

  // Now let's convert these to the forms needed by AudioSpecificConfig.
  uint8_t audioObjectType =
      profile_ObjectType + 1;  // see near Table 1.A.11, for AAC not MPEG-2
  uint8_t samplingFrequencyIndex =
      sampling_frequency_index;                          // no conversion needed
  uint8_t channelConfiguration = channel_configuration;  // no conversion needed
  uint8_t frameLengthFlag = 0;
  uint8_t dependsOnCoreCoder = 0;
  uint8_t extensionFlag = 0;

  // Now we are ready to build a two-byte AudioSpecificConfig.  Not an
  // AudioSpecificInfo as stated in avc_utils.cpp (AOSP) mind you, but an
  // AudioSpecificConfig.
  asc[0] = (audioObjectType << 3) | (samplingFrequencyIndex >> 1);
  asc[1] = (samplingFrequencyIndex << 7) | (channelConfiguration << 3) |
           (frameLengthFlag << 2) | (dependsOnCoreCoder << 1) |
           (extensionFlag << 0);

  return asc;
}

}  // namespace

// static
void FidlDecoder::Create(
    const StreamType& stream_type,
    fuchsia::media::FormatDetails input_format_details,
    fuchsia::media::StreamProcessorPtr decoder,
    fit::function<void(std::shared_ptr<Decoder>)> callback) {
  auto fidl_decoder = std::make_shared<FidlDecoder>(
      stream_type, std::move(input_format_details));
  fidl_decoder->Init(
      std::move(decoder),
      [fidl_decoder, callback = std::move(callback)](bool succeeded) {
        callback(succeeded ? fidl_decoder : nullptr);
      });
}

FidlDecoder::FidlDecoder(
    const StreamType& stream_type,
    fuchsia::media::FormatDetails input_format_details)
    : medium_(stream_type.medium()),
      input_format_details_(std::move(input_format_details)) {
  update_oob_bytes_ = (input_format_details_.mime_type == kAacAdtsMimeType);

  switch (medium_) {
    case StreamType::Medium::kAudio:
      output_stream_type_ =
          AudioStreamType::Create(StreamType::kAudioEncodingLpcm, nullptr,
                                  AudioStreamType::SampleFormat::kNone, 1, 1);
      break;
    case StreamType::Medium::kVideo:
      output_stream_type_ = VideoStreamType::Create(
          StreamType::kVideoEncodingUncompressed, nullptr,
          VideoStreamType::PixelFormat::kUnknown,
          VideoStreamType::ColorSpace::kUnknown, 0, 0, 0, 0, 1, 1, 0);
      break;
    case StreamType::Medium::kText:
    case StreamType::Medium::kSubpicture:
      FXL_CHECK(false) << "Only audio and video are supported.";
      break;
  }
}

void FidlDecoder::Init(fuchsia::media::StreamProcessorPtr decoder,
                       fit::function<void(bool)> callback) {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
  FXL_DCHECK(decoder);
  FXL_DCHECK(callback);

  outboard_decoder_ = std::move(decoder);
  init_callback_ = std::move(callback);

  outboard_decoder_.set_error_handler(
      fit::bind_member(this, &FidlDecoder::OnConnectionFailed));

  outboard_decoder_.events().OnStreamFailed =
      fit::bind_member(this, &FidlDecoder::OnStreamFailed);
  outboard_decoder_.events().OnInputConstraints =
      fit::bind_member(this, &FidlDecoder::OnInputConstraints);
  outboard_decoder_.events().OnOutputConfig =
      fit::bind_member(this, &FidlDecoder::OnOutputConfig);
  outboard_decoder_.events().OnOutputPacket =
      fit::bind_member(this, &FidlDecoder::OnOutputPacket);
  outboard_decoder_.events().OnOutputEndOfStream =
      fit::bind_member(this, &FidlDecoder::OnOutputEndOfStream);
  outboard_decoder_.events().OnFreeInputPacket =
      fit::bind_member(this, &FidlDecoder::OnFreeInputPacket);

  outboard_decoder_->EnableOnStreamFailed();
}

FidlDecoder::~FidlDecoder() {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
}

const char* FidlDecoder::label() const { return "fidl decoder"; }

void FidlDecoder::Dump(std::ostream& os) const {
  Node::Dump(os);
  // TODO(dalesat): More.
}

void FidlDecoder::ConfigureConnectors() {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);

  MaybeConfigureInput(nullptr);
  MaybeConfigureOutput(nullptr);
}

void FidlDecoder::OnInputConnectionReady(size_t input_index) {
  FXL_DCHECK(input_index == 0);

  if (add_input_buffers_pending_) {
    add_input_buffers_pending_ = false;
    AddInputBuffers();
  }
}

void FidlDecoder::FlushInput(bool hold_frame, size_t input_index,
                             fit::closure callback) {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
  FXL_DCHECK(input_index == 0);
  FXL_DCHECK(callback);

  // This decoder will always receive a FlushOutput shortly after a FlushInput.
  // We call CloseCurrentStream now to let the outboard decoder know we're
  // abandoning this stream. Incrementing stream_lifetime_ordinal_ will cause
  // any stale output packets to be discarded. When FlushOutput is called, we'll
  // sync with the outboard decoder to make sure we're all caught up.
  outboard_decoder_->CloseCurrentStream(stream_lifetime_ordinal_, false, false);
  stream_lifetime_ordinal_ += 2;
  end_of_input_stream_ = false;
  update_oob_bytes_ = (input_format_details_.mime_type == kAacAdtsMimeType);
  flushing_ = true;

  callback();
}

void FidlDecoder::PutInputPacket(PacketPtr packet, size_t input_index) {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
  FXL_DCHECK(packet);
  FXL_DCHECK(input_index == 0);
  FXL_DCHECK(input_buffers_.has_current_set());

  if (flushing_) {
    return;
  }

  if (pts_rate_ == media::TimelineRate()) {
    pts_rate_ = packet->pts_rate();
  } else {
    FXL_DCHECK(pts_rate_ == packet->pts_rate());
  }

  if (packet->size() != 0) {
    // The buffer attached to this packet will be one we created using
    // |input_buffers_|.

    BufferSet& current_set = input_buffers_.current_set();

    // TODO(dalesat): Remove when the aac/adts decoder no longer needs this
    // help.
    if (update_oob_bytes_ && packet->size() >= 4) {
      FXL_DCHECK(packet->payload());

      input_format_details_.oob_bytes =
          fidl::VectorPtr<uint8_t>(MakeOobBytesFromAdtsHeader(
              static_cast<const uint8_t*>(packet->payload())));

      outboard_decoder_->QueueInputFormatDetails(
          stream_lifetime_ordinal_, fidl::Clone(input_format_details_));
      update_oob_bytes_ = false;
    }

    FXL_DCHECK(packet->payload_buffer()->id() < current_set.buffer_count())
        << "Buffer ID " << packet->payload_buffer()->id()
        << " is out of range, should be less than "
        << current_set.buffer_count();
    current_set.AddRefBufferForDecoder(packet->payload_buffer()->id(),
                                       packet->payload_buffer());

    fuchsia::media::Packet codec_packet;
    codec_packet.header.buffer_lifetime_ordinal =
        current_set.lifetime_ordinal();
    codec_packet.header.packet_index = packet->payload_buffer()->id();
    codec_packet.buffer_index = packet->payload_buffer()->id();
    codec_packet.stream_lifetime_ordinal = stream_lifetime_ordinal_;
    codec_packet.start_offset = 0;
    codec_packet.valid_length_bytes = packet->size();
    codec_packet.timestamp_ish = static_cast<uint64_t>(packet->pts());
    codec_packet.has_timestamp_ish = true;
    codec_packet.start_access_unit = packet->keyframe();
    codec_packet.known_end_access_unit = false;

    FXL_DCHECK(packet->size() <= current_set.buffer_size());

    outboard_decoder_->QueueInputPacket(std::move(codec_packet));
  }

  if (packet->end_of_stream()) {
    end_of_input_stream_ = true;
    outboard_decoder_->QueueInputEndOfStream(stream_lifetime_ordinal_);
  }
}

void FidlDecoder::OnOutputConnectionReady(size_t output_index) {
  FXL_DCHECK(output_index == 0);

  if (add_output_buffers_pending_) {
    add_output_buffers_pending_ = false;
    AddOutputBuffers();
  }
}

void FidlDecoder::FlushOutput(size_t output_index, fit::closure callback) {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
  FXL_DCHECK(output_index == 0);
  FXL_DCHECK(callback);

  // This decoder will always receive a FlushInput shortly before a FlushOutput.
  // In FlushInput, we've already closed the stream. Now we sync with the
  // output decoder just to make sure we're caught up.
  outboard_decoder_->Sync(std::move(callback));
}

void FidlDecoder::RequestOutputPacket() {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
  flushing_ = false;

  MaybeRequestInputPacket();
}

std::unique_ptr<StreamType> FidlDecoder::output_stream_type() const {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
  FXL_DCHECK(output_stream_type_);
  return output_stream_type_->Clone();
}

void FidlDecoder::InitSucceeded() {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);

  if (init_callback_) {
    auto callback = std::move(init_callback_);
    callback(true);
  }
}

void FidlDecoder::InitFailed() {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);

  if (init_callback_) {
    auto callback = std::move(init_callback_);
    callback(false);
  }
}

void FidlDecoder::MaybeConfigureInput(
    fuchsia::media::StreamBufferConstraints* constraints) {
  if (constraints == nullptr) {
    // We have no constraints to apply. Defer the configuration.
    ConfigureInputDeferred();
    return;
  }

  FXL_DCHECK(input_buffers_.has_current_set());

  BufferSet& current_set = input_buffers_.current_set();
  ConfigureInputToUseVmos(
      0, current_set.buffer_count(), current_set.buffer_size(),
      current_set.single_vmo() ? VmoAllocation::kSingleVmo
                               : VmoAllocation::kVmoPerBuffer,
      constraints->is_physically_contiguous_required,
      std::move(constraints->very_temp_kludge_bti_handle),
      [this, &current_set](uint64_t size, const PayloadVmos& payload_vmos) {
        // This callback runs on an arbitrary thread.
        return current_set.AllocateBuffer(size, payload_vmos);
      });

  if (InputConnectionReady()) {
    AddInputBuffers();
  } else {
    add_input_buffers_pending_ = true;
  }
}

void FidlDecoder::AddInputBuffers() {
  FXL_DCHECK(InputConnectionReady());

  BufferSet& current_set = input_buffers_.current_set();
  for (uint32_t index = 0; index < current_set.buffer_count(); ++index) {
    auto descriptor =
        current_set.GetBufferDescriptor(index, false, UseInputVmos());
    outboard_decoder_->AddInputBuffer(std::move(descriptor));
  }
}

void FidlDecoder::MaybeConfigureOutput(
    fuchsia::media::StreamBufferConstraints* constraints) {
  FXL_DCHECK(constraints == nullptr ||
             constraints->per_packet_buffer_bytes_max != 0);

  if (constraints == nullptr) {
    // We have no constraints to apply. Defer the configuration.
    ConfigureOutputDeferred();
    return;
  }

  FXL_DCHECK(output_buffers_.has_current_set());
  FXL_DCHECK(output_stream_type_);

  // TODO(dalesat): Do we need to add some buffers for queueing?
  BufferSet& current_set = output_buffers_.current_set();
  output_vmos_physically_contiguous_ =
      constraints->is_physically_contiguous_required;
  ConfigureOutputToUseVmos(
      0, current_set.buffer_count(), current_set.buffer_size(),
      current_set.single_vmo() ? VmoAllocation::kSingleVmo
                               : VmoAllocation::kVmoPerBuffer,
      output_vmos_physically_contiguous_,
      std::move(constraints->very_temp_kludge_bti_handle));

  if (OutputConnectionReady()) {
    AddOutputBuffers();
  } else {
    add_output_buffers_pending_ = true;
  }
}

void FidlDecoder::AddOutputBuffers() {
  FXL_DCHECK(OutputConnectionReady());

  // We allocate all the buffers on behalf of the outboard decoder. We give
  // the outboard decoder ownership of these buffers as long as this set is
  // current. The decoder decides what buffers to use for output. When an
  // output packet is produced, the player shares ownership of the buffer until
  // all packets referencing the buffer are recycled. This ownership model
  // reflects the fact that the outboard decoder is free to use output buffers
  // as references and even use the same output buffer for multiple packets as
  // happens with VP9.
  BufferSet& current_set = output_buffers_.current_set();
  current_set.AllocateAllBuffersForDecoder(UseOutputVmos());

  for (uint32_t index = 0; index < current_set.buffer_count(); ++index) {
    auto descriptor =
        current_set.GetBufferDescriptor(index, true, UseOutputVmos());
    outboard_decoder_->AddOutputBuffer(std::move(descriptor));
  }
}

void FidlDecoder::MaybeRequestInputPacket() {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);

  if (!flushing_ && input_buffers_.has_current_set() && !end_of_input_stream_) {
    // |HasFreeBuffer| returns true if there's a free buffer. If there's no
    // free buffer, it will call the callback when there is one.
    if (!input_buffers_.current_set().HasFreeBuffer(
            [this]() { PostTask([this]() { MaybeRequestInputPacket(); }); })) {
      return;
    }

    if (!have_real_output_stream_type_) {
      if (pre_stream_type_packet_requests_remaining_ != 0) {
        --pre_stream_type_packet_requests_remaining_;
      } else {
        return;
      }
    }

    RequestInputPacket();
  }
}

void FidlDecoder::OnConnectionFailed(zx_status_t error) {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);

  InitFailed();
  // TODO(dalesat): Report failure.
}

void FidlDecoder::OnStreamFailed(uint64_t stream_lifetime_ordinal) {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
  // TODO(dalesat): Report failure.
}

void FidlDecoder::OnInputConstraints(
    fuchsia::media::StreamBufferConstraints constraints) {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);
  FXL_DCHECK(!input_buffers_.has_current_set())
      << "OnInputConstraints received more than once.";

  input_buffers_.ApplyConstraints(constraints, true);
  FXL_DCHECK(input_buffers_.has_current_set());
  BufferSet& current_set = input_buffers_.current_set();

  MaybeConfigureInput(&constraints);

  outboard_decoder_->SetInputBufferSettings(current_set.settings());

  InitSucceeded();
}

void FidlDecoder::OnOutputConfig(
    fuchsia::media::StreamOutputConfig config) {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);

  auto stream_type =
      fxl::To<std::unique_ptr<StreamType>>(config.format_details);
  if (!stream_type) {
    FXL_LOG(ERROR) << "Can't comprehend format details.";
    InitFailed();
    return;
  }

  if (output_stream_type_) {
    if (output_format_details_version_ordinal_ !=
        config.format_details.format_details_version_ordinal) {
      HandlePossibleOutputStreamTypeChange(*output_stream_type_, *stream_type);
    }
  }

  output_format_details_version_ordinal_ =
      config.format_details.format_details_version_ordinal;

  output_stream_type_ = std::move(stream_type);
  have_real_output_stream_type_ = true;

  if (!config.buffer_constraints_action_required) {
    if (init_callback_) {
      FXL_LOG(ERROR)
          << "OnOutputConfig: action not required on initial config.";
      InitFailed();
    }

    return;
  }

  if (output_buffers_.has_current_set()) {
    // All the old output buffers were owned by the outboard decoder. We release
    // that ownership. The buffers will continue to exist until all packets
    // referencing them are destroyed.
    output_buffers_.current_set().ReleaseAllDecoderOwnedBuffers();
  }

  // Use a single VMO for audio, VMO per buffer for video.
  output_buffers_.ApplyConstraints(
      config.buffer_constraints,
      output_stream_type_->medium() == StreamType::Medium::kAudio);

  FXL_DCHECK(output_buffers_.has_current_set());
  BufferSet& current_set = output_buffers_.current_set();

  outboard_decoder_->SetOutputBufferSettings(current_set.settings());

  // Create the VMOs when we're ready, and add them to the outboard decoder.
  MaybeConfigureOutput(&config.buffer_constraints);
};

void FidlDecoder::OnOutputPacket(fuchsia::media::Packet packet,
                                 bool error_detected_before,
                                 bool error_detected_during) {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);

  uint64_t buffer_lifetime_ordinal = packet.header.buffer_lifetime_ordinal;
  uint32_t packet_index = packet.header.packet_index;
  uint32_t buffer_index = packet.buffer_index;
  FXL_DCHECK(buffer_index != 0x80000000);

  if (error_detected_before) {
    FXL_LOG(WARNING) << "OnOutputPacket: error_detected_before";
  }

  if (error_detected_during) {
    FXL_LOG(WARNING) << "OnOutputPacket: error_detected_during";
  }

  if (!output_buffers_.has_current_set()) {
    FXL_LOG(FATAL) << "OnOutputPacket event without prior OnOutputConfig event";
    // TODO(dalesat): Report error rather than crashing.
  }

  BufferSet& current_set = output_buffers_.current_set();

  if (packet.header.buffer_lifetime_ordinal != current_set.lifetime_ordinal()) {
    // Refers to an obsolete buffer. We've already assumed the outboard
    // decoder gave up this buffer, so there's no need to free it. Also, this
    // shouldn't happen, and there's no evidence that it does.
    FXL_LOG(FATAL) << "OnOutputPacket delivered tacket with obsolete "
                      "buffer_lifetime_ordinal.";
    return;
  }

  if (packet.stream_lifetime_ordinal != stream_lifetime_ordinal_) {
    // Refers to an obsolete stream. We'll just recycle the packet back to the
    // output decoder.
    outboard_decoder_->RecycleOutputPacket(std::move(packet.header));
    return;
  }

  // All the output buffers in the current set are always owned by the outboard
  // decoder. Get another reference to the |PayloadBuffer| for the specified
  // buffer.
  FXL_DCHECK(buffer_lifetime_ordinal == current_set.lifetime_ordinal());
  fbl::RefPtr<PayloadBuffer> payload_buffer =
      current_set.GetDecoderOwnedBuffer(buffer_index);

  // TODO(dalesat): Tolerate !has_timestamp_ish somehow.
  if (!packet.has_timestamp_ish) {
    FXL_LOG(ERROR) << "We demand has_timestamp_ish for now (TODO)";
    return;
  }

  next_pts_ = static_cast<int64_t>(packet.timestamp_ish);

  auto output_packet =
      Packet::Create(next_pts_, pts_rate_, true, false,
                     packet.valid_length_bytes, std::move(payload_buffer));

  if (revised_output_stream_type_) {
    output_packet->SetRevisedStreamType(std::move(revised_output_stream_type_));
  }

  output_packet->AfterRecycling(
      [this, shared_this = shared_from_this(), packet_index](Packet* packet) {
        PostTask([this, shared_this, packet_index,
                  buffer_lifetime_ordinal =
                      packet->payload_buffer()->buffer_config()]() {
          FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);

          // |outboard_decoder_| is always set after |Init| is called, so we
          // can rely on it here.
          FXL_DCHECK(outboard_decoder_);
          outboard_decoder_->RecycleOutputPacket(
              fuchsia::media::PacketHeader{
                  .buffer_lifetime_ordinal = buffer_lifetime_ordinal,
                  .packet_index = packet_index});
        });
      });

  PutOutputPacket(std::move(output_packet));
}

void FidlDecoder::OnOutputEndOfStream(uint64_t stream_lifetime_ordinal,
                                      bool error_detected_before) {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);

  if (error_detected_before) {
    FXL_LOG(WARNING) << "OnOutputEndOfStream: error_detected_before";
  }

  PutOutputPacket(Packet::CreateEndOfStream(next_pts_, pts_rate_));
}

void FidlDecoder::OnFreeInputPacket(
    fuchsia::media::PacketHeader packet_header) {
  FXL_DCHECK_CREATION_THREAD_IS_CURRENT(thread_checker_);

  input_buffers_.ReleaseBufferForDecoder(packet_header.buffer_lifetime_ordinal,
                                         packet_header.packet_index);
}

void FidlDecoder::HandlePossibleOutputStreamTypeChange(
    const StreamType& old_type, const StreamType& new_type) {
  // TODO(dalesat): Actually compare the types.
  revised_output_stream_type_ = new_type.Clone();
}

}  // namespace media_player
