/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "common_video/include/video_frame_buffer_pool.h"

#include <cstddef>
#include <limits>

#include "api/make_ref_counted.h"
#include "api/scoped_refptr.h"
#include "api/video/i010_buffer.h"
#include "api/video/i210_buffer.h"
#include "api/video/i410_buffer.h"
#include "api/video/i420_buffer.h"
#include "api/video/i422_buffer.h"
#include "api/video/i444_buffer.h"
#include "api/video/nv12_buffer.h"
#include "api/video/video_frame_buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/race_checker.h"
#include "rtc_base/ref_counted_object.h"

namespace webrtc {

namespace {
bool HasOneRef(const scoped_refptr<VideoFrameBuffer>& buffer) {
  // Cast to RefCountedObject is safe because this function is only called
  // on locally created VideoFrameBuffers, which are either
  // `RefCountedObject<I420Buffer>`, `RefCountedObject<I444Buffer>` or
  // `RefCountedObject<NV12Buffer>`.
  switch (buffer->type()) {
    case VideoFrameBuffer::Type::kI420: {
      return static_cast<RefCountedObject<I420Buffer>*>(buffer.get())
          ->HasOneRef();
    }
    case VideoFrameBuffer::Type::kI444: {
      return static_cast<RefCountedObject<I444Buffer>*>(buffer.get())
          ->HasOneRef();
    }
    case VideoFrameBuffer::Type::kI422: {
      return static_cast<RefCountedObject<I422Buffer>*>(buffer.get())
          ->HasOneRef();
    }
    case VideoFrameBuffer::Type::kI010: {
      return static_cast<RefCountedObject<I010Buffer>*>(buffer.get())
          ->HasOneRef();
    }
    case VideoFrameBuffer::Type::kI210: {
      return static_cast<RefCountedObject<I210Buffer>*>(buffer.get())
          ->HasOneRef();
    }
    case VideoFrameBuffer::Type::kI410: {
      return static_cast<RefCountedObject<I410Buffer>*>(buffer.get())
          ->HasOneRef();
    }
    case VideoFrameBuffer::Type::kNV12: {
      return static_cast<RefCountedObject<NV12Buffer>*>(buffer.get())
          ->HasOneRef();
    }
    default:
      RTC_DCHECK_NOTREACHED();
  }
  return false;
}

}  // namespace

VideoFrameBufferPool::VideoFrameBufferPool() : VideoFrameBufferPool(false) {}

VideoFrameBufferPool::VideoFrameBufferPool(bool zero_initialize)
    : VideoFrameBufferPool(zero_initialize,
                           std::numeric_limits<size_t>::max()) {}

VideoFrameBufferPool::VideoFrameBufferPool(bool zero_initialize,
                                           size_t max_number_of_buffers)
    : zero_initialize_(zero_initialize),
      max_number_of_buffers_(max_number_of_buffers) {}

VideoFrameBufferPool::~VideoFrameBufferPool() = default;

void VideoFrameBufferPool::Release() {
  buffers_.clear();
}

bool VideoFrameBufferPool::Resize(size_t max_number_of_buffers) {
  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
  size_t used_buffers_count = 0;
  for (const scoped_refptr<VideoFrameBuffer>& buffer : buffers_) {
    // If the buffer is in use, the ref count will be >= 2, one from the list we
    // are looping over and one from the application. If the ref count is 1,
    // then the list we are looping over holds the only reference and it's safe
    // to reuse.
    if (!HasOneRef(buffer)) {
      used_buffers_count++;
    }
  }
  if (used_buffers_count > max_number_of_buffers) {
    return false;
  }
  max_number_of_buffers_ = max_number_of_buffers;

  size_t buffers_to_purge = buffers_.size() - max_number_of_buffers_;
  auto iter = buffers_.begin();
  while (iter != buffers_.end() && buffers_to_purge > 0) {
    if (HasOneRef(*iter)) {
      iter = buffers_.erase(iter);
      buffers_to_purge--;
    } else {
      ++iter;
    }
  }
  return true;
}

scoped_refptr<I420Buffer> VideoFrameBufferPool::CreateI420Buffer(int width,
                                                                 int height) {
  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);

