// 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.

#ifndef SRC_MEDIA_PLAYBACK_MEDIAPLAYER_GRAPH_PAYLOADS_PAYLOAD_BUFFER_H_
#define SRC_MEDIA_PLAYBACK_MEDIAPLAYER_GRAPH_PAYLOADS_PAYLOAD_BUFFER_H_

#include <fbl/recycler.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <fbl/unique_ptr.h>
#include <lib/fit/function.h>
#include <lib/fzl/vmo-mapper.h>
#include <lib/zx/vmo.h>

#include <memory>

#include "src/lib/fxl/logging.h"
#include "src/media/playback/mediaplayer/graph/payloads/fifo_allocator.h"

namespace media_player {

class VmoPayloadAllocator;

// A VMO used for payload buffers.
class PayloadVmo : public fbl::RefCounted<PayloadVmo> {
 public:
  // Creates a VMO and wraps it with a |PayloadVmo|. If |bti_handle| is
  // provided, the VMO is created with |zx_vmo_create_contiguous|.
  // TODO(dalesat): Remove |bti_handle| when the fidl buffer allocator happens.
  static fbl::RefPtr<PayloadVmo> Create(uint64_t vmo_size,
                                        const zx::handle* bti_handle = nullptr);

  // Creates a |PayloadVmo| that wraps the provided VMO.
  static fbl::RefPtr<PayloadVmo> Create(zx::vmo vmo, zx_vm_option_t map_flags);

  PayloadVmo(zx::vmo vmo, uint64_t vmo_size, zx_vm_option_t map_flags,
             const zx::handle* bti_handle, zx_status_t* status_out);

  ~PayloadVmo() = default;

  // Returns the size of the VMO in bytes.
  uint64_t size() const { return size_; }

  // Returns the address in process virtual memory where this VMO is mapped, if
  // it is mapped, nullptr otherwise.
  void* start() const { return vmo_mapper_.start(); }

  // The index of this VMO in the allocator's vector of VMOs.
  uint32_t index() { return index_; }

  // Sets the index of this VMO in the allocator's vector of VMOs.
  void SetIndex(uint32_t index) { index_ = index; }

  // Returns |start()| offset by |offset| if the VMO is mapped, nullptr
  // otherwise.
  void* at_offset(uint64_t offset) {
    FXL_DCHECK(offset < size_);

    if (start() == nullptr) {
      return nullptr;
    }

    return reinterpret_cast<uint8_t*>(start()) + offset;
  }

  // Returns a reference to the VMO.
  zx::vmo& vmo() { return vmo_; }
  const zx::vmo& vmo() const { return vmo_; }

  // Duplicates the VMO creating a new VMO handle with the specified rights.
  zx::vmo Duplicate(zx_rights_t rights);

 private:
  zx::vmo vmo_;
  uint64_t size_;
  uint32_t index_;

  fzl::VmoMapper vmo_mapper_;

  // NOTE: Access to these two fields is serialized using the mutex on the
  // owning |VmoPayloadAllocator|.
  bool allocated_ = false;
  fbl::unique_ptr<FifoAllocator> allocator_;

