Pass java EncodedImage over jni to VideoEncoderWrapper::OnEncodedFrame

Preparation for adding a release() method on java's EncodedImage, and
call that from C++.

Bug: webrtc:9378
Change-Id: I301f64b16684c535f45a3fc9cd9ae1543df59d92
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/141861
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28268}
This commit is contained in:
Niels Möller
2019-06-13 14:37:24 +02:00
committed by Commit Bot
parent f3f57700a8
commit 6fd67f086c
6 changed files with 103 additions and 48 deletions

View File

@ -10,6 +10,7 @@
package org.webrtc; package org.webrtc;
import android.support.annotation.Nullable;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -53,11 +54,11 @@ public class EncodedImage {
public final FrameType frameType; public final FrameType frameType;
public final int rotation; public final int rotation;
public final boolean completeFrame; public final boolean completeFrame;
public final Integer qp; public final @Nullable Integer qp;
@CalledByNative @CalledByNative
private EncodedImage(ByteBuffer buffer, int encodedWidth, int encodedHeight, long captureTimeNs, private EncodedImage(ByteBuffer buffer, int encodedWidth, int encodedHeight, long captureTimeNs,
FrameType frameType, int rotation, boolean completeFrame, Integer qp) { FrameType frameType, int rotation, boolean completeFrame, @Nullable Integer qp) {
this.buffer = buffer; this.buffer = buffer;
this.encodedWidth = encodedWidth; this.encodedWidth = encodedWidth;
this.encodedHeight = encodedHeight; this.encodedHeight = encodedHeight;
@ -69,6 +70,46 @@ public class EncodedImage {
this.qp = qp; this.qp = qp;
} }
@CalledByNative
private ByteBuffer getBuffer() {
return buffer;
}
@CalledByNative
private int getEncodedWidth() {
return encodedWidth;
}
@CalledByNative
private int getEncodedHeight() {
return encodedHeight;
}
@CalledByNative
private long getCaptureTimeNs() {
return captureTimeNs;
}
@CalledByNative
private int getFrameType() {
return frameType.getNative();
}
@CalledByNative
private int getRotation() {
return rotation;
}
@CalledByNative
private boolean getCompleteFrame() {
return completeFrame;
}
@CalledByNative
private @Nullable Integer getQp() {
return qp;
}
public static Builder builder() { public static Builder builder() {
return new Builder(); return new Builder();
} }
@ -81,7 +122,7 @@ public class EncodedImage {
private EncodedImage.FrameType frameType; private EncodedImage.FrameType frameType;
private int rotation; private int rotation;
private boolean completeFrame; private boolean completeFrame;
private Integer qp; private @Nullable Integer qp;
private Builder() {} private Builder() {}
@ -126,7 +167,7 @@ public class EncodedImage {
return this; return this;
} }
public Builder setQp(Integer qp) { public Builder setQp(@Nullable Integer qp) {
this.qp = qp; this.qp = qp;
return this; return this;
} }

View File

@ -38,13 +38,10 @@ class VideoEncoderWrapper {
@CalledByNative @CalledByNative
static VideoEncoder.Callback createEncoderCallback(final long nativeEncoder) { static VideoEncoder.Callback createEncoderCallback(final long nativeEncoder) {
return (EncodedImage frame, VideoEncoder.CodecSpecificInfo info) return (EncodedImage frame,
-> nativeOnEncodedFrame(nativeEncoder, frame.buffer, frame.encodedWidth, VideoEncoder.CodecSpecificInfo info) -> nativeOnEncodedFrame(nativeEncoder, frame);
frame.encodedHeight, frame.captureTimeNs, frame.frameType.getNative(),
frame.rotation, frame.completeFrame, frame.qp);
} }
private static native void nativeOnEncodedFrame(long nativeVideoEncoderWrapper, ByteBuffer buffer, private static native void nativeOnEncodedFrame(
int encodedWidth, int encodedHeight, long captureTimeNs, int frameType, int rotation, long nativeVideoEncoderWrapper, EncodedImage frame);
boolean completeFrame, Integer qp);
} }

View File

@ -49,5 +49,40 @@ ScopedJavaLocalRef<jobjectArray> NativeToJavaFrameTypeArray(
&NativeToJavaFrameType); &NativeToJavaFrameType);
} }
EncodedImage JavaToNativeEncodedImage(JNIEnv* env,
const JavaRef<jobject>& j_encoded_image) {
const JavaRef<jobject>& j_buffer =
Java_EncodedImage_getBuffer(env, j_encoded_image);
const uint8_t* buffer =
static_cast<uint8_t*>(env->GetDirectBufferAddress(j_buffer.obj()));
const size_t buffer_size = env->GetDirectBufferCapacity(j_buffer.obj());
EncodedImage frame;
frame.Allocate(buffer_size);
frame.set_size(buffer_size);
memcpy(frame.data(), buffer, buffer_size);
frame._encodedWidth = Java_EncodedImage_getEncodedWidth(env, j_encoded_image);
frame._encodedHeight =
Java_EncodedImage_getEncodedHeight(env, j_encoded_image);
frame.rotation_ =
(VideoRotation)Java_EncodedImage_getRotation(env, j_encoded_image);
frame._completeFrame =
Java_EncodedImage_getCompleteFrame(env, j_encoded_image);
frame.qp_ = JavaToNativeOptionalInt(
env, Java_EncodedImage_getQp(env, j_encoded_image))
.value_or(-1);
frame._frameType =
(VideoFrameType)Java_EncodedImage_getFrameType(env, j_encoded_image);
return frame;
}
int64_t GetJavaEncodedImageCaptureTimeNs(
JNIEnv* env,
const JavaRef<jobject>& j_encoded_image) {
return Java_EncodedImage_getCaptureTimeNs(env, j_encoded_image);
}
} // namespace jni } // namespace jni
} // namespace webrtc } // namespace webrtc

