/*
 *  Copyright (c) 2017 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 <jni.h>

#include "webrtc/api/video/video_frame.h"
#include "webrtc/media/base/videosinkinterface.h"
#include "webrtc/sdk/android/src/jni/classreferenceholder.h"
#include "webrtc/sdk/android/src/jni/jni_helpers.h"
#include "webrtc/sdk/android/src/jni/native_handle_impl.h"

namespace webrtc {
namespace jni {

// Wrapper dispatching rtc::VideoSinkInterface to a Java VideoRenderer
// instance.
class JavaVideoRendererWrapper : public rtc::VideoSinkInterface<VideoFrame> {
 public:
  JavaVideoRendererWrapper(JNIEnv* jni, jobject j_callbacks)
      : j_callbacks_(jni, j_callbacks),
        j_render_frame_id_(
            GetMethodID(jni,
                        GetObjectClass(jni, j_callbacks),
                        "renderFrame",
                        "(Lorg/webrtc/VideoRenderer$I420Frame;)V")),
        j_frame_class_(jni,
                       FindClass(jni, "org/webrtc/VideoRenderer$I420Frame")),
        j_i420_frame_ctor_id_(GetMethodID(jni,
                                          *j_frame_class_,
                                          "<init>",
                                          "(III[I[Ljava/nio/ByteBuffer;J)V")),
        j_texture_frame_ctor_id_(
            GetMethodID(jni, *j_frame_class_, "<init>", "(IIII[FJ)V")),
        j_byte_buffer_class_(jni, FindClass(jni, "java/nio/ByteBuffer")) {
    CHECK_EXCEPTION(jni);
  }

  virtual ~JavaVideoRendererWrapper() {}

  void OnFrame(const VideoFrame& video_frame) override {
    ScopedLocalRefFrame local_ref_frame(jni());

    jobject j_frame;
    if (video_frame.video_frame_buffer()->type() ==
        VideoFrameBuffer::Type::kNative) {
      AndroidVideoFrameBuffer* android_buffer =
          static_cast<AndroidVideoFrameBuffer*>(
              video_frame.video_frame_buffer().get());
      switch (android_buffer->android_type()) {
        case AndroidVideoFrameBuffer::AndroidType::kTextureBuffer:
          j_frame = ToJavaTextureFrame(&video_frame);
          break;
        case AndroidVideoFrameBuffer::AndroidType::kJavaBuffer:
          j_frame = static_cast<AndroidVideoBuffer*>(android_buffer)
                        ->ToJavaI420Frame(jni(), video_frame.rotation());
          break;
        default:
          RTC_NOTREACHED();
      }
    } else {
      j_frame = ToJavaI420Frame(&video_frame);
    }
    // |j_callbacks_| is responsible for releasing |j_frame| with
    // VideoRenderer.renderFrameDone().
    jni()->CallVoidMethod(*j_callbacks_, j_render_frame_id_, j_frame);
    CHECK_EXCEPTION(jni());
  }

 private:
  // Make a shallow copy of |frame| to be used with Java. The callee has
  // ownership of the frame, and the frame should be released with
  // VideoRenderer.releaseNativeFrame().
  static jlong javaShallowCopy(const VideoFrame* frame) {
    return jlongFromPointer(new VideoFrame(*frame));
  }

  // Return a VideoRenderer.I420Frame referring to the data in |frame|.
  jobject ToJavaI420Frame(const VideoFrame* frame) {
    jintArray strides = jni()->NewIntArray(3);
    jint* strides_array = jni()->GetIntArrayElements(strides, NULL);
    rtc::scoped_refptr<I420BufferInterface> i420_buffer =
        frame->video_frame_buffer()->ToI420();
    strides_array[0] = i420_buffer->StrideY();
    strides_array[1] = i420_buffer->StrideU();
    strides_array[2] = i420_buffer->StrideV();
    jni()->ReleaseIntArrayElements(strides, strides_array, 0);
    jobjectArray planes = jni()->NewObjectArray(3, *j_byte_buffer_class_, NULL);
    jobject y_buffer = jni()->NewDirectByteBuffer(
        const_cast<uint8_t*>(i420_buffer->DataY()),
        i420_buffer->StrideY() * i420_buffer->height());
    size_t chroma_height = i420_buffer->ChromaHeight();
    jobject u_buffer =
        jni()->NewDirectByteBuffer(const_cast<uint8_t*>(i420_buffer->DataU()),
                                   i420_buffer->StrideU() * chroma_height);
    jobject v_buffer =
        jni()->NewDirectByteBuffer(const_cast<uint8_t*>(i420_buffer->DataV()),
                                   i420_buffer->StrideV() * chroma_height);

    jni()->SetObjectArrayElement(planes, 0, y_buffer);
    jni()->SetObjectArrayElement(planes, 1, u_buffer);
    jni()->SetObjectArrayElement(planes, 2, v_buffer);
    return jni()->NewObject(*j_frame_class_, j_i420_frame_ctor_id_,
                            frame->width(), frame->height(),
                            static_cast<int>(frame->rotation()), strides,
                            planes, javaShallowCopy(frame));
  }

  // Return a VideoRenderer.I420Frame referring texture object in |frame|.
  jobject ToJavaTextureFrame(const VideoFrame* frame) {
    NativeHandleImpl handle =
        static_cast<AndroidTextureBuffer*>(frame->video_frame_buffer().get())
            ->native_handle_impl();
    jfloatArray sampling_matrix = handle.sampling_matrix.ToJava(jni());

    return jni()->NewObject(
        *j_frame_class_, j_texture_frame_ctor_id_, frame->width(),
        frame->height(), static_cast<int>(frame->rotation()),
        handle.oes_texture_id, sampling_matrix, javaShallowCopy(frame));
  }

  JNIEnv* jni() { return AttachCurrentThreadIfNeeded(); }

  ScopedGlobalRef<jobject> j_callbacks_;
  jmethodID j_render_frame_id_;
  ScopedGlobalRef<jclass> j_frame_class_;
  jmethodID j_i420_frame_ctor_id_;
  jmethodID j_texture_frame_ctor_id_;
  ScopedGlobalRef<jclass> j_byte_buffer_class_;
};

JNI_FUNCTION_DECLARATION(void,
                         VideoRenderer_freeWrappedVideoRenderer,
                         JNIEnv*,
                         jclass,
                         jlong j_p) {
  delete reinterpret_cast<JavaVideoRendererWrapper*>(j_p);
}

JNI_FUNCTION_DECLARATION(void,
                         VideoRenderer_releaseNativeFrame,
                         JNIEnv* jni,
                         jclass,
                         jlong j_frame_ptr) {
  delete reinterpret_cast<const VideoFrame*>(j_frame_ptr);
}

JNI_FUNCTION_DECLARATION(jlong,
                         VideoRenderer_nativeWrapVideoRenderer,
                         JNIEnv* jni,
                         jclass,
                         jobject j_callbacks) {
  std::unique_ptr<JavaVideoRendererWrapper> renderer(
      new JavaVideoRendererWrapper(jni, j_callbacks));
  return (jlong)renderer.release();
}

JNI_FUNCTION_DECLARATION(void,
                         VideoRenderer_nativeCopyPlane,
                         JNIEnv* jni,
                         jclass,
                         jobject j_src_buffer,
                         jint width,
                         jint height,
                         jint src_stride,
                         jobject j_dst_buffer,
                         jint dst_stride) {
  size_t src_size = jni->GetDirectBufferCapacity(j_src_buffer);
  size_t dst_size = jni->GetDirectBufferCapacity(j_dst_buffer);
  RTC_CHECK(src_stride >= width) << "Wrong source stride " << src_stride;
  RTC_CHECK(dst_stride >= width) << "Wrong destination stride " << dst_stride;
  RTC_CHECK(src_size >= src_stride * height)
      << "Insufficient source buffer capacity " << src_size;
  RTC_CHECK(dst_size >= dst_stride * height)
      << "Insufficient destination buffer capacity " << dst_size;
  uint8_t* src =
      reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_src_buffer));
  uint8_t* dst =
      reinterpret_cast<uint8_t*>(jni->GetDirectBufferAddress(j_dst_buffer));
  if (src_stride == dst_stride) {
    memcpy(dst, src, src_stride * height);
  } else {
    for (int i = 0; i < height; i++) {
      memcpy(dst, src, width);
      src += src_stride;
      dst += dst_stride;
    }
  }
}

}  // namespace jni
}  // namespace webrtc