  friend class VmoPayloadAllocator;
};

// A buffer used to hold a packet payload.
//
// A |PayloadBuffer| instance is managed using |fbl::RefPtr| and has an
// associated recycler, which is responsible for freeing the memory that the
// |PayloadBuffer| encapsulates. When the last reference to a |PayloadBuffer|
// is dropped, the recycler is called.
class PayloadBuffer final : public fbl::RefCounted<PayloadBuffer>,
                            public fbl::Recyclable<PayloadBuffer> {
 public:
  // All payload buffers must be aligned on |kByteAlignment|-byte boundaries.
  static constexpr size_t kByteAlignment = 32;

  // Returns the smallest multiple of |kByteAlignment| that is no smaller than
  // |size|.
  static size_t AlignUp(size_t size) {
    return size = (size + kByteAlignment - 1) & ~(kByteAlignment - 1);
  }

  // Indicates whether |buffer| is aligned to |kByteAlignment| bytes.
  static bool IsAligned(void* buffer) {
    return (reinterpret_cast<uintptr_t>(buffer) & (kByteAlignment - 1)) == 0;
  }

  // Function type used to recycle a |PayloadBuffer|. The |PayloadBuffer|
  // deletes itself, so the recycler should not attempt to delete it.
  using Recycler = fit::function<void(PayloadBuffer*)>;

  // Function type used for |AfterRecycling|.
  using Action = fit::function<void(PayloadBuffer*)>;

  // Creates a new |PayloadBuffer|. |size| may not be 0, and |data| may not be
  // nullptr.
  static fbl::RefPtr<PayloadBuffer> Create(uint64_t size, void* data,
                                           Recycler recycler);

  // Creates a new |PayloadBuffer|. |size| may not be 0, and |data| may not be
  // nullptr. |offset_in_vmo| gives the offset of the buffer with respect to
  // the start of the VMO. This should be (data - vmo.start()). This
  // redundancy is for future support of VMOs that can't be mapped.
  // TODO(dalesat): Support null data for payloads that can't be mapped.
  static fbl::RefPtr<PayloadBuffer> Create(uint64_t size, void* data,
                                           fbl::RefPtr<PayloadVmo> vmo,
                                           uint64_t offset_in_vmo,
                                           Recycler recycler);

  static fbl::RefPtr<PayloadBuffer> CreateWithMalloc(uint64_t size);

  ~PayloadBuffer();

  // Returns the size in bytes of the buffer, which will never be 0.
  uint64_t size() const { return size_; }

  // Returns a pointer to the buffer, which will never be nullptr.
  void* data() const { return data_; }

  // Returns the |PayloadVmo| containing the buffer, if the buffer was allocated
  // from a VMO, nullptr otherwise.
  PayloadVmo* vmo() const { return vmo_.get(); }

  // Returns the offset of the data in the VMO, if the buffer was allocated from
  // a VMO, zero otherwise.
  uint64_t offset() const { return offset_; }

  // Returns the ID of this |PayloadBuffer|. This value is set by the party
  // that creates the buffer, and its semantics are defined by that party. It
  // is intended to identify the buffer and may correspond to the fidl field
  // media.StreamPacket.payload_buffer_id or
  // mediacodec.CodecBuffer.buffer_index.
  uint32_t id() const { return id_; }

  // Sets the ID of this |PayloadBuffer|.
  void SetId(uint32_t id) { id_ = id; }

  // Returns the buffer config of this |PayloadBuffer|. This value is set by the
  // party that creates the buffer, and its semantics are defined by that party.
  // It is intended to identify the buffer configuration and may correspond to
  // the fidl field media.StreamPacket.buffer_config or
  // mediacodec.CodecBuffer.buffer_lifetime_ordinal.
  uint64_t buffer_config() const { return buffer_config_; }

  // Sets the ID of this |PayloadBuffer|.
  void SetBufferConfig(uint64_t buffer_config) {
    buffer_config_ = buffer_config;
  }

  // Registers a function to be called after recycling. This method may only
  // be called once on a given instance. An |Action| should not hold a reference
  // to the |PayloadBuffer|, because this would produce a circular reference,
  // and the |PayloadBuffer| would never be released.
  void AfterRecycling(Action action);

 private:
  PayloadBuffer(uint64_t size, void* data, Recycler recycler);

  PayloadBuffer(uint64_t size, void* data, fbl::RefPtr<PayloadVmo> vmo,
                uint64_t offset, Recycler recycler);

  void fbl_recycle();

  uint64_t size_;
  void* data_;
  fbl::RefPtr<PayloadVmo> vmo_;
  uint64_t offset_;
  uint32_t id_ = 0;
  uint64_t buffer_config_ = 0;
  Recycler recycler_;
  Action after_recycling_;

  friend class fbl::Recyclable<PayloadBuffer>;
};

}  // namespace media_player

#endif  // SRC_MEDIA_PLAYBACK_MEDIAPLAYER_GRAPH_PAYLOADS_PAYLOAD_BUFFER_H_
