diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn index 9daae54666..98ba0da641 100644 --- a/sdk/android/BUILD.gn +++ b/sdk/android/BUILD.gn @@ -105,11 +105,14 @@ rtc_static_library("null_audio_jni") { generate_jni("generated_video_jni") { sources = [ + "api/org/webrtc/EncodedImage.java", "api/org/webrtc/SurfaceTextureHelper.java", "api/org/webrtc/VideoCodecStatus.java", + "api/org/webrtc/VideoDecoder.java", "api/org/webrtc/VideoEncoder.java", "api/org/webrtc/VideoFrame.java", "api/org/webrtc/VideoSink.java", + "src/java/org/webrtc/VideoDecoderWrapper.java", "src/java/org/webrtc/VideoEncoderWrapper.java", "src/java/org/webrtc/WrappedNativeVideoDecoder.java", "src/java/org/webrtc/WrappedNativeVideoEncoder.java", @@ -128,6 +131,8 @@ rtc_static_library("video_jni") { "src/jni/androidvideotracksource.cc", "src/jni/androidvideotracksource.h", "src/jni/androidvideotracksource_jni.cc", + "src/jni/encodedimage.cc", + "src/jni/encodedimage.h", "src/jni/hardwarevideoencoderfactory.cc", "src/jni/jni_generator_helper.h", "src/jni/nv12buffer_jni.cc", @@ -138,6 +143,8 @@ rtc_static_library("video_jni") { "src/jni/video_renderer_jni.cc", "src/jni/videocodecinfo.cc", "src/jni/videocodecinfo.h", + "src/jni/videocodecstatus.cc", + "src/jni/videocodecstatus.h", "src/jni/videodecoderfactorywrapper.cc", "src/jni/videodecoderfactorywrapper.h", "src/jni/videodecoderfallback.cc", @@ -447,6 +454,7 @@ dist_jar("libwebrtc") { rtc_android_library("libjingle_peerconnection_java") { java_files = [ + "src/java/org/webrtc/VideoDecoderWrapper.java", "api/org/webrtc/AudioProcessingFactory.java", "api/org/webrtc/AudioSource.java", "api/org/webrtc/AudioTrack.java", @@ -548,7 +556,6 @@ rtc_android_library("libjingle_peerconnection_java") { "src/java/org/webrtc/NV21Buffer.java", "src/java/org/webrtc/TextureBufferImpl.java", "src/java/org/webrtc/VideoCodecType.java", - "src/java/org/webrtc/VideoDecoderWrapperCallback.java", "src/java/org/webrtc/VideoEncoderWrapper.java", "src/java/org/webrtc/WrappedNativeI420Buffer.java", "src/java/org/webrtc/WrappedNativeVideoEncoder.java", diff --git a/sdk/android/api/org/webrtc/EncodedImage.java b/sdk/android/api/org/webrtc/EncodedImage.java index c6c56ce532..dc8eb62615 100644 --- a/sdk/android/api/org/webrtc/EncodedImage.java +++ b/sdk/android/api/org/webrtc/EncodedImage.java @@ -12,6 +12,8 @@ package org.webrtc; import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit; +// TODO(bugs.webrtc.org/8556): Remove unnecessary import. +import org.webrtc.EncodedImage; /** * An encoded frame from a video stream. Used as an input for decoders and as an output for @@ -33,6 +35,17 @@ public class EncodedImage { public int getNative() { return nativeIndex; } + + // TODO(bugs.webrtc.org/8556): Remove unnecessary 'EncodedImage.'. + @CalledByNative("FrameType") + static EncodedImage.FrameType fromNativeIndex(int nativeIndex) { + for (FrameType type : FrameType.values()) { + if (type.getNative() == nativeIndex) { + return type; + } + } + throw new IllegalArgumentException("Unknown native frame type: " + nativeIndex); + } } public final ByteBuffer buffer; @@ -125,4 +138,13 @@ public class EncodedImage { rotation, completeFrame, qp); } } + + // TODO(bugs.webrtc.org/8551) Remove. + @CalledByNative + static EncodedImage create(ByteBuffer buffer, int encodedWidth, int encodedHeight, + long captureTimeNs, EncodedImage.FrameType frameType, int rotation, boolean completeFrame, + Integer qp) { + return new EncodedImage( + buffer, encodedWidth, encodedHeight, captureTimeNs, frameType, rotation, completeFrame, qp); + } } diff --git a/sdk/android/api/org/webrtc/VideoDecoder.java b/sdk/android/api/org/webrtc/VideoDecoder.java index 76b030ca24..f5acfad0fc 100644 --- a/sdk/android/api/org/webrtc/VideoDecoder.java +++ b/sdk/android/api/org/webrtc/VideoDecoder.java @@ -54,23 +54,23 @@ public interface VideoDecoder { * Initializes the decoding process with specified settings. Will be called on the decoding thread * before any decode calls. */ - VideoCodecStatus initDecode(Settings settings, Callback decodeCallback); + @CalledByNative VideoCodecStatus initDecode(Settings settings, Callback decodeCallback); /** * Called when the decoder is no longer needed. Any more calls to decode will not be made. */ - VideoCodecStatus release(); + @CalledByNative VideoCodecStatus release(); /** * Request the decoder to decode a frame. */ - VideoCodecStatus decode(EncodedImage frame, DecodeInfo info); + @CalledByNative VideoCodecStatus decode(EncodedImage frame, DecodeInfo info); /** * The decoder should return true if it prefers late decoding. That is, it can not decode * infinite number of frames before the decoded frame is consumed. */ - boolean getPrefersLateDecoding(); + @CalledByNative boolean getPrefersLateDecoding(); /** * Should return a descriptive name for the implementation. Gets called once and cached. May be * called from arbitrary thread. */ - String getImplementationName(); + @CalledByNative String getImplementationName(); } diff --git a/sdk/android/src/java/org/webrtc/VideoDecoderWrapper.java b/sdk/android/src/java/org/webrtc/VideoDecoderWrapper.java new file mode 100644 index 0000000000..97134c51a8 --- /dev/null +++ b/sdk/android/src/java/org/webrtc/VideoDecoderWrapper.java @@ -0,0 +1,34 @@ +/* + * 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 org.webrtc.VideoDecoder; + +/** + * This class contains the Java glue code for JNI generation of VideoDecoder. + */ +class VideoDecoderWrapper { + // TODO(bugs.webrtc.org/8551) Remove. + @CalledByNative + static VideoDecoder.Settings createSettings(int numberOfCores, int width, int height) { + return new VideoDecoder.Settings(numberOfCores, width, height); + } + + @CalledByNative + static VideoDecoder.Callback createDecoderCallback(final long nativeDecoder) { + return (VideoFrame frame, Integer decodeTimeMs, + Integer qp) -> nativeOnDecodedFrame(nativeDecoder, frame, decodeTimeMs, qp); + } + + @NativeClassQualifiedName("webrtc::jni::VideoDecoderWrapper") + private static native void nativeOnDecodedFrame( + long nativeDecoder, VideoFrame frame, Integer decodeTimeMs, Integer qp); +} diff --git a/sdk/android/src/java/org/webrtc/VideoDecoderWrapperCallback.java b/sdk/android/src/java/org/webrtc/VideoDecoderWrapperCallback.java deleted file mode 100644 index 232466d7cb..0000000000 --- a/sdk/android/src/java/org/webrtc/VideoDecoderWrapperCallback.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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. - */ - -package org.webrtc; - -/** - * VideoDecoder callback that calls VideoDecoderWrapper.OnDecodedFrame for the decoded frames. - */ -class VideoDecoderWrapperCallback implements VideoDecoder.Callback { - private final long nativeDecoder; - - public VideoDecoderWrapperCallback(long nativeDecoder) { - this.nativeDecoder = nativeDecoder; - } - - @Override - public void onDecodedFrame(VideoFrame frame, Integer decodeTimeMs, Integer qp) { - nativeOnDecodedFrame(nativeDecoder, frame, decodeTimeMs, qp); - } - - private native static void nativeOnDecodedFrame( - long nativeDecoder, VideoFrame frame, Integer decodeTimeMs, Integer qp); -} diff --git a/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java b/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java index b2bc081c87..5acfe677e4 100644 --- a/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java +++ b/sdk/android/src/java/org/webrtc/VideoEncoderWrapper.java @@ -36,16 +36,6 @@ class VideoEncoderWrapper { 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; diff --git a/sdk/android/src/jni/classreferenceholder.cc b/sdk/android/src/jni/classreferenceholder.cc index 25cb38c5c6..910aa5692c 100644 --- a/sdk/android/src/jni/classreferenceholder.cc +++ b/sdk/android/src/jni/classreferenceholder.cc @@ -113,8 +113,6 @@ ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) { LoadClass(jni, "org/webrtc/VideoCapturer"); LoadClass(jni, "org/webrtc/VideoCodecInfo"); LoadClass(jni, "org/webrtc/VideoCodecStatus"); - LoadClass(jni, "org/webrtc/VideoDecoder$Settings"); - LoadClass(jni, "org/webrtc/VideoDecoderWrapperCallback"); LoadClass(jni, "org/webrtc/VideoFrame"); LoadClass(jni, "org/webrtc/VideoFrame$Buffer"); LoadClass(jni, "org/webrtc/VideoFrame$I420Buffer"); diff --git a/sdk/android/src/jni/encodedimage.cc b/sdk/android/src/jni/encodedimage.cc new file mode 100644 index 0000000000..f540b77f1e --- /dev/null +++ b/sdk/android/src/jni/encodedimage.cc @@ -0,0 +1,35 @@ +/* + * 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. + */ + +#include "sdk/android/src/jni/encodedimage.h" + +#include "common_video/include/video_frame.h" +#include "rtc_base/timeutils.h" +#include "sdk/android/generated_video_jni/jni/EncodedImage_jni.h" + +namespace webrtc { +namespace jni { + +jobject NativeToJavaFrameType(JNIEnv* env, FrameType frame_type) { + return Java_FrameType_fromNativeIndex(env, frame_type); +} + +jobject NativeToJavaEncodedImage(JNIEnv* jni, const EncodedImage& image) { + jobject buffer = jni->NewDirectByteBuffer(image._buffer, image._length); + jobject frame_type = NativeToJavaFrameType(jni, image._frameType); + jobject qp = (image.qp_ == -1) ? nullptr : JavaIntegerFromInt(jni, image.qp_); + return Java_EncodedImage_create( + jni, buffer, image._encodedWidth, image._encodedHeight, + image.capture_time_ms_ * rtc::kNumNanosecsPerMillisec, frame_type, + static_cast(image.rotation_), image._completeFrame, qp); +} + +} // namespace jni +} // namespace webrtc diff --git a/sdk/android/src/jni/encodedimage.h b/sdk/android/src/jni/encodedimage.h new file mode 100644 index 0000000000..a84b91e3c7 --- /dev/null +++ b/sdk/android/src/jni/encodedimage.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef SDK_ANDROID_SRC_JNI_ENCODEDIMAGE_H_ +#define SDK_ANDROID_SRC_JNI_ENCODEDIMAGE_H_ + +#include + +#include "api/video/video_rotation.h" +#include "common_types.h" // NOLINT(build/include) + +namespace webrtc { + +class EncodedImage; + +namespace jni { + +jobject NativeToJavaFrameType(JNIEnv* env, FrameType frame_type); +jobject NativeToJavaEncodedImage(JNIEnv* jni, const EncodedImage& image); + +} // namespace jni +} // namespace webrtc + +#endif // SDK_ANDROID_SRC_JNI_ENCODEDIMAGE_H_ diff --git a/sdk/android/src/jni/videocodecstatus.cc b/sdk/android/src/jni/videocodecstatus.cc new file mode 100644 index 0000000000..6641f30ac4 --- /dev/null +++ b/sdk/android/src/jni/videocodecstatus.cc @@ -0,0 +1,24 @@ +/* + * 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. + */ + +#include "sdk/android/src/jni/videocodecstatus.h" + +#include "sdk/android/generated_video_jni/jni/VideoCodecStatus_jni.h" + +namespace webrtc { +namespace jni { + +int32_t JavaToNativeVideoCodecStatus(JNIEnv* env, + jobject j_video_codec_status) { + return Java_VideoCodecStatus_getNumber(env, j_video_codec_status); +} + +} // namespace jni +} // namespace webrtc diff --git a/sdk/android/src/jni/videocodecstatus.h b/sdk/android/src/jni/videocodecstatus.h new file mode 100644 index 0000000000..a2ad39ed73 --- /dev/null +++ b/sdk/android/src/jni/videocodecstatus.h @@ -0,0 +1,23 @@ +/* + * 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. + */ + +#ifndef SDK_ANDROID_SRC_JNI_VIDEOCODECSTATUS_H_ +#define SDK_ANDROID_SRC_JNI_VIDEOCODECSTATUS_H_ + +#include +#include + +namespace webrtc { +namespace jni { +int32_t JavaToNativeVideoCodecStatus(JNIEnv* env, jobject j_video_codec_status); +} // namespace jni +} // namespace webrtc + +#endif // SDK_ANDROID_SRC_JNI_VIDEOCODECSTATUS_H_ diff --git a/sdk/android/src/jni/videodecoderwrapper.cc b/sdk/android/src/jni/videodecoderwrapper.cc index 1bc75b0c3b..3dd398e9df 100644 --- a/sdk/android/src/jni/videodecoderwrapper.cc +++ b/sdk/android/src/jni/videodecoderwrapper.cc @@ -15,9 +15,12 @@ #include "modules/video_coding/utility/vp8_header_parser.h" #include "modules/video_coding/utility/vp9_uncompressed_header_parser.h" #include "rtc_base/logging.h" -#include "rtc_base/safe_conversions.h" -#include "rtc_base/timeutils.h" +#include "sdk/android/generated_video_jni/jni/VideoDecoderWrapper_jni.h" +#include "sdk/android/generated_video_jni/jni/VideoDecoder_jni.h" #include "sdk/android/src/jni/classreferenceholder.h" +#include "sdk/android/src/jni/encodedimage.h" +#include "sdk/android/src/jni/videocodecstatus.h" +#include "sdk/android/src/jni/videoframe.h" namespace webrtc { namespace jni { @@ -31,58 +34,13 @@ inline rtc::Optional cast_optional(const rtc::Optional& value) { } // namespace VideoDecoderWrapper::VideoDecoderWrapper(JNIEnv* jni, jobject decoder) - : decoder_(jni, decoder), - encoded_image_class_(jni, FindClass(jni, "org/webrtc/EncodedImage")), - frame_type_class_(jni, - FindClass(jni, "org/webrtc/EncodedImage$FrameType")), - settings_class_(jni, FindClass(jni, "org/webrtc/VideoDecoder$Settings")), - video_frame_class_(jni, FindClass(jni, "org/webrtc/VideoFrame")), - video_codec_status_class_(jni, - FindClass(jni, "org/webrtc/VideoCodecStatus")), - integer_class_(jni, jni->FindClass("java/lang/Integer")) { - encoded_image_constructor_ = - jni->GetMethodID(*encoded_image_class_, "", - "(Ljava/nio/ByteBuffer;IIJLorg/webrtc/" - "EncodedImage$FrameType;IZLjava/lang/Integer;)V"); - settings_constructor_ = - jni->GetMethodID(*settings_class_, "", "(III)V"); - - empty_frame_field_ = jni->GetStaticFieldID( - *frame_type_class_, "EmptyFrame", "Lorg/webrtc/EncodedImage$FrameType;"); - video_frame_key_field_ = - jni->GetStaticFieldID(*frame_type_class_, "VideoFrameKey", - "Lorg/webrtc/EncodedImage$FrameType;"); - video_frame_delta_field_ = - jni->GetStaticFieldID(*frame_type_class_, "VideoFrameDelta", - "Lorg/webrtc/EncodedImage$FrameType;"); - - video_frame_get_timestamp_ns_method_ = - jni->GetMethodID(*video_frame_class_, "getTimestampNs", "()J"); - - jclass decoder_class = jni->GetObjectClass(decoder); - init_decode_method_ = - jni->GetMethodID(decoder_class, "initDecode", - "(Lorg/webrtc/VideoDecoder$Settings;Lorg/webrtc/" - "VideoDecoder$Callback;)Lorg/webrtc/VideoCodecStatus;"); - release_method_ = jni->GetMethodID(decoder_class, "release", - "()Lorg/webrtc/VideoCodecStatus;"); - decode_method_ = jni->GetMethodID(decoder_class, "decode", - "(Lorg/webrtc/EncodedImage;Lorg/webrtc/" - "VideoDecoder$DecodeInfo;)Lorg/webrtc/" - "VideoCodecStatus;"); - get_prefers_late_decoding_method_ = - jni->GetMethodID(decoder_class, "getPrefersLateDecoding", "()Z"); - get_implementation_name_method_ = jni->GetMethodID( - decoder_class, "getImplementationName", "()Ljava/lang/String;"); - - get_number_method_ = - jni->GetMethodID(*video_codec_status_class_, "getNumber", "()I"); - + : decoder_(jni, decoder) { initialized_ = false; // QP parsing starts enabled and we disable it if the decoder provides frames. qp_parsing_enabled_ = true; - implementation_name_ = GetImplementationName(jni); + implementation_name_ = JavaToStdString( + jni, Java_VideoDecoder_getImplementationName(jni, decoder)); } int32_t VideoDecoderWrapper::InitDecode(const VideoCodec* codec_settings, @@ -96,20 +54,15 @@ int32_t VideoDecoderWrapper::InitDecode(const VideoCodec* codec_settings, } int32_t VideoDecoderWrapper::InitDecodeInternal(JNIEnv* jni) { - jobject settings = - jni->NewObject(*settings_class_, settings_constructor_, number_of_cores_, - codec_settings_.width, codec_settings_.height); + jobject settings = Java_VideoDecoderWrapper_createSettings( + jni, number_of_cores_, codec_settings_.width, codec_settings_.height); - jclass callback_class = - FindClass(jni, "org/webrtc/VideoDecoderWrapperCallback"); - jmethodID callback_constructor = - jni->GetMethodID(callback_class, "", "(J)V"); - jobject callback = jni->NewObject(callback_class, callback_constructor, - jlongFromPointer(this)); + jobject callback = Java_VideoDecoderWrapper_createDecoderCallback( + jni, jlongFromPointer(this)); jobject ret = - jni->CallObjectMethod(*decoder_, init_decode_method_, settings, callback); - if (jni->CallIntMethod(ret, get_number_method_) == WEBRTC_VIDEO_CODEC_OK) { + Java_VideoDecoder_initDecode(jni, *decoder_, settings, callback); + if (JavaToNativeVideoCodecStatus(jni, ret) == WEBRTC_VIDEO_CODEC_OK) { initialized_ = true; } @@ -142,10 +95,8 @@ int32_t VideoDecoderWrapper::Decode( qp_parsing_enabled_ ? ParseQP(input_image) : rtc::nullopt; frame_extra_infos_.push_back(frame_extra_info); - jobject jinput_image = - ConvertEncodedImageToJavaEncodedImage(jni, input_image); - jobject ret = - jni->CallObjectMethod(*decoder_, decode_method_, jinput_image, nullptr); + jobject jinput_image = NativeToJavaEncodedImage(jni, input_image); + jobject ret = Java_VideoDecoder_decode(jni, *decoder_, jinput_image, nullptr); return HandleReturnCode(jni, ret); } @@ -158,7 +109,7 @@ int32_t VideoDecoderWrapper::RegisterDecodeCompleteCallback( int32_t VideoDecoderWrapper::Release() { JNIEnv* jni = AttachCurrentThreadIfNeeded(); ScopedLocalRefFrame local_ref_frame(jni); - jobject ret = jni->CallObjectMethod(*decoder_, release_method_); + jobject ret = Java_VideoDecoder_release(jni, *decoder_); frame_extra_infos_.clear(); initialized_ = false; return HandleReturnCode(jni, ret); @@ -166,19 +117,20 @@ int32_t VideoDecoderWrapper::Release() { bool VideoDecoderWrapper::PrefersLateDecoding() const { JNIEnv* jni = AttachCurrentThreadIfNeeded(); - return jni->CallBooleanMethod(*decoder_, get_prefers_late_decoding_method_); + return Java_VideoDecoder_getPrefersLateDecoding(jni, *decoder_); } const char* VideoDecoderWrapper::ImplementationName() const { return implementation_name_.c_str(); } -void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* jni, - jobject jframe, - jobject jdecode_time_ms, - jobject jqp) { - const jlong capture_time_ns = - jni->CallLongMethod(jframe, video_frame_get_timestamp_ns_method_); +void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* env, + jobject j_caller, + jobject j_frame, + jobject j_decode_time_ms, + jobject j_qp) { + const uint64_t capture_time_ns = GetJavaVideoFrameTimestampNs(env, j_frame); + FrameExtraInfo frame_extra_info; do { if (frame_extra_infos_.empty()) { @@ -193,13 +145,13 @@ void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* jni, } while (frame_extra_info.capture_time_ns != capture_time_ns); VideoFrame frame = - JavaToNativeFrame(jni, jframe, frame_extra_info.timestamp_rtp); + JavaToNativeFrame(env, j_frame, frame_extra_info.timestamp_rtp); rtc::Optional decoding_time_ms = - JavaIntegerToOptionalInt(jni, jdecode_time_ms); + JavaIntegerToOptionalInt(env, j_decode_time_ms); rtc::Optional decoder_qp = - cast_optional(JavaIntegerToOptionalInt(jni, jqp)); + cast_optional(JavaIntegerToOptionalInt(env, j_qp)); // If the decoder provides QP values itself, no need to parse the bitstream. // Enable QP parsing if decoder does not provide QP values itself. qp_parsing_enabled_ = !decoder_qp.has_value(); @@ -207,41 +159,8 @@ void VideoDecoderWrapper::OnDecodedFrame(JNIEnv* jni, decoder_qp ? decoder_qp : frame_extra_info.qp); } -jobject VideoDecoderWrapper::ConvertEncodedImageToJavaEncodedImage( - JNIEnv* jni, - const EncodedImage& image) { - jobject buffer = jni->NewDirectByteBuffer(image._buffer, image._length); - jfieldID frame_type_field; - switch (image._frameType) { - case kEmptyFrame: - frame_type_field = empty_frame_field_; - break; - case kVideoFrameKey: - frame_type_field = video_frame_key_field_; - break; - case kVideoFrameDelta: - frame_type_field = video_frame_delta_field_; - break; - default: - RTC_NOTREACHED(); - return nullptr; - } - jobject frame_type = - jni->GetStaticObjectField(*frame_type_class_, frame_type_field); - jobject qp = nullptr; - if (image.qp_ != -1) { - qp = JavaIntegerFromInt(jni, image.qp_); - } - return jni->NewObject( - *encoded_image_class_, encoded_image_constructor_, buffer, - static_cast(image._encodedWidth), - static_cast(image._encodedHeight), - static_cast(image.capture_time_ms_ * rtc::kNumNanosecsPerMillisec), - frame_type, static_cast(image.rotation_), image._completeFrame, qp); -} - int32_t VideoDecoderWrapper::HandleReturnCode(JNIEnv* jni, jobject code) { - int32_t value = jni->CallIntMethod(code, get_number_method_); + int32_t value = JavaToNativeVideoCodecStatus(jni, code); if (value < 0) { // Any errors are represented by negative values. // Reset the codec. if (Release() == WEBRTC_VIDEO_CODEC_OK) { @@ -292,24 +211,5 @@ rtc::Optional VideoDecoderWrapper::ParseQP( return qp; } -std::string VideoDecoderWrapper::GetImplementationName(JNIEnv* jni) const { - jstring jname = reinterpret_cast( - jni->CallObjectMethod(*decoder_, get_implementation_name_method_)); - return JavaToStdString(jni, jname); -} - -JNI_FUNCTION_DECLARATION(void, - VideoDecoderWrapperCallback_nativeOnDecodedFrame, - JNIEnv* jni, - jclass, - jlong jnative_decoder, - jobject jframe, - jobject jdecode_time_ms, - jobject jqp) { - VideoDecoderWrapper* native_decoder = - reinterpret_cast(jnative_decoder); - native_decoder->OnDecodedFrame(jni, jframe, jdecode_time_ms, jqp); -} - } // namespace jni } // namespace webrtc diff --git a/sdk/android/src/jni/videodecoderwrapper.h b/sdk/android/src/jni/videodecoderwrapper.h index 0e4e96eb50..48517c770b 100644 --- a/sdk/android/src/jni/videodecoderwrapper.h +++ b/sdk/android/src/jni/videodecoderwrapper.h @@ -17,14 +17,11 @@ #include "api/video_codecs/video_decoder.h" #include "common_video/h264/h264_bitstream_parser.h" #include "sdk/android/src/jni/jni_helpers.h" -#include "sdk/android/src/jni/videoframe.h" namespace webrtc { namespace jni { -// Wraps a Java decoder and delegates all calls to it. Passes -// VideoDecoderWrapperCallback to the decoder on InitDecode. Wraps the received -// frames to AndroidVideoBuffer. +// Wraps a Java decoder and delegates all calls to it. class VideoDecoderWrapper : public VideoDecoder { public: VideoDecoderWrapper(JNIEnv* jni, jobject decoder); @@ -51,10 +48,11 @@ class VideoDecoderWrapper : public VideoDecoder { const char* ImplementationName() const override; // Wraps the frame to a AndroidVideoBuffer and passes it to the callback. - void OnDecodedFrame(JNIEnv* jni, - jobject jframe, - jobject jdecode_time_ms, - jobject jqp); + void OnDecodedFrame(JNIEnv* env, + jobject j_caller, + jobject j_frame, + jobject j_decode_time_ms, + jobject j_qp); private: struct FrameExtraInfo { @@ -72,8 +70,6 @@ class VideoDecoderWrapper : public VideoDecoder { rtc::Optional ParseQP(const EncodedImage& input_image); - std::string GetImplementationName(JNIEnv* jni) const; - VideoCodec codec_settings_; int32_t number_of_cores_; @@ -86,32 +82,6 @@ class VideoDecoderWrapper : public VideoDecoder { DecodedImageCallback* callback_; const ScopedGlobalRef decoder_; - const ScopedGlobalRef encoded_image_class_; - const ScopedGlobalRef frame_type_class_; - const ScopedGlobalRef settings_class_; - const ScopedGlobalRef video_frame_class_; - const ScopedGlobalRef video_codec_status_class_; - const ScopedGlobalRef integer_class_; - - jmethodID encoded_image_constructor_; - jmethodID settings_constructor_; - - jfieldID empty_frame_field_; - jfieldID video_frame_key_field_; - jfieldID video_frame_delta_field_; - - jmethodID video_frame_get_timestamp_ns_method_; - - jmethodID init_decode_method_; - jmethodID release_method_; - jmethodID decode_method_; - jmethodID get_prefers_late_decoding_method_; - jmethodID get_implementation_name_method_; - - jmethodID get_number_method_; - - jobject ConvertEncodedImageToJavaEncodedImage(JNIEnv* jni, - const EncodedImage& image); }; } // namespace jni diff --git a/sdk/android/src/jni/videoencoderwrapper.cc b/sdk/android/src/jni/videoencoderwrapper.cc index 360a5c68d9..66b54f9e8a 100644 --- a/sdk/android/src/jni/videoencoderwrapper.cc +++ b/sdk/android/src/jni/videoencoderwrapper.cc @@ -21,10 +21,11 @@ #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/class_loader.h" +#include "sdk/android/src/jni/encodedimage.h" +#include "sdk/android/src/jni/videocodecstatus.h" namespace webrtc { namespace jni { @@ -84,7 +85,7 @@ int32_t VideoEncoderWrapper::InitEncodeInternal(JNIEnv* jni) { jobject ret = Java_VideoEncoder_initEncode(jni, *encoder_, settings, callback); - if (Java_VideoCodecStatus_getNumber(jni, ret) == WEBRTC_VIDEO_CODEC_OK) { + if (JavaToNativeVideoCodecStatus(jni, ret) == WEBRTC_VIDEO_CODEC_OK) { initialized_ = true; } @@ -123,8 +124,7 @@ int32_t VideoEncoderWrapper::Encode( 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 = Java_VideoEncoderWrapper_createFrameType( - jni, static_cast((*frame_types)[i])); + jobject j_frame_type = NativeToJavaFrameType(jni, (*frame_types)[i]); jni->SetObjectArrayElement(j_frame_types, i, j_frame_type); } jobject encode_info = @@ -245,7 +245,7 @@ void VideoEncoderWrapper::OnEncodedFrame(JNIEnv* jni, } int32_t VideoEncoderWrapper::HandleReturnCode(JNIEnv* jni, jobject code) { - int32_t value = Java_VideoCodecStatus_getNumber(jni, code); + int32_t value = JavaToNativeVideoCodecStatus(jni, code); if (value < 0) { // Any errors are represented by negative values. // Try resetting the codec. if (++num_resets_ <= kMaxJavaEncoderResets && diff --git a/sdk/android/src/jni/videoframe.cc b/sdk/android/src/jni/videoframe.cc index c914727af5..be07c75744 100644 --- a/sdk/android/src/jni/videoframe.cc +++ b/sdk/android/src/jni/videoframe.cc @@ -109,6 +109,10 @@ AndroidVideoI420Buffer::~AndroidVideoI420Buffer() { } // namespace +int64_t GetJavaVideoFrameTimestampNs(JNIEnv* jni, jobject j_video_frame) { + return Java_VideoFrame_getTimestampNs(jni, j_video_frame); +} + Matrix::Matrix(JNIEnv* jni, jfloatArray a) { RTC_CHECK_EQ(16, jni->GetArrayLength(a)); jfloat* ptr = jni->GetFloatArrayElements(a, nullptr); @@ -366,7 +370,7 @@ VideoFrame JavaToNativeFrame(JNIEnv* jni, uint32_t timestamp_rtp) { jobject j_video_frame_buffer = Java_VideoFrame_getBuffer(jni, j_video_frame); int rotation = Java_VideoFrame_getRotation(jni, j_video_frame); - uint32_t timestamp_ns = Java_VideoFrame_getTimestampNs(jni, j_video_frame); + int64_t timestamp_ns = Java_VideoFrame_getTimestampNs(jni, j_video_frame); rtc::scoped_refptr buffer = AndroidVideoBuffer::Create(jni, j_video_frame_buffer); return VideoFrame(buffer, timestamp_rtp, diff --git a/sdk/android/src/jni/videoframe.h b/sdk/android/src/jni/videoframe.h index 1f10eb4009..26206b8631 100644 --- a/sdk/android/src/jni/videoframe.h +++ b/sdk/android/src/jni/videoframe.h @@ -159,6 +159,8 @@ VideoFrame JavaToNativeFrame(JNIEnv* jni, jobject NativeToJavaFrame(JNIEnv* jni, const VideoFrame& frame); +int64_t GetJavaVideoFrameTimestampNs(JNIEnv* jni, jobject j_video_frame); + } // namespace jni } // namespace webrtc