/*
 *  Copyright (c) 2020 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 "test/mappable_native_buffer.h"

#include "absl/algorithm/container.h"
#include "api/video/i420_buffer.h"
#include "api/video/nv12_buffer.h"
#include "api/video/video_frame.h"
#include "api/video/video_rotation.h"
#include "common_video/include/video_frame_buffer.h"
#include "rtc_base/checks.h"

namespace webrtc {
namespace test {

namespace {

class NV12BufferWithDidConvertToI420 : public NV12Buffer {
 public:
  NV12BufferWithDidConvertToI420(int width, int height)
      : NV12Buffer(width, height), did_convert_to_i420_(false) {}

  bool did_convert_to_i420() const { return did_convert_to_i420_; }

  rtc::scoped_refptr<I420BufferInterface> ToI420() override {
    did_convert_to_i420_ = true;
    return NV12Buffer::ToI420();
  }

 private:
  bool did_convert_to_i420_;
};

}  // namespace

VideoFrame CreateMappableNativeFrame(int64_t ntp_time_ms,
                                     VideoFrameBuffer::Type mappable_type,
                                     int width,
                                     int height) {
  VideoFrame frame =
      VideoFrame::Builder()
          .set_video_frame_buffer(rtc::make_ref_counted<MappableNativeBuffer>(
              mappable_type, width, height))
          .set_timestamp_rtp(99)
          .set_timestamp_ms(99)
          .set_rotation(kVideoRotation_0)
          .build();
  frame.set_ntp_time_ms(ntp_time_ms);
  return frame;
}

rtc::scoped_refptr<MappableNativeBuffer> GetMappableNativeBufferFromVideoFrame(
    const VideoFrame& frame) {
  return static_cast<MappableNativeBuffer*>(frame.video_frame_buffer().get());
}

MappableNativeBuffer::ScaledBuffer::ScaledBuffer(
    rtc::scoped_refptr<MappableNativeBuffer> parent,
    int width,
    int height)
    : parent_(std::move(parent)), width_(width), height_(height) {}

MappableNativeBuffer::ScaledBuffer::~ScaledBuffer() {}

rtc::scoped_refptr<VideoFrameBuffer>
MappableNativeBuffer::ScaledBuffer::CropAndScale(int offset_x,
                                                 int offset_y,
                                                 int crop_width,
                                                 int crop_height,
                                                 int scaled_width,
                                                 int scaled_height) {
  return rtc::make_ref_counted<ScaledBuffer>(parent_, scaled_width,
                                             scaled_height);
}

rtc::scoped_refptr<I420BufferInterface>
MappableNativeBuffer::ScaledBuffer::ToI420() {
  return parent_->GetOrCreateMappedBuffer(width_, height_)->ToI420();
}

rtc::scoped_refptr<VideoFrameBuffer>
MappableNativeBuffer::ScaledBuffer::GetMappedFrameBuffer(
    rtc::ArrayView<VideoFrameBuffer::Type> types) {
  if (absl::c_find(types, parent_->mappable_type_) == types.end())
    return nullptr;
  return parent_->GetOrCreateMappedBuffer(width_, height_);
}

MappableNativeBuffer::MappableNativeBuffer(VideoFrameBuffer::Type mappable_type,
                                           int width,
                                           int height)
    : mappable_type_(mappable_type), width_(width), height_(height) {
  RTC_DCHECK(mappable_type_ == VideoFrameBuffer::Type::kI420 ||
             mappable_type_ == VideoFrameBuffer::Type::kNV12);
}

MappableNativeBuffer::~MappableNativeBuffer() {}

rtc::scoped_refptr<VideoFrameBuffer> MappableNativeBuffer::CropAndScale(
    int offset_x,
    int offset_y,
    int crop_width,
    int crop_height,
    int scaled_width,
    int scaled_height) {
  return FullSizeBuffer()->CropAndScale(
      offset_x, offset_y, crop_width, crop_height, scaled_width, scaled_height);
}

rtc::scoped_refptr<I420BufferInterface> MappableNativeBuffer::ToI420() {
  return FullSizeBuffer()->ToI420();
}

rtc::scoped_refptr<VideoFrameBuffer> MappableNativeBuffer::GetMappedFrameBuffer(
    rtc::ArrayView<VideoFrameBuffer::Type> types) {
  return FullSizeBuffer()->GetMappedFrameBuffer(types);
}

std::vector<rtc::scoped_refptr<VideoFrameBuffer>>
MappableNativeBuffer::GetMappedFramedBuffers() const {
  MutexLock lock(&lock_);
  return mapped_buffers_;
}

bool MappableNativeBuffer::DidConvertToI420() const {
  if (mappable_type_ != VideoFrameBuffer::Type::kNV12)
    return false;
  MutexLock lock(&lock_);
  for (auto& mapped_buffer : mapped_buffers_) {
    if (static_cast<NV12BufferWithDidConvertToI420*>(mapped_buffer.get())
            ->did_convert_to_i420()) {
      return true;
    }
  }
  return false;
}

rtc::scoped_refptr<MappableNativeBuffer::ScaledBuffer>
MappableNativeBuffer::FullSizeBuffer() {
  return rtc::make_ref_counted<ScaledBuffer>(this, width_, height_);
}

rtc::scoped_refptr<VideoFrameBuffer>
MappableNativeBuffer::GetOrCreateMappedBuffer(int width, int height) {
  MutexLock lock(&lock_);
  for (auto& mapped_buffer : mapped_buffers_) {
    if (mapped_buffer->width() == width && mapped_buffer->height() == height) {
      return mapped_buffer;
    }
  }
  rtc::scoped_refptr<VideoFrameBuffer> mapped_buffer;
  switch (mappable_type_) {
    case VideoFrameBuffer::Type::kI420: {
      rtc::scoped_refptr<I420Buffer> i420_buffer =
          I420Buffer::Create(width, height);
      I420Buffer::SetBlack(i420_buffer);
      mapped_buffer = i420_buffer;
      break;
    }
    case VideoFrameBuffer::Type::kNV12: {
      auto nv12_buffer =
          rtc::make_ref_counted<NV12BufferWithDidConvertToI420>(width, height);
      nv12_buffer->InitializeData();
      mapped_buffer = std::move(nv12_buffer);
      break;
    }
    default:
      RTC_NOTREACHED();
  }
  mapped_buffers_.push_back(mapped_buffer);
  return mapped_buffer;
}

}  // namespace test
}  // namespace webrtc
