/*
 *  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 "webrtc/api/video/i420_buffer.h"

#include <string.h>

#include <algorithm>
#include <utility>

#include "webrtc/base/checks.h"
#include "webrtc/base/keep_ref_until_done.h"
#include "libyuv/convert.h"
#include "libyuv/planar_functions.h"
#include "libyuv/scale.h"

// Aligning pointer to 64 bytes for improved performance, e.g. use SIMD.
static const int kBufferAlignment = 64;

namespace webrtc {

namespace {

int I420DataSize(int height, int stride_y, int stride_u, int stride_v) {
  return stride_y * height + (stride_u + stride_v) * ((height + 1) / 2);
}

}  // namespace

I420Buffer::I420Buffer(int width, int height)
    : I420Buffer(width, height, width, (width + 1) / 2, (width + 1) / 2) {
}

I420Buffer::I420Buffer(int width,
                       int height,
                       int stride_y,
                       int stride_u,
                       int stride_v)
    : width_(width),
      height_(height),
      stride_y_(stride_y),
      stride_u_(stride_u),
      stride_v_(stride_v),
      data_(static_cast<uint8_t*>(AlignedMalloc(
          I420DataSize(height, stride_y, stride_u, stride_v),
          kBufferAlignment))) {
  RTC_DCHECK_GT(width, 0);
  RTC_DCHECK_GT(height, 0);
  RTC_DCHECK_GE(stride_y, width);
  RTC_DCHECK_GE(stride_u, (width + 1) / 2);
  RTC_DCHECK_GE(stride_v, (width + 1) / 2);
}

I420Buffer::~I420Buffer() {
}

// static
rtc::scoped_refptr<I420Buffer> I420Buffer::Create(int width, int height) {
  return new rtc::RefCountedObject<I420Buffer>(width, height);
}

// static
rtc::scoped_refptr<I420Buffer> I420Buffer::Create(int width,
                                                  int height,
                                                  int stride_y,
                                                  int stride_u,
                                                  int stride_v) {
  return new rtc::RefCountedObject<I420Buffer>(
      width, height, stride_y, stride_u, stride_v);
}

// static
rtc::scoped_refptr<I420Buffer> I420Buffer::Copy(
    const VideoFrameBuffer& source) {
  return Copy(source.width(), source.height(),
              source.DataY(), source.StrideY(),
              source.DataU(), source.StrideU(),
              source.DataV(), source.StrideV());
}

// static
rtc::scoped_refptr<I420Buffer> I420Buffer::Copy(
      int width, int height,
      const uint8_t* data_y, int stride_y,
      const uint8_t* data_u, int stride_u,
      const uint8_t* data_v, int stride_v) {
  // Note: May use different strides than the input data.
  rtc::scoped_refptr<I420Buffer> buffer = Create(width, height);
  RTC_CHECK_EQ(0, libyuv::I420Copy(data_y, stride_y,
                                   data_u, stride_u,
                                   data_v, stride_v,
                                   buffer->MutableDataY(), buffer->StrideY(),
                                   buffer->MutableDataU(), buffer->StrideU(),
                                   buffer->MutableDataV(), buffer->StrideV(),
                                   width, height));
  return buffer;
}

// static
rtc::scoped_refptr<I420Buffer> I420Buffer::Rotate(
    const VideoFrameBuffer& src, VideoRotation rotation) {
  RTC_CHECK(src.DataY());
  RTC_CHECK(src.DataU());
  RTC_CHECK(src.DataV());

  int rotated_width = src.width();
  int rotated_height = src.height();
  if (rotation == webrtc::kVideoRotation_90 ||
      rotation == webrtc::kVideoRotation_270) {
    std::swap(rotated_width, rotated_height);
  }

  rtc::scoped_refptr<webrtc::I420Buffer> buffer =
      I420Buffer::Create(rotated_width, rotated_height);

  RTC_CHECK_EQ(0, libyuv::I420Rotate(
      src.DataY(), src.StrideY(),
      src.DataU(), src.StrideU(),
      src.DataV(), src.StrideV(),
      buffer->MutableDataY(), buffer->StrideY(), buffer->MutableDataU(),
      buffer->StrideU(), buffer->MutableDataV(), buffer->StrideV(),
      src.width(), src.height(),
      static_cast<libyuv::RotationMode>(rotation)));

  return buffer;
}

void I420Buffer::InitializeData() {
  memset(data_.get(), 0,
         I420DataSize(height_, stride_y_, stride_u_, stride_v_));
}

VideoFrameBuffer::Type I420Buffer::type() const {
  return Type::kI420;
}

int I420Buffer::width() const {
  return width_;
}

int I420Buffer::height() const {
  return height_;
}

const uint8_t* I420Buffer::DataY() const {
  return data_.get();
}
const uint8_t* I420Buffer::DataU() const {
  return data_.get() + stride_y_ * height_;
}
const uint8_t* I420Buffer::DataV() const {
  return data_.get() + stride_y_ * height_ + stride_u_ * ((height_ + 1) / 2);
}

int I420Buffer::StrideY() const {
  return stride_y_;
}
int I420Buffer::StrideU() const {
  return stride_u_;
}
int I420Buffer::StrideV() const {
  return stride_v_;
}

uint8_t* I420Buffer::MutableDataY() {
  return const_cast<uint8_t*>(DataY());
}
uint8_t* I420Buffer::MutableDataU() {
  return const_cast<uint8_t*>(DataU());
}
uint8_t* I420Buffer::MutableDataV() {
  return const_cast<uint8_t*>(DataV());
}

// static
void I420Buffer::SetBlack(I420Buffer* buffer) {
  RTC_CHECK(libyuv::I420Rect(buffer->MutableDataY(), buffer->StrideY(),
                             buffer->MutableDataU(), buffer->StrideU(),
                             buffer->MutableDataV(), buffer->StrideV(),
                             0, 0, buffer->width(), buffer->height(),
                             0, 128, 128) == 0);
}

void I420Buffer::CropAndScaleFrom(
    const VideoFrameBuffer& src,
    int offset_x,
    int offset_y,
    int crop_width,
    int crop_height) {
  RTC_CHECK_LE(crop_width, src.width());
  RTC_CHECK_LE(crop_height, src.height());
  RTC_CHECK_LE(crop_width + offset_x, src.width());
  RTC_CHECK_LE(crop_height + offset_y, src.height());
  RTC_CHECK_GE(offset_x, 0);
  RTC_CHECK_GE(offset_y, 0);

  // Make sure offset is even so that u/v plane becomes aligned.
  const int uv_offset_x = offset_x / 2;
  const int uv_offset_y = offset_y / 2;
  offset_x = uv_offset_x * 2;
  offset_y = uv_offset_y * 2;

  const uint8_t* y_plane =
      src.DataY() + src.StrideY() * offset_y + offset_x;
  const uint8_t* u_plane =
      src.DataU() + src.StrideU() * uv_offset_y + uv_offset_x;
  const uint8_t* v_plane =
      src.DataV() + src.StrideV() * uv_offset_y + uv_offset_x;
  int res = libyuv::I420Scale(y_plane, src.StrideY(),
                              u_plane, src.StrideU(),
                              v_plane, src.StrideV(),
                              crop_width, crop_height,
                              MutableDataY(), StrideY(),
                              MutableDataU(), StrideU(),
                              MutableDataV(), StrideV(),
                              width(), height(), libyuv::kFilterBox);

  RTC_DCHECK_EQ(res, 0);
}

void I420Buffer::CropAndScaleFrom(
    const VideoFrameBuffer& src) {
  const int crop_width =
      std::min(src.width(), width() * src.height() / height());
  const int crop_height =
      std::min(src.height(), height() * src.width() / width());

  CropAndScaleFrom(
      src,
      (src.width() - crop_width) / 2, (src.height() - crop_height) / 2,
      crop_width, crop_height);
}

void I420Buffer::ScaleFrom(const VideoFrameBuffer& src) {
  CropAndScaleFrom(src, 0, 0, src.width(), src.height());
}

}  // namespace webrtc
