/*
 * Copyright 2019 The libgav1 Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef LIBGAV1_SRC_BUFFER_POOL_H_
#define LIBGAV1_SRC_BUFFER_POOL_H_

#include <array>
#include <cassert>
#include <climits>
#include <condition_variable>  // NOLINT (unapproved c++11 header)
#include <cstdint>
#include <cstring>
#include <mutex>  // NOLINT (unapproved c++11 header)

#include "src/dsp/common.h"
#include "src/gav1/decoder_buffer.h"
#include "src/gav1/frame_buffer.h"
#include "src/internal_frame_buffer_list.h"
#include "src/symbol_decoder_context.h"
#include "src/utils/compiler_attributes.h"
#include "src/utils/constants.h"
#include "src/utils/reference_info.h"
#include "src/utils/segmentation.h"
#include "src/utils/segmentation_map.h"
#include "src/utils/types.h"
#include "src/utils/vector.h"
#include "src/yuv_buffer.h"

namespace libgav1 {

class BufferPool;

enum FrameState : uint8_t {
  kFrameStateUnknown,
  kFrameStateStarted,
  kFrameStateParsed,
  kFrameStateDecoded
};

// A reference-counted frame buffer. Clients should access it via
// RefCountedBufferPtr, which manages reference counting transparently.
class RefCountedBuffer {
 public:
  // Not copyable or movable.
  RefCountedBuffer(const RefCountedBuffer&) = delete;
  RefCountedBuffer& operator=(const RefCountedBuffer&) = delete;

  // Allocates the YUV buffer. Returns true on success. Returns false on
  // failure. This function ensures the thread safety of the |get_frame_buffer_|
  // call (i.e.) only one |get_frame_buffer_| call will happen at a given time.
  // TODO(b/142583029): In frame parallel mode, we can require the callbacks to
  // be thread safe so that we can remove the thread safety of this function and
  // applications can have fine grained locks.
  //
  // * |width| and |height| are the image dimensions in pixels.
  // * |subsampling_x| and |subsampling_y| (either 0 or 1) specify the
  //   subsampling of the width and height of the chroma planes, respectively.
  // * |left_border|, |right_border|, |top_border|, and |bottom_border| are
  //   the sizes (in pixels) of the borders on the left, right, top, and
  //   bottom sides, respectively.
  //
  // NOTE: The strides are a multiple of 16. Since the first row in each plane
  // is 16-byte aligned, subsequent rows are also 16-byte aligned.
  bool Realloc(int bitdepth, bool is_monochrome, int width, int height,
               int subsampling_x, int subsampling_y, int left_border,
               int right_border, int top_border, int bottom_border);

  YuvBuffer* buffer() { return &yuv_buffer_; }

  // Returns the buffer private data set by the get frame buffer callback when
  // it allocated the YUV buffer.
  void* buffer_private_data() const {
    assert(buffer_private_data_valid_);
    return buffer_private_data_;
  }

  // NOTE: In the current frame, this is the frame_type syntax element in the
  // frame header. In a reference frame, this implements the RefFrameType array
  // in the spec.
  FrameType frame_type() const { return frame_type_; }
  void set_frame_type(FrameType frame_type) { frame_type_ = frame_type; }

  // The sample position for subsampled streams. This is the
  // chroma_sample_position syntax element in the sequence header.
  //
  // NOTE: The decoder does not use chroma_sample_position, but it needs to be
  // passed on to the client in DecoderBuffer.
  ChromaSamplePosition chroma_sample_position() const {
    return chroma_sample_position_;
  }
  void set_chroma_sample_position(ChromaSamplePosition chroma_sample_position) {
    chroma_sample_position_ = chroma_sample_position;
  }

  // Whether the frame can be used as show existing frame in the future.
  bool showable_frame() const { return showable_frame_; }
  void set_showable_frame(bool value) { showable_frame_ = value; }

  // Sets upscaled_width_, frame_width_, frame_height_, render_width_,
  // render_height_, rows4x4_ and columns4x4_ from the corresponding fields
  // in frame_header. Allocates reference_info_.motion_field_reference_frame,
  // reference_info_.motion_field_mv_, and segmentation_map_. Returns true on
  // success, false on failure.
  bool SetFrameDimensions(const ObuFrameHeader& frame_header);

  int32_t upscaled_width() const { return upscaled_width_; }
  int32_t frame_width() const { return frame_width_; }
  int32_t frame_height() const { return frame_height_; }
  // RenderWidth() and RenderHeight() return the render size, which is a hint
  // to the application about the desired display size.
  int32_t render_width() const { return render_width_; }
  int32_t render_height() const { return render_height_; }
  int32_t rows4x4() const { return rows4x4_; }
  int32_t columns4x4() const { return columns4x4_; }

  int spatial_id() const { return spatial_id_; }
  void set_spatial_id(int value) { spatial_id_ = value; }
  int temporal_id() const { return temporal_id_; }
  void set_temporal_id(int value) { temporal_id_ = value; }

  SegmentationMap* segmentation_map() { return &segmentation_map_; }
  const SegmentationMap* segmentation_map() const { return &segmentation_map_; }

  // Only the |params| field of each GlobalMotion struct should be used.
  const std::array<GlobalMotion, kNumReferenceFrameTypes>& GlobalMotions()
      const {
    return global_motion_;
  }
  // Saves the GlobalMotion array. Only the |params| field of each GlobalMotion
  // struct is saved.
  void SetGlobalMotions(
      const std::array<GlobalMotion, kNumReferenceFrameTypes>& global_motions);

  // Returns the saved CDF tables.
  const SymbolDecoderContext& FrameContext() const { return frame_context_; }
  // Saves the CDF tables. The intra_frame_y_mode_cdf table is reset to the
  // default. The last entry in each table, representing the symbol count for
  // that context, is set to 0.
  void SetFrameContext(const SymbolDecoderContext& context);

  const std::array<int8_t, kNumReferenceFrameTypes>& loop_filter_ref_deltas()
      const {
    return loop_filter_ref_deltas_;
  }
  const std::array<int8_t, kLoopFilterMaxModeDeltas>& loop_filter_mode_deltas()
      const {
    return loop_filter_mode_deltas_;
  }
  // Saves the ref_deltas and mode_deltas arrays in loop_filter.
  void SetLoopFilterDeltas(const LoopFilter& loop_filter) {
    loop_filter_ref_deltas_ = loop_filter.ref_deltas;
    loop_filter_mode_deltas_ = loop_filter.mode_deltas;
  }

  // Copies the saved values of the following fields to the Segmentation
  // struct: feature_enabled, feature_data, segment_id_pre_skip, and
  // last_active_segment_id. The other fields are left unchanged.
  void GetSegmentationParameters(Segmentation* segmentation) const;
  // Saves the feature_enabled, feature_data, segment_id_pre_skip, and
  // last_active_segment_id fields of the Segmentation struct.
  void SetSegmentationParameters(const Segmentation& segmentation);

  const FilmGrainParams& film_grain_params() const {
    return film_grain_params_;
  }
  void set_film_grain_params(const FilmGrainParams& params) {
    film_grain_params_ = params;
  }

  const ReferenceInfo* reference_info() const { return &reference_info_; }
  ReferenceInfo* reference_info() { return &reference_info_; }

  // This will wake up the WaitUntil*() functions and make them return false.
  void Abort() {
    {
      std::lock_guard<std::mutex> lock(mutex_);
      abort_ = true;
    }
    parsed_condvar_.notify_all();
    decoded_condvar_.notify_all();
    progress_row_condvar_.notify_all();
  }

  void SetFrameState(FrameState frame_state) {
    {
      std::lock_guard<std::mutex> lock(mutex_);
      frame_state_ = frame_state;
    }
    if (frame_state == kFrameStateParsed) {
      parsed_condvar_.notify_all();
    } else if (frame_state == kFrameStateDecoded) {
      decoded_condvar_.notify_all();
      progress_row_condvar_.notify_all();
    }
  }

  // Sets the progress of this frame to |progress_row| and notifies any threads
  // that may be waiting on rows <= |progress_row|.
  void SetProgress(int progress_row) {
    {
      std::lock_guard<std::mutex> lock(mutex_);
      if (progress_row_ >= progress_row) return;
      progress_row_ = progress_row;
    }
    progress_row_condvar_.notify_all();
  }

  void MarkFrameAsStarted() {
    std::lock_guard<std::mutex> lock(mutex_);
    if (frame_state_ != kFrameStateUnknown) return;
    frame_state_ = kFrameStateStarted;
  }

  // All the WaitUntil* functions will return true if the desired wait state was
  // reached successfully. If the return value is false, then the caller must
  // assume that the wait was not successful and try to stop whatever they are
  // doing as early as possible.

  // Waits until the frame has been parsed.
  bool WaitUntilParsed() {
    std::unique_lock<std::mutex> lock(mutex_);
    while (frame_state_ < kFrameStateParsed && !abort_) {
      parsed_condvar_.wait(lock);
    }
    return !abort_;
  }

  // Waits until the |progress_row| has been decoded (as indicated either by
  // |progress_row_| or |frame_state_|). |progress_row_cache| must not be
  // nullptr and will be populated with the value of |progress_row_| after the
  // wait.
  //
  // Typical usage of |progress_row_cache| is as follows:
  //  * Initialize |*progress_row_cache| to INT_MIN.
  //  * Call WaitUntil only if |*progress_row_cache| < |progress_row|.
  bool WaitUntil(int progress_row, int* progress_row_cache) {
    // If |progress_row| is negative, it means that the wait is on the top
    // border to be available. The top border will be available when row 0 has
    // been decoded. So we can simply wait on row 0 instead.
    progress_row = std::max(progress_row, 0);
    std::unique_lock<std::mutex> lock(mutex_);
    while (progress_row_ < progress_row && frame_state_ != kFrameStateDecoded &&
           !abort_) {
      progress_row_condvar_.wait(lock);
    }
    // Once |frame_state_| reaches kFrameStateDecoded, |progress_row_| may no
    // longer be updated. So we set |*progress_row_cache| to INT_MAX in that
    // case.
    *progress_row_cache =
        (frame_state_ != kFrameStateDecoded) ? progress_row_ : INT_MAX;
    return !abort_;
  }

  // Waits until the entire frame has been decoded.
  bool WaitUntilDecoded() {
    std::unique_lock<std::mutex> lock(mutex_);
    while (frame_state_ != kFrameStateDecoded && !abort_) {
      decoded_condvar_.wait(lock);
    }
    return !abort_;
  }

 private:
  friend class BufferPool;

  // Methods for BufferPool:
  RefCountedBuffer();
  ~RefCountedBuffer();
  void SetBufferPool(BufferPool* pool);
  static void ReturnToBufferPool(RefCountedBuffer* ptr);

  BufferPool* pool_ = nullptr;
  bool buffer_private_data_valid_ = false;
  void* buffer_private_data_ = nullptr;
  YuvBuffer yuv_buffer_;
  bool in_use_ = false;  // Only used by BufferPool.

  std::mutex mutex_;
  FrameState frame_state_ = kFrameStateUnknown LIBGAV1_GUARDED_BY(mutex_);
  int progress_row_ = -1 LIBGAV1_GUARDED_BY(mutex_);
  // Signaled when progress_row_ is updated or when frame_state_ is set to
  // kFrameStateDecoded.
  std::condition_variable progress_row_condvar_;
  // Signaled when the frame state is set to kFrameStateParsed.
  std::condition_variable parsed_condvar_;
  // Signaled when the frame state is set to kFrameStateDecoded.
  std::condition_variable decoded_condvar_;
  bool abort_ = false LIBGAV1_GUARDED_BY(mutex_);

  FrameType frame_type_ = kFrameKey;
  ChromaSamplePosition chroma_sample_position_ = kChromaSamplePositionUnknown;
  bool showable_frame_ = false;

  int32_t upscaled_width_ = 0;
  int32_t frame_width_ = 0;
  int32_t frame_height_ = 0;
  int32_t render_width_ = 0;
  int32_t render_height_ = 0;
  int32_t columns4x4_ = 0;
  int32_t rows4x4_ = 0;
  int spatial_id_ = 0;
  int temporal_id_ = 0;

  // segmentation_map_ contains a rows4x4_ by columns4x4_ 2D array.
  SegmentationMap segmentation_map_;

  // Only the |params| field of each GlobalMotion struct is used.
  // global_motion_[0] (for kReferenceFrameIntra) is not used.
  std::array<GlobalMotion, kNumReferenceFrameTypes> global_motion_ = {};
  SymbolDecoderContext frame_context_;
  std::array<int8_t, kNumReferenceFrameTypes> loop_filter_ref_deltas_;
  std::array<int8_t, kLoopFilterMaxModeDeltas> loop_filter_mode_deltas_;
  // Only the feature_enabled, feature_data, segment_id_pre_skip, and
  // last_active_segment_id fields of the Segmentation struct are used.
  //
  // Note: The spec only requires that we save feature_enabled and
  // feature_data. Since segment_id_pre_skip and last_active_segment_id depend
  // on feature_enabled only, we also save their values as an optimization.
  Segmentation segmentation_ = {};
  FilmGrainParams film_grain_params_ = {};
  ReferenceInfo reference_info_;
};

// RefCountedBufferPtr contains a reference to a RefCountedBuffer.
//
// Note: For simplicity, RefCountedBufferPtr is implemented as a
// std::shared_ptr<RefCountedBuffer>. This requires a heap allocation of the
// control block for std::shared_ptr. To avoid that heap allocation, we can
// add a |ref_count_| field to RefCountedBuffer and implement a custom
// RefCountedBufferPtr class.
using RefCountedBufferPtr = std::shared_ptr<RefCountedBuffer>;

// BufferPool maintains a pool of RefCountedBuffers.
class BufferPool {
 public:
  BufferPool(FrameBufferSizeChangedCallback on_frame_buffer_size_changed,
             GetFrameBufferCallback get_frame_buffer,
             ReleaseFrameBufferCallback release_frame_buffer,
             void* callback_private_data);

  // Not copyable or movable.
  BufferPool(const BufferPool&) = delete;
  BufferPool& operator=(const BufferPool&) = delete;

  ~BufferPool();

  LIBGAV1_MUST_USE_RESULT bool OnFrameBufferSizeChanged(
      int bitdepth, Libgav1ImageFormat image_format, int width, int height,
      int left_border, int right_border, int top_border, int bottom_border);

  // Finds a free buffer in the buffer pool and returns a reference to the free
  // buffer. If there is no free buffer, returns a null pointer. This function
  // is thread safe.
  RefCountedBufferPtr GetFreeBuffer();

  // Aborts all the buffers that are in use.
  void Abort();

 private:
  friend class RefCountedBuffer;

  // Returns an unused buffer to the buffer pool. Called by RefCountedBuffer
  // only. This function is thread safe.
  void ReturnUnusedBuffer(RefCountedBuffer* buffer);

  // Used to make the following functions thread safe: GetFreeBuffer(),
  // ReturnUnusedBuffer(), RefCountedBuffer::Realloc().
  std::mutex mutex_;

  // Storing a RefCountedBuffer object in a Vector is complicated because of the
  // copy/move semantics. So the simplest way around that is to store a list of
  // pointers in the vector.
  Vector<RefCountedBuffer*> buffers_ LIBGAV1_GUARDED_BY(mutex_);
  InternalFrameBufferList internal_frame_buffers_;

  // Frame buffer callbacks.
  FrameBufferSizeChangedCallback on_frame_buffer_size_changed_;
  GetFrameBufferCallback get_frame_buffer_;
  ReleaseFrameBufferCallback release_frame_buffer_;
  // Private data associated with the frame buffer callbacks.
  void* callback_private_data_;
};

}  // namespace libgav1

#endif  // LIBGAV1_SRC_BUFFER_POOL_H_
