/*
 *  Copyright 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/java/jni/native_handle_impl.h"

#include <memory>

#include "webrtc/api/java/jni/jni_helpers.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/keep_ref_until_done.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ref_ptr.h"

using webrtc::NativeHandleBuffer;

namespace {

void RotateMatrix(float a[16], webrtc::VideoRotation rotation) {
  // Texture coordinates are in the range 0 to 1. The transformation of the last
  // row in each rotation matrix is needed for proper translation, e.g, to
  // mirror x, we don't replace x by -x, but by 1-x.
  switch (rotation) {
    case webrtc::kVideoRotation_0:
      break;
    case webrtc::kVideoRotation_90: {
      const float ROTATE_90[16] =
          { a[4], a[5], a[6], a[7],
            -a[0], -a[1], -a[2], -a[3],
            a[8], a[9], a[10], a[11],
            a[0] + a[12], a[1] + a[13], a[2] + a[14], a[3] + a[15]};
      memcpy(a, ROTATE_90, sizeof(ROTATE_90));
    } break;
    case webrtc::kVideoRotation_180: {
      const float ROTATE_180[16] =
          { -a[0], -a[1], -a[2], -a[3],
            -a[4], -a[5], -a[6], -a[7],
            a[8], a[9], a[10], a[11],
            a[0] + a[4] + a[12], a[1] +a[5] + a[13], a[2] + a[6] + a[14],
            a[3] + a[11]+ a[15]};
        memcpy(a, ROTATE_180, sizeof(ROTATE_180));
      }
      break;
    case webrtc::kVideoRotation_270: {
      const float ROTATE_270[16] =
          { -a[4], -a[5], -a[6], -a[7],
            a[0], a[1], a[2], a[3],
            a[8], a[9], a[10], a[11],
            a[4] + a[12], a[5] + a[13], a[6] + a[14], a[7] + a[15]};
        memcpy(a, ROTATE_270, sizeof(ROTATE_270));
    } break;
  }
}

// Calculates result = a * b, in column-major order.
void MultiplyMatrix(const float a[16], const float b[16], float result[16]) {
  for (int i = 0; i < 4; ++i) {
    for (int j = 0; j < 4; ++j) {
      float sum = 0;
      for (int k = 0; k < 4; ++k) {
        sum += a[k * 4 + j] * b[i * 4 + k];
      }
      result[i * 4 + j] = sum;
    }
  }
}

// Center crop by keeping xFraction of the width and yFraction of the height,
// so e.g. cropping from 640x480 to 640x360 would use
// xFraction=1, yFraction=360/480.
void CropMatrix(float a[16], float xFraction, float yFraction) {
  // Move cropped area to the center of the frame by offsetting half the
  // removed area.
  const float xOffset = (1 - xFraction) / 2;
  const float yOffset = (1 - yFraction) / 2;
  const float crop_matrix[16] = {
    xFraction, 0, 0, 0,
    0, yFraction, 0, 0,
    0, 0, 1, 0,
    xOffset, yOffset, 0, 1};
  float mul_result[16];
  MultiplyMatrix(crop_matrix, a, mul_result);
  memcpy(a, mul_result, sizeof(mul_result));
}

}  // anonymouse namespace

namespace webrtc_jni {

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

NativeHandleImpl::NativeHandleImpl(JNIEnv* jni,
                                   jint j_oes_texture_id,
                                   jfloatArray j_transform_matrix)
  : oes_texture_id(j_oes_texture_id) {
  RTC_CHECK_EQ(16, jni->GetArrayLength(j_transform_matrix));
  jfloat* transform_matrix_ptr =
      jni->GetFloatArrayElements(j_transform_matrix, nullptr);
  for (int i = 0; i < 16; ++i) {
    sampling_matrix[i] = transform_matrix_ptr[i];
  }
  jni->ReleaseFloatArrayElements(j_transform_matrix, transform_matrix_ptr, 0);
}

AndroidTextureBuffer::AndroidTextureBuffer(
    int width,
    int height,
    const NativeHandleImpl& native_handle,
    jobject surface_texture_helper,
    const rtc::Callback0<void>& no_longer_used)
    : webrtc::NativeHandleBuffer(&native_handle_, width, height),
      native_handle_(native_handle),
      surface_texture_helper_(surface_texture_helper),
      no_longer_used_cb_(no_longer_used) {}

AndroidTextureBuffer::~AndroidTextureBuffer() {
  no_longer_used_cb_();
}

rtc::scoped_refptr<webrtc::VideoFrameBuffer>
AndroidTextureBuffer::NativeToI420Buffer() {
  int uv_width = (width()+7) / 8;
  int stride = 8 * uv_width;
  int uv_height = (height()+1)/2;
  size_t size = stride * (height() + uv_height);
  // The data is owned by the frame, and the normal case is that the
  // data is deleted by the frame's destructor callback.
  //
  // TODO(nisse): Use an I420BufferPool. We then need to extend that
  // class, and I420Buffer, to support our memory layout.
  std::unique_ptr<uint8_t, webrtc::AlignedFreeDeleter> yuv_data(
      static_cast<uint8_t*>(webrtc::AlignedMalloc(size, kBufferAlignment)));
  // See SurfaceTextureHelper.java for the required layout.
  uint8_t* y_data = yuv_data.get();
  uint8_t* u_data = y_data + height() * stride;
  uint8_t* v_data = u_data + stride/2;

  rtc::scoped_refptr<webrtc::VideoFrameBuffer> copy =
    new rtc::RefCountedObject<webrtc::WrappedI420Buffer>(
        width(), height(),
        y_data, stride,
        u_data, stride,
        v_data, stride,
        rtc::Bind(&webrtc::AlignedFree, yuv_data.release()));

  JNIEnv* jni = AttachCurrentThreadIfNeeded();
  ScopedLocalRefFrame local_ref_frame(jni);

  jmethodID transform_mid = GetMethodID(
      jni,
      GetObjectClass(jni, surface_texture_helper_),
      "textureToYUV",
      "(Ljava/nio/ByteBuffer;IIII[F)V");

  jobject byte_buffer = jni->NewDirectByteBuffer(y_data, size);

  // TODO(nisse): Keep java transform matrix around.
  jfloatArray sampling_matrix = jni->NewFloatArray(16);
  jni->SetFloatArrayRegion(sampling_matrix, 0, 16,
                           native_handle_.sampling_matrix);

  jni->CallVoidMethod(surface_texture_helper_,
                      transform_mid,
                      byte_buffer, width(), height(), stride,
                      native_handle_.oes_texture_id, sampling_matrix);
  CHECK_EXCEPTION(jni) << "textureToYUV throwed an exception";

  return copy;
}

rtc::scoped_refptr<AndroidTextureBuffer>
AndroidTextureBuffer::CropScaleAndRotate(int cropped_width,
                                         int cropped_height,
                                         int dst_width,
                                         int dst_height,
                                         webrtc::VideoRotation rotation) {
  if (cropped_width == dst_width && cropped_height == dst_height &&
      width() == dst_width && height() == dst_height &&
      rotation == webrtc::kVideoRotation_0) {
    return this;
  }
  int rotated_width = (rotation % 180 == 0) ? dst_width : dst_height;
  int rotated_height = (rotation % 180 == 0) ? dst_height : dst_width;

  // Here we use Bind magic to add a reference count to |this| until the newly
  // created AndroidTextureBuffer is destructed
  rtc::scoped_refptr<AndroidTextureBuffer> buffer(
      new rtc::RefCountedObject<AndroidTextureBuffer>(
          rotated_width, rotated_height, native_handle_,
          surface_texture_helper_, rtc::KeepRefUntilDone(this)));

  if (cropped_width != width() || cropped_height != height()) {
    CropMatrix(buffer->native_handle_.sampling_matrix,
               cropped_width / static_cast<float>(width()),
               cropped_height / static_cast<float>(height()));
  }
  RotateMatrix(buffer->native_handle_.sampling_matrix, rotation);
  return buffer;
}

}  // namespace webrtc_jni
