Android: Generate all C++ -> Java JNI code for VideoEncoder
The first example CL for generating JNI code
(https://webrtc-review.googlesource.com/c/src/+/4500) seems to stick, so
this CL updates the rest of the VideoEncoder. The JNI code for
Java -> C++ is still done manually.
This CL puts the necessary helper Java methods in a class called
VideoEncoderWrapper.
Bug: webrtc:8278
Change-Id: Ic3a6defe59c094f67ffd8ea86d6c272c676980ae
Reviewed-on: https://webrtc-review.googlesource.com/20871
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20587}
diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn
index b2bef9e..5bb7300 100644
--- a/sdk/android/BUILD.gn
+++ b/sdk/android/BUILD.gn
@@ -103,8 +103,10 @@
generate_jni("generated_video_jni") {
sources = [
+ "api/org/webrtc/VideoCodecStatus.java",
"api/org/webrtc/VideoEncoder.java",
"api/org/webrtc/VideoSink.java",
+ "src/java/org/webrtc/VideoEncoderWrapper.java",
]
jni_package = ""
jni_generator_include = "//sdk/android/src/jni/jni_generator_helper.h"
@@ -492,7 +494,7 @@
"src/java/org/webrtc/TextureBufferImpl.java",
"src/java/org/webrtc/VideoCodecType.java",
"src/java/org/webrtc/VideoDecoderWrapperCallback.java",
- "src/java/org/webrtc/VideoEncoderWrapperCallback.java",
+ "src/java/org/webrtc/VideoEncoderWrapper.java",
"src/java/org/webrtc/WrappedNativeI420Buffer.java",
]
diff --git a/sdk/android/api/org/webrtc/EncodedImage.java b/sdk/android/api/org/webrtc/EncodedImage.java
index 6720cd7..c6c56ce 100644
--- a/sdk/android/api/org/webrtc/EncodedImage.java
+++ b/sdk/android/api/org/webrtc/EncodedImage.java
@@ -33,15 +33,6 @@
public int getNative() {
return nativeIndex;
}
-
- public static FrameType fromNative(int nativeIndex) {
- for (FrameType type : FrameType.values()) {
- if (type.nativeIndex == nativeIndex) {
- return type;
- }
- }
- throw new IllegalArgumentException("Unknown native frame type: " + nativeIndex);
- }
}
public final ByteBuffer buffer;
diff --git a/sdk/android/api/org/webrtc/VideoCodecStatus.java b/sdk/android/api/org/webrtc/VideoCodecStatus.java
index 3a7c81f..a86d6fb 100644
--- a/sdk/android/api/org/webrtc/VideoCodecStatus.java
+++ b/sdk/android/api/org/webrtc/VideoCodecStatus.java
@@ -35,6 +35,7 @@
this.number = number;
}
+ @CalledByNative
public int getNumber() {
return number;
}
diff --git a/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java b/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java
new file mode 100644
index 0000000..6d7924a
--- /dev/null
+++ b/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java
@@ -0,0 +1,80 @@
+/*
+ * 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;
+
+// Explicit imports necessary for JNI generation.
+import org.webrtc.EncodedImage;
+import org.webrtc.VideoEncoder;
+import java.nio.ByteBuffer;
+
+/**
+ * This class contains the Java glue code for JNI generation of VideoEncoder.
+ */
+class VideoEncoderWrapper {
+ @CalledByNative
+ static VideoEncoder.Settings createSettings(int numberOfCores, int width, int height,
+ int startBitrate, int maxFramerate, boolean automaticResizeOn) {
+ return new VideoEncoder.Settings(
+ numberOfCores, width, height, startBitrate, maxFramerate, automaticResizeOn);
+ }
+
+ @CalledByNative
+ static VideoEncoder.EncodeInfo createEncodeInfo(EncodedImage.FrameType[] frameTypes) {
+ return new VideoEncoder.EncodeInfo(frameTypes);
+ }
+
+ @CalledByNative
+ static VideoEncoder.BitrateAllocation createBitrateAllocation(int[][] bitratesBbs) {
+ return new VideoEncoder.BitrateAllocation(bitratesBbs);
+ }
+
+ @CalledByNative
+ static EncodedImage.FrameType createFrameType(int nativeIndex) {
+ for (EncodedImage.FrameType type : EncodedImage.FrameType.values()) {
+ if (type.getNative() == nativeIndex) {
+ return type;
+ }
+ }
+ throw new IllegalArgumentException("Unknown native frame type: " + nativeIndex);
+ }
+
+ @CalledByNative
+ static boolean getScalingSettingsOn(VideoEncoder.ScalingSettings scalingSettings) {
+ return scalingSettings.on;
+ }
+
+ @CalledByNative
+ static Integer getScalingSettingsLow(VideoEncoder.ScalingSettings scalingSettings) {
+ return scalingSettings.low;
+ }
+
+ @CalledByNative
+ static Integer getScalingSettingsHigh(VideoEncoder.ScalingSettings scalingSettings) {
+ return scalingSettings.high;
+ }
+
+ @CalledByNative
+ static int getIntValue(Integer i) {
+ return i.intValue();
+ }
+
+ @CalledByNative
+ static VideoEncoder.Callback createEncoderCallback(final long nativeEncoder) {
+ return (EncodedImage frame, VideoEncoder.CodecSpecificInfo info)
+ -> onEncodedFrame(nativeEncoder, frame.buffer, frame.encodedWidth,
+ frame.encodedHeight, frame.captureTimeNs, frame.frameType.getNative(),
+ frame.rotation, frame.completeFrame, frame.qp);
+ }
+
+ private static native void onEncodedFrame(long nativeEncoder, ByteBuffer buffer, int encodedWidth,
+ int encodedHeight, long captureTimeNs, int frameType, int rotation, boolean completeFrame,
+ Integer qp);
+}
diff --git a/sdk/android/src/java/org/webrtc/VideoEncoderWrapperCallback.java b/sdk/android/src/java/org/webrtc/VideoEncoderWrapperCallback.java
deleted file mode 100644
index 0a8a8a6..0000000
--- a/sdk/android/src/java/org/webrtc/VideoEncoderWrapperCallback.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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;
-
-/**
- * VideoEncoder callback that calls VideoEncoderWrapper.OnEncodedFrame for the Encoded frames.
- */
-class VideoEncoderWrapperCallback implements VideoEncoder.Callback {
- private final long nativeEncoder;
-
- public VideoEncoderWrapperCallback(long nativeEncoder) {
- this.nativeEncoder = nativeEncoder;
- }
-
- @Override
- public void onEncodedFrame(EncodedImage frame, VideoEncoder.CodecSpecificInfo info) {
- nativeOnEncodedFrame(nativeEncoder, frame.buffer, frame.encodedWidth, frame.encodedHeight,
- frame.captureTimeNs, frame.frameType.getNative(), frame.rotation, frame.completeFrame,
- frame.qp);
- }
-
- private native static void nativeOnEncodedFrame(long nativeEncoder, ByteBuffer buffer,
- int encodedWidth, int encodedHeight, long captureTimeNs, int frameType, int rotation,
- boolean completeFrame, Integer qp);
-}
diff --git a/sdk/android/src/jni/classreferenceholder.cc b/sdk/android/src/jni/classreferenceholder.cc
index e4ff16f..0aa3e62 100644
--- a/sdk/android/src/jni/classreferenceholder.cc
+++ b/sdk/android/src/jni/classreferenceholder.cc
@@ -111,11 +111,6 @@
LoadClass(jni, "org/webrtc/VideoCodecStatus");
LoadClass(jni, "org/webrtc/VideoDecoder$Settings");
LoadClass(jni, "org/webrtc/VideoDecoderWrapperCallback");
- LoadClass(jni, "org/webrtc/VideoEncoder$BitrateAllocation");
- LoadClass(jni, "org/webrtc/VideoEncoder$EncodeInfo");
- LoadClass(jni, "org/webrtc/VideoEncoder$ScalingSettings");
- LoadClass(jni, "org/webrtc/VideoEncoder$Settings");
- LoadClass(jni, "org/webrtc/VideoEncoderWrapperCallback");
LoadClass(jni, "org/webrtc/VideoFrame");
LoadClass(jni, "org/webrtc/VideoFrame$Buffer");
LoadClass(jni, "org/webrtc/VideoFrame$I420Buffer");
diff --git a/sdk/android/src/jni/videoencoderwrapper.cc b/sdk/android/src/jni/videoencoderwrapper.cc
index 7c76b4e..d85844c 100644
--- a/sdk/android/src/jni/videoencoderwrapper.cc
+++ b/sdk/android/src/jni/videoencoderwrapper.cc
@@ -21,8 +21,10 @@
#include "rtc_base/logging.h"
#include "rtc_base/random.h"
#include "rtc_base/timeutils.h"
+#include "sdk/android/generated_video_jni/jni/VideoCodecStatus_jni.h"
+#include "sdk/android/generated_video_jni/jni/VideoEncoderWrapper_jni.h"
#include "sdk/android/generated_video_jni/jni/VideoEncoder_jni.h"
-#include "sdk/android/src/jni/classreferenceholder.h"
+#include "sdk/android/src/jni/class_loader.h"
namespace webrtc {
namespace jni {
@@ -31,46 +33,10 @@
VideoEncoderWrapper::VideoEncoderWrapper(JNIEnv* jni, jobject j_encoder)
: encoder_(jni, j_encoder),
- settings_class_(jni, FindClass(jni, "org/webrtc/VideoEncoder$Settings")),
- encode_info_class_(jni,
- FindClass(jni, "org/webrtc/VideoEncoder$EncodeInfo")),
frame_type_class_(jni,
- FindClass(jni, "org/webrtc/EncodedImage$FrameType")),
- bitrate_allocation_class_(
- jni,
- FindClass(jni, "org/webrtc/VideoEncoder$BitrateAllocation")),
+ GetClass(jni, "org/webrtc/EncodedImage$FrameType")),
int_array_class_(jni, jni->FindClass("[I")),
video_frame_factory_(jni) {
- settings_constructor_ =
- jni->GetMethodID(*settings_class_, "<init>", "(IIIIIZ)V");
-
- encode_info_constructor_ = jni->GetMethodID(
- *encode_info_class_, "<init>", "([Lorg/webrtc/EncodedImage$FrameType;)V");
-
- frame_type_from_native_method_ =
- jni->GetStaticMethodID(*frame_type_class_, "fromNative",
- "(I)Lorg/webrtc/EncodedImage$FrameType;");
-
- bitrate_allocation_constructor_ =
- jni->GetMethodID(*bitrate_allocation_class_, "<init>", "([[I)V");
-
- jclass video_codec_status_class =
- FindClass(jni, "org/webrtc/VideoCodecStatus");
- get_number_method_ =
- jni->GetMethodID(video_codec_status_class, "getNumber", "()I");
-
- jclass integer_class = jni->FindClass("java/lang/Integer");
- int_value_method_ = jni->GetMethodID(integer_class, "intValue", "()I");
-
- jclass scaling_settings_class =
- FindClass(jni, "org/webrtc/VideoEncoder$ScalingSettings");
- scaling_settings_on_field_ =
- jni->GetFieldID(scaling_settings_class, "on", "Z");
- scaling_settings_low_field_ =
- jni->GetFieldID(scaling_settings_class, "low", "Ljava/lang/Integer;");
- scaling_settings_high_field_ =
- jni->GetFieldID(scaling_settings_class, "high", "Ljava/lang/Integer;");
-
implementation_name_ = GetImplementationName(jni);
initialized_ = false;
@@ -108,23 +74,18 @@
automatic_resize_on = true;
}
- jobject settings =
- jni->NewObject(*settings_class_, settings_constructor_, number_of_cores_,
- codec_settings_.width, codec_settings_.height,
- codec_settings_.startBitrate, codec_settings_.maxFramerate,
- automatic_resize_on);
+ jobject settings = Java_VideoEncoderWrapper_createSettings(
+ jni, number_of_cores_, codec_settings_.width, codec_settings_.height,
+ codec_settings_.startBitrate, codec_settings_.maxFramerate,
+ automatic_resize_on);
- jclass callback_class =
- FindClass(jni, "org/webrtc/VideoEncoderWrapperCallback");
- jmethodID callback_constructor =
- jni->GetMethodID(callback_class, "<init>", "(J)V");
- jobject callback = jni->NewObject(callback_class, callback_constructor,
- jlongFromPointer(this));
+ jobject callback = Java_VideoEncoderWrapper_createEncoderCallback(
+ jni, jlongFromPointer(this));
jobject ret =
Java_VideoEncoder_initEncode(jni, *encoder_, settings, callback);
- if (jni->CallIntMethod(ret, get_number_method_) == WEBRTC_VIDEO_CODEC_OK) {
+ if (Java_VideoCodecStatus_getNumber(jni, ret) == WEBRTC_VIDEO_CODEC_OK) {
initialized_ = true;
}
@@ -163,13 +124,12 @@
jobjectArray j_frame_types =
jni->NewObjectArray(frame_types->size(), *frame_type_class_, nullptr);
for (size_t i = 0; i < frame_types->size(); ++i) {
- jobject j_frame_type = jni->CallStaticObjectMethod(
- *frame_type_class_, frame_type_from_native_method_,
- static_cast<jint>((*frame_types)[i]));
+ jobject j_frame_type = Java_VideoEncoderWrapper_createFrameType(
+ jni, static_cast<jint>((*frame_types)[i]));
jni->SetObjectArrayElement(j_frame_types, i, j_frame_type);
}
- jobject encode_info = jni->NewObject(*encode_info_class_,
- encode_info_constructor_, j_frame_types);
+ jobject encode_info =
+ Java_VideoEncoderWrapper_createEncodeInfo(jni, j_frame_types);
FrameExtraInfo info;
info.capture_time_ns = frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec;
@@ -210,17 +170,17 @@
jobject j_scaling_settings =
Java_VideoEncoder_getScalingSettings(jni, *encoder_);
bool on =
- jni->GetBooleanField(j_scaling_settings, scaling_settings_on_field_);
+ Java_VideoEncoderWrapper_getScalingSettingsOn(jni, j_scaling_settings);
jobject j_low =
- jni->GetObjectField(j_scaling_settings, scaling_settings_low_field_);
+ Java_VideoEncoderWrapper_getScalingSettingsLow(jni, j_scaling_settings);
jobject j_high =
- jni->GetObjectField(j_scaling_settings, scaling_settings_high_field_);
+ Java_VideoEncoderWrapper_getScalingSettingsHigh(jni, j_scaling_settings);
if (j_low != nullptr || j_high != nullptr) {
RTC_DCHECK(j_low != nullptr);
RTC_DCHECK(j_high != nullptr);
- int low = jni->CallIntMethod(j_low, int_value_method_);
- int high = jni->CallIntMethod(j_high, int_value_method_);
+ int low = Java_VideoEncoderWrapper_getIntValue(jni, j_low);
+ int high = Java_VideoEncoderWrapper_getIntValue(jni, j_high);
return ScalingSettings(on, low, high);
} else {
return ScalingSettings(on);
@@ -248,7 +208,7 @@
memcpy(buffer_copy.data(), buffer, buffer_size);
int qp = -1;
if (j_qp != nullptr) {
- qp = jni->CallIntMethod(j_qp, int_value_method_);
+ qp = Java_VideoEncoderWrapper_getIntValue(jni, j_qp);
}
encoder_queue_->PostTask(
@@ -293,7 +253,7 @@
}
int32_t VideoEncoderWrapper::HandleReturnCode(JNIEnv* jni, jobject code) {
- int32_t value = jni->CallIntMethod(code, get_number_method_);
+ int32_t value = Java_VideoCodecStatus_getNumber(jni, code);
if (value < 0) { // Any errors are represented by negative values.
// Try resetting the codec.
if (++num_resets_ <= kMaxJavaEncoderResets &&
@@ -433,8 +393,8 @@
jni->SetObjectArrayElement(j_allocation_array, spatial_i,
j_array_spatial_layer);
}
- return jni->NewObject(*bitrate_allocation_class_,
- bitrate_allocation_constructor_, j_allocation_array);
+ return Java_VideoEncoderWrapper_createBitrateAllocation(jni,
+ j_allocation_array);
}
std::string VideoEncoderWrapper::GetImplementationName(JNIEnv* jni) const {
@@ -443,7 +403,7 @@
}
JNI_FUNCTION_DECLARATION(void,
- VideoEncoderWrapperCallback_nativeOnEncodedFrame,
+ VideoEncoderWrapper_onEncodedFrame,
JNIEnv* jni,
jclass,
jlong j_native_encoder,
diff --git a/sdk/android/src/jni/videoencoderwrapper.h b/sdk/android/src/jni/videoencoderwrapper.h
index 866002a..7717eb8 100644
--- a/sdk/android/src/jni/videoencoderwrapper.h
+++ b/sdk/android/src/jni/videoencoderwrapper.h
@@ -26,9 +26,7 @@
namespace webrtc {
namespace jni {
-// Wraps a Java decoder and delegates all calls to it. Passes
-// VideoEncoderWrapperCallback to the decoder on InitDecode. Wraps the received
-// frames to AndroidVideoBuffer.
+// Wraps a Java encoder and delegates all calls to it.
class VideoEncoderWrapper : public VideoEncoder {
public:
VideoEncoderWrapper(JNIEnv* jni, jobject j_encoder);
@@ -90,28 +88,9 @@
std::string GetImplementationName(JNIEnv* jni) const;
const ScopedGlobalRef<jobject> encoder_;
- const ScopedGlobalRef<jclass> settings_class_;
- const ScopedGlobalRef<jclass> encode_info_class_;
const ScopedGlobalRef<jclass> frame_type_class_;
- const ScopedGlobalRef<jclass> bitrate_allocation_class_;
const ScopedGlobalRef<jclass> int_array_class_;
- jmethodID settings_constructor_;
-
- jmethodID encode_info_constructor_;
-
- jmethodID frame_type_from_native_method_;
-
- jmethodID bitrate_allocation_constructor_;
-
- jfieldID scaling_settings_on_field_;
- jfieldID scaling_settings_low_field_;
- jfieldID scaling_settings_high_field_;
-
- jmethodID get_number_method_;
-
- jmethodID int_value_method_;
-
std::string implementation_name_;
rtc::TaskQueue* encoder_queue_;