  scoped_refptr<VideoFrameBuffer> existing_buffer =
      GetExistingBuffer(width, height, VideoFrameBuffer::Type::kI420);
  if (existing_buffer) {
    // Cast is safe because the only way kI420 buffer is created is
    // in the same function below, where `RefCountedObject<I420Buffer>` is
    // created.
    RefCountedObject<I420Buffer>* raw_buffer =
        static_cast<RefCountedObject<I420Buffer>*>(existing_buffer.get());
    // Creates a new scoped_refptr, which is also pointing to the same
    // RefCountedObject as buffer, increasing ref count.
    return scoped_refptr<I420Buffer>(raw_buffer);
  }

  if (buffers_.size() >= max_number_of_buffers_)
    return nullptr;
  // Allocate new buffer.
  scoped_refptr<I420Buffer> buffer =
      make_ref_counted<I420Buffer>(width, height);

  if (zero_initialize_)
    buffer->InitializeData();

  buffers_.push_back(buffer);
  return buffer;
}

scoped_refptr<I444Buffer> VideoFrameBufferPool::CreateI444Buffer(int width,
                                                                 int height) {
  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);

  scoped_refptr<VideoFrameBuffer> existing_buffer =
      GetExistingBuffer(width, height, VideoFrameBuffer::Type::kI444);
  if (existing_buffer) {
    // Cast is safe because the only way kI444 buffer is created is
    // in the same function below, where |RefCountedObject<I444Buffer>|
    // is created.
    RefCountedObject<I444Buffer>* raw_buffer =
        static_cast<RefCountedObject<I444Buffer>*>(existing_buffer.get());
    // Creates a new scoped_refptr, which is also pointing to the same
    // RefCountedObject as buffer, increasing ref count.
    return scoped_refptr<I444Buffer>(raw_buffer);
  }

  if (buffers_.size() >= max_number_of_buffers_)
    return nullptr;
  // Allocate new buffer.
  scoped_refptr<I444Buffer> buffer =
      make_ref_counted<I444Buffer>(width, height);

  if (zero_initialize_)
    buffer->InitializeData();

  buffers_.push_back(buffer);
  return buffer;
}

scoped_refptr<I422Buffer> VideoFrameBufferPool::CreateI422Buffer(int width,
                                                                 int height) {
  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);

  scoped_refptr<VideoFrameBuffer> existing_buffer =
      GetExistingBuffer(width, height, VideoFrameBuffer::Type::kI422);
  if (existing_buffer) {
    // Cast is safe because the only way kI422 buffer is created is
    // in the same function below, where |RefCountedObject<I422Buffer>|
    // is created.
    RefCountedObject<I422Buffer>* raw_buffer =
        static_cast<RefCountedObject<I422Buffer>*>(existing_buffer.get());
    // Creates a new scoped_refptr, which is also pointing to the same
    // RefCountedObject as buffer, increasing ref count.
    return scoped_refptr<I422Buffer>(raw_buffer);
  }

  if (buffers_.size() >= max_number_of_buffers_)
    return nullptr;
  // Allocate new buffer.
  scoped_refptr<I422Buffer> buffer =
      make_ref_counted<I422Buffer>(width, height);

  if (zero_initialize_)
    buffer->InitializeData();

  buffers_.push_back(buffer);
  return buffer;
}

scoped_refptr<NV12Buffer> VideoFrameBufferPool::CreateNV12Buffer(int width,
                                                                 int height) {
  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);

  scoped_refptr<VideoFrameBuffer> existing_buffer =
      GetExistingBuffer(width, height, VideoFrameBuffer::Type::kNV12);
  if (existing_buffer) {
    // Cast is safe because the only way kI420 buffer is created is
    // in the same function below, where `RefCountedObject<I420Buffer>` is
    // created.
    RefCountedObject<NV12Buffer>* raw_buffer =
        static_cast<RefCountedObject<NV12Buffer>*>(existing_buffer.get());
    // Creates a new scoped_refptr, which is also pointing to the same
    // RefCountedObject as buffer, increasing ref count.
    return scoped_refptr<NV12Buffer>(raw_buffer);
  }

  if (buffers_.size() >= max_number_of_buffers_)
    return nullptr;
  // Allocate new buffer.
  scoped_refptr<NV12Buffer> buffer =
      make_ref_counted<NV12Buffer>(width, height);

  if (zero_initialize_)
    buffer->InitializeData();

  buffers_.push_back(buffer);
  return buffer;
}