View File

@ -32,6 +32,13 @@ ScopedJavaLocalRef<jobjectArray> NativeToJavaFrameTypeArray(
JNIEnv* env, JNIEnv* env,
const std::vector<VideoFrameType>& frame_types); const std::vector<VideoFrameType>& frame_types);
EncodedImage JavaToNativeEncodedImage(JNIEnv* env,
const JavaRef<jobject>& j_encoded_image);
int64_t GetJavaEncodedImageCaptureTimeNs(
JNIEnv* jni,
const JavaRef<jobject>& j_encoded_image);
} // namespace jni } // namespace jni
} // namespace webrtc } // namespace webrtc

View File

@ -214,38 +214,18 @@ VideoEncoderWrapper::GetScalingSettingsInternal(JNIEnv* jni) const {
} }
} }
void VideoEncoderWrapper::OnEncodedFrame(JNIEnv* jni, void VideoEncoderWrapper::OnEncodedFrame(
JNIEnv* jni,
const JavaRef<jobject>& j_caller, const JavaRef<jobject>& j_caller,
const JavaRef<jobject>& j_buffer, const JavaRef<jobject>& j_encoded_image) {
jint encoded_width, EncodedImage frame = JavaToNativeEncodedImage(jni, j_encoded_image);
jint encoded_height, int64_t capture_time_ns =
jlong capture_time_ns, GetJavaEncodedImageCaptureTimeNs(jni, j_encoded_image);
jint frame_type,
jint rotation,
jboolean complete_frame,
const JavaRef<jobject>& j_qp) {
const uint8_t* buffer =
static_cast<uint8_t*>(jni->GetDirectBufferAddress(j_buffer.obj()));
const size_t buffer_size = jni->GetDirectBufferCapacity(j_buffer.obj());
EncodedImage frame;
frame.Allocate(buffer_size);
frame.set_size(buffer_size);
memcpy(frame.data(), buffer, buffer_size);
frame._encodedWidth = encoded_width;
frame._encodedHeight = encoded_height;
frame.rotation_ = (VideoRotation)rotation;
frame._completeFrame = complete_frame;
const absl::optional<int> qp = JavaToNativeOptionalInt(jni, j_qp);
frame._frameType = (VideoFrameType)frame_type;
{ {
rtc::CritScope lock(&encoder_queue_crit_); rtc::CritScope lock(&encoder_queue_crit_);
if (encoder_queue_ != nullptr) { if (encoder_queue_ != nullptr) {
encoder_queue_->PostTask(ToQueuedTask([this, frame, qp, encoder_queue_->PostTask(ToQueuedTask([this, frame, capture_time_ns]() {
capture_time_ns]() {
// Encoded frames are delivered in the order received, but some of them // Encoded frames are delivered in the order received, but some of them
// may be dropped, so remove records of frames older than the current // may be dropped, so remove records of frames older than the current
// one. // one.
@ -284,7 +264,9 @@ void VideoEncoderWrapper::OnEncodedFrame(JNIEnv* jni,
capture_time_ns / rtc::kNumNanosecsPerMillisec; capture_time_ns / rtc::kNumNanosecsPerMillisec;
RTPFragmentationHeader header = ParseFragmentationHeader(frame); RTPFragmentationHeader header = ParseFragmentationHeader(frame);
frame_copy.qp_ = qp ? *qp : ParseQp(frame); if (frame_copy.qp_ < 0)
frame_copy.qp_ = ParseQp(frame);
CodecSpecificInfo info(ParseCodecSpecificInfo(frame)); CodecSpecificInfo info(ParseCodecSpecificInfo(frame));
callback_->OnEncodedImage(frame_copy, &info, &header); callback_->OnEncodedImage(frame_copy, &info, &header);

View File

@ -51,14 +51,7 @@ class VideoEncoderWrapper : public VideoEncoder {
// Should only be called by JNI. // Should only be called by JNI.
void OnEncodedFrame(JNIEnv* jni, void OnEncodedFrame(JNIEnv* jni,
const JavaRef<jobject>& j_caller, const JavaRef<jobject>& j_caller,
const JavaRef<jobject>& j_buffer, const JavaRef<jobject>& j_encoded_image);
jint encoded_width,
jint encoded_height,
jlong capture_time_ms,
jint frame_type,
jint rotation,
jboolean complete_frame,
const JavaRef<jobject>& j_qp);
private: private:
struct FrameExtraInfo { struct FrameExtraInfo {