From 62faaabce961327c677385b64b8fee2ab983a743 Mon Sep 17 00:00:00 2001 From: Magnus Jedvert Date: Wed, 14 Jun 2017 19:03:31 +0200 Subject: [PATCH] Android: Add functionality for wrapping C++ I420 buffers to Java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This functionality is needed when sending C++ I420 buffers to Java VideoSinks or Java encoders. Bug: webrtc:7749 Change-Id: Ied783470b90b9d2e0cb5930795f35de4a296d499 Reviewed-on: https://chromium-review.googlesource.com/532961 Commit-Queue: Magnus Jedvert Reviewed-by: Sami Kalliomäki Cr-Commit-Position: refs/heads/master@{#18597} --- webrtc/sdk/android/BUILD.gn | 3 + .../org/webrtc/WrappedNativeI420Buffer.java | 99 +++++++++++++++++++ .../android/src/jni/classreferenceholder.cc | 1 + .../src/jni/wrapped_native_i420_buffer.cc | 61 ++++++++++++ .../src/jni/wrapped_native_i420_buffer.h | 27 +++++ 5 files changed, 191 insertions(+) create mode 100644 webrtc/sdk/android/src/java/org/webrtc/WrappedNativeI420Buffer.java create mode 100644 webrtc/sdk/android/src/jni/wrapped_native_i420_buffer.cc create mode 100644 webrtc/sdk/android/src/jni/wrapped_native_i420_buffer.h diff --git a/webrtc/sdk/android/BUILD.gn b/webrtc/sdk/android/BUILD.gn index 442649eb9f..8f9fb07e76 100644 --- a/webrtc/sdk/android/BUILD.gn +++ b/webrtc/sdk/android/BUILD.gn @@ -46,6 +46,8 @@ rtc_static_library("libjingle_peerconnection_jni") { "src/jni/rtcstatscollectorcallbackwrapper.h", "src/jni/surfacetexturehelper_jni.cc", "src/jni/surfacetexturehelper_jni.h", + "src/jni/wrapped_native_i420_buffer.cc", + "src/jni/wrapped_native_i420_buffer.h", ] configs += [ ":libjingle_peerconnection_jni_warnings_config" ] @@ -214,6 +216,7 @@ android_library("libjingle_peerconnection_java") { "src/java/org/webrtc/FramerateBitrateAdjuster.java", "src/java/org/webrtc/HardwareVideoEncoder.java", "src/java/org/webrtc/Histogram.java", + "src/java/org/webrtc/WrappedNativeI420Buffer.java", "src/java/org/webrtc/YuvConverter.java", ] diff --git a/webrtc/sdk/android/src/java/org/webrtc/WrappedNativeI420Buffer.java b/webrtc/sdk/android/src/java/org/webrtc/WrappedNativeI420Buffer.java new file mode 100644 index 0000000000..3beef16e60 --- /dev/null +++ b/webrtc/sdk/android/src/java/org/webrtc/WrappedNativeI420Buffer.java @@ -0,0 +1,99 @@ +/* + * Copyright 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. + */ + +package org.webrtc; + +import java.nio.ByteBuffer; + +/** + * This class wraps a webrtc::I420BufferInterface into a VideoFrame.I420Buffer. + */ +class WrappedNativeI420Buffer implements VideoFrame.I420Buffer { + private final int width; + private final int height; + private final ByteBuffer dataY; + private final int strideY; + private final ByteBuffer dataU; + private final int strideU; + private final ByteBuffer dataV; + private final int strideV; + private final long nativeBuffer; + + WrappedNativeI420Buffer(int width, int height, ByteBuffer dataY, int strideY, ByteBuffer dataU, + int strideU, ByteBuffer dataV, int strideV, long nativeBuffer) { + this.width = width; + this.height = height; + this.dataY = dataY; + this.strideY = strideY; + this.dataU = dataU; + this.strideU = strideU; + this.dataV = dataV; + this.strideV = strideV; + this.nativeBuffer = nativeBuffer; + } + + @Override + public int getWidth() { + return width; + } + + @Override + public int getHeight() { + return height; + } + + @Override + public ByteBuffer getDataY() { + return dataY; + } + + @Override + public ByteBuffer getDataU() { + return dataU; + } + + @Override + public ByteBuffer getDataV() { + return dataV; + } + + @Override + public int getStrideY() { + return strideY; + } + + @Override + public int getStrideU() { + return strideU; + } + + @Override + public int getStrideV() { + return strideV; + } + + @Override + public VideoFrame.I420Buffer toI420() { + return this; + } + + @Override + public void retain() { + nativeAddRef(nativeBuffer); + } + + @Override + public void release() { + nativeRelease(nativeBuffer); + } + + private static native long nativeAddRef(long nativeBuffer); + private static native long nativeRelease(long nativeBuffer); +} diff --git a/webrtc/sdk/android/src/jni/classreferenceholder.cc b/webrtc/sdk/android/src/jni/classreferenceholder.cc index 263b564154..31c25e42f5 100644 --- a/webrtc/sdk/android/src/jni/classreferenceholder.cc +++ b/webrtc/sdk/android/src/jni/classreferenceholder.cc @@ -105,6 +105,7 @@ ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) { LoadClass(jni, "org/webrtc/VideoCapturer"); LoadClass(jni, "org/webrtc/VideoRenderer$I420Frame"); LoadClass(jni, "org/webrtc/VideoTrack"); + LoadClass(jni, "org/webrtc/WrappedNativeI420Buffer"); } ClassReferenceHolder::~ClassReferenceHolder() { diff --git a/webrtc/sdk/android/src/jni/wrapped_native_i420_buffer.cc b/webrtc/sdk/android/src/jni/wrapped_native_i420_buffer.cc new file mode 100644 index 0000000000..c9b691e114 --- /dev/null +++ b/webrtc/sdk/android/src/jni/wrapped_native_i420_buffer.cc @@ -0,0 +1,61 @@ +/* + * 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 "webrtc/sdk/android/src/jni/wrapped_native_i420_buffer.h" + +#include "webrtc/sdk/android/src/jni/classreferenceholder.h" +#include "webrtc/sdk/android/src/jni/jni_helpers.h" + +namespace webrtc_jni { + +// TODO(magjed): Write a test for this function. +jobject WrapI420Buffer( + const rtc::scoped_refptr& i420_buffer) { + JNIEnv* jni = AttachCurrentThreadIfNeeded(); + ScopedLocalRefFrame local_ref_frame(jni); + + jclass j_wrapped_native_i420_buffer_class = + FindClass(jni, "org/webrtc/WrappedNativeI420Buffer"); + jmethodID j_wrapped_native_i420_buffer_ctor_id = + GetMethodID(jni, j_wrapped_native_i420_buffer_class, "", + "(IILjava/nio/ByteBuffer;ILjava/nio/ByteBuffer;ILjava/nio/" + "ByteBuffer;IJ)V"); + + jobject y_buffer = + jni->NewDirectByteBuffer(const_cast(i420_buffer->DataY()), + i420_buffer->StrideY() * i420_buffer->height()); + jobject u_buffer = jni->NewDirectByteBuffer( + const_cast(i420_buffer->DataU()), + i420_buffer->StrideU() * i420_buffer->ChromaHeight()); + jobject v_buffer = jni->NewDirectByteBuffer( + const_cast(i420_buffer->DataV()), + i420_buffer->StrideV() * i420_buffer->ChromaHeight()); + + jobject j_wrapped_native_i420_buffer = jni->NewObject( + j_wrapped_native_i420_buffer_class, j_wrapped_native_i420_buffer_ctor_id, + i420_buffer->width(), i420_buffer->height(), y_buffer, + i420_buffer->StrideY(), u_buffer, i420_buffer->StrideU(), v_buffer, + i420_buffer->StrideV(), jlongFromPointer(i420_buffer.get())); + CHECK_EXCEPTION(jni); + + return j_wrapped_native_i420_buffer; +} + +JOW(void, WrappedNativeI420Buffer_nativeAddRef) +(JNIEnv* jni, jclass, jlong j_buffer_pointer) { + reinterpret_cast(j_buffer_pointer)->AddRef(); +} + +JOW(void, WrappedNativeI420Buffer_nativeRelease) +(JNIEnv* jni, jclass, jlong j_buffer_pointer) { + reinterpret_cast(j_buffer_pointer)->Release(); +} + +} // namespace webrtc_jni diff --git a/webrtc/sdk/android/src/jni/wrapped_native_i420_buffer.h b/webrtc/sdk/android/src/jni/wrapped_native_i420_buffer.h new file mode 100644 index 0000000000..e5ae137cd9 --- /dev/null +++ b/webrtc/sdk/android/src/jni/wrapped_native_i420_buffer.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef WEBRTC_SDK_ANDROID_SRC_JNI_WRAPPED_NATIVE_I420_BUFFER_H_ +#define WEBRTC_SDK_ANDROID_SRC_JNI_WRAPPED_NATIVE_I420_BUFFER_H_ + +#include + +#include "webrtc/api/video/video_frame_buffer.h" + +namespace webrtc_jni { + +// This function wraps the C++ I420 buffer and returns a Java +// VideoFrame.I420Buffer as a jobject. +jobject WrapI420Buffer( + const rtc::scoped_refptr& i420_buffer); + +} // namespace webrtc_jni + +#endif // WEBRTC_SDK_ANDROID_SRC_JNI_WRAPPED_NATIVE_I420_BUFFER_H_