scoped_refptr<I010Buffer> VideoFrameBufferPool::CreateI010Buffer(int width,
                                                                 int height) {
  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);

  scoped_refptr<VideoFrameBuffer> existing_buffer =
      GetExistingBuffer(width, height, VideoFrameBuffer::Type::kI010);
  if (existing_buffer) {
    // Cast is safe because the only way kI010 buffer is created is
    // in the same function below, where |RefCountedObject<I010Buffer>|
    // is created.
    RefCountedObject<I010Buffer>* raw_buffer =
        static_cast<RefCountedObject<I010Buffer>*>(existing_buffer.get());
    // Creates a new scoped_refptr, which is also pointing to the same
    // RefCountedObject as buffer, increasing ref count.
    return scoped_refptr<I010Buffer>(raw_buffer);
  }

  if (buffers_.size() >= max_number_of_buffers_)
    return nullptr;
  // Allocate new buffer.
  scoped_refptr<I010Buffer> buffer = I010Buffer::Create(width, height);

  buffers_.push_back(buffer);
  return buffer;
}

scoped_refptr<I210Buffer> VideoFrameBufferPool::CreateI210Buffer(int width,
                                                                 int height) {
  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);

  scoped_refptr<VideoFrameBuffer> existing_buffer =
      GetExistingBuffer(width, height, VideoFrameBuffer::Type::kI210);
  if (existing_buffer) {
    // Cast is safe because the only way kI210 buffer is created is
    // in the same function below, where |RefCountedObject<I210Buffer>|
    // is created.
    RefCountedObject<I210Buffer>* raw_buffer =
        static_cast<RefCountedObject<I210Buffer>*>(existing_buffer.get());
    // Creates a new scoped_refptr, which is also pointing to the same
    // RefCountedObject as buffer, increasing ref count.
    return scoped_refptr<I210Buffer>(raw_buffer);
  }

  if (buffers_.size() >= max_number_of_buffers_)
    return nullptr;
  // Allocate new buffer.
  scoped_refptr<I210Buffer> buffer = I210Buffer::Create(width, height);

  buffers_.push_back(buffer);
  return buffer;
}

scoped_refptr<I410Buffer> VideoFrameBufferPool::CreateI410Buffer(int width,
                                                                 int height) {
  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);

  scoped_refptr<VideoFrameBuffer> existing_buffer =
      GetExistingBuffer(width, height, VideoFrameBuffer::Type::kI410);
  if (existing_buffer) {
    // Cast is safe because the only way kI410 buffer is created is
    // in the same function below, where |RefCountedObject<I410Buffer>|
    // is created.
    RefCountedObject<I410Buffer>* raw_buffer =
        static_cast<RefCountedObject<I410Buffer>*>(existing_buffer.get());
    // Creates a new scoped_refptr, which is also pointing to the same
    // RefCountedObject as buffer, increasing ref count.
    return scoped_refptr<I410Buffer>(raw_buffer);
  }

  if (buffers_.size() >= max_number_of_buffers_)
    return nullptr;
  // Allocate new buffer.
  scoped_refptr<I410Buffer> buffer = I410Buffer::Create(width, height);

  buffers_.push_back(buffer);
  return buffer;
}

scoped_refptr<VideoFrameBuffer> VideoFrameBufferPool::GetExistingBuffer(
    int width,
    int height,
    VideoFrameBuffer::Type type) {
  // Release buffers with wrong resolution or different type.
  for (auto it = buffers_.begin(); it != buffers_.end();) {
    const auto& buffer = *it;
    if (buffer->width() != width || buffer->height() != height ||
        buffer->type() != type) {
      it = buffers_.erase(it);
    } else {
      ++it;
    }
  }
  // Look for a free buffer.
  for (const scoped_refptr<VideoFrameBuffer>& buffer : buffers_) {
    // If the buffer is in use, the ref count will be >= 2, one from the list we
    // are looping over and one from the application. If the ref count is 1,
    // then the list we are looping over holds the only reference and it's safe
    // to reuse.
    if (HasOneRef(buffer)) {
      RTC_CHECK(buffer->type() == type);
      return buffer;
    }
  }
  return nullptr;
}

}  // namespace webrtc
