// Copyright 2016 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/playback/mediaplayer/graph/nodes/input.h"

#include <atomic>

#include "src/media/playback/mediaplayer/graph/nodes/node.h"
#include "src/media/playback/mediaplayer/graph/nodes/output.h"

namespace media_player {
namespace {

// Creates a copy of |original| with |copied_payload_buffer| replacing the
// original's payload buffer. |copied_payload_buffer| may be nullptr if and
// only if |original| has no payload.
PacketPtr CopyPacket(const Packet& original,
                     fbl::RefPtr<PayloadBuffer> copied_payload_buffer) {
  FXL_DCHECK(copied_payload_buffer ||
             (original.size() == 0 && !original.payload_buffer()));

  PacketPtr copy =
      Packet::Create(original.pts(), original.pts_rate(), original.keyframe(),
                     original.end_of_stream(), original.size(),
                     std::move(copied_payload_buffer));

  if (original.revised_stream_type()) {
    copy->SetRevisedStreamType(original.revised_stream_type()->Clone());
  }

  return copy;
}

}  // namespace

Input::Input(Node* node, size_t index)
    : node_(node), index_(index), state_(State::kRefusesPacket) {
  FXL_DCHECK(node_);
}

Input::Input(Input&& input)
    : node_(input.node()), index_(input.index()), state_(input.state_.load()) {
  // We can't move an input that's connected, has a packet or is configured.
  // TODO(dalesat): Make |Input| non-movable.
  FXL_DCHECK(input.mate() == nullptr);
  FXL_DCHECK(input.packet() == nullptr);
  FXL_DCHECK(input.payload_config().mode_ == PayloadMode::kNotConfigured);
}

Input::~Input() {}

void Input::Connect(Output* output) {
  FXL_DCHECK(output);
  FXL_DCHECK(!mate_);
  mate_ = output;
}

bool Input::needs_packet() const {
  return state_.load() == State::kNeedsPacket;
}

void Input::PutPacket(PacketPtr packet) {
  FXL_DCHECK(packet);
  FXL_DCHECK(needs_packet());

  std::atomic_store(&packet_, packet);
  state_.store(State::kHasPacket);
  node_->NeedsUpdate();
}

PacketPtr Input::TakePacket(bool request_another) {
  FXL_DCHECK(mate_);

  PacketPtr no_packet;
  PacketPtr packet = std::atomic_exchange(&packet_, no_packet);

  if (request_another) {
    state_.store(State::kNeedsPacket);
    mate_->node()->NeedsUpdate();
  } else {
    state_.store(State::kRefusesPacket);
  }

  if (!packet) {
    return nullptr;
  }

  size_t size = packet->size();

  fbl::RefPtr<PayloadBuffer> copy_destination_buffer;
  if (!payload_manager_.MaybeAllocatePayloadBufferForCopy(
          size, &copy_destination_buffer)) {
    // Copying is not required, so we just return the packet.
    return packet;
  }

  if (size == 0) {
    // Copying is required, but there's no payload. Return a new packet with the
    // same attributes as |packet|.
    return CopyPacket(*packet, nullptr);
  }

  if (!copy_destination_buffer) {
    // We just drop the packet, so there will be a glitch.
    FXL_LOG(WARNING) << "Allocator starved copying payload.";

    // We needed a packet and couldn't produce one, so we still need one.
    state_.store(State::kNeedsPacket);
    mate_->node()->NeedsUpdate();

    return nullptr;
  }

  // Copy the payload.
  FXL_DCHECK(copy_destination_buffer->size() >= size);
  memcpy(copy_destination_buffer->data(), packet->payload(), size);

  // Return a new packet like |packet| but with the new payload buffer.
  return CopyPacket(*packet, std::move(copy_destination_buffer));
}

void Input::RequestPacket() {
  FXL_DCHECK(mate_);

  State expected = State::kRefusesPacket;
  if (state_.compare_exchange_strong(expected, State::kNeedsPacket)) {
    mate_->node()->NeedsUpdate();
  }
}

void Input::Flush() { TakePacket(false); }

}  // namespace media_player
