Propagate webrtc::Environment to create VideoDecoder through java wrappers

Bug: webrtc:15791
Change-Id: I25976158ef780211355deb934e83d275d4f881e2
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/336980
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41686}
This commit is contained in:
Danil Chapovalov 2024-02-06 21:31:44 +01:00 committed by WebRTC LUCI CQ
parent 2425c8ddea
commit 22b6564d77
11 changed files with 109 additions and 13 deletions

View file

@ -663,6 +663,7 @@ if (current_os == "linux" || is_android) {
"../../api:libjingle_peerconnection_api", "../../api:libjingle_peerconnection_api",
"../../api:media_stream_interface", "../../api:media_stream_interface",
"../../api:sequence_checker", "../../api:sequence_checker",
"../../api/environment",
"../../api/task_queue", "../../api/task_queue",
"../../api/video:encoded_image", "../../api/video:encoded_image",
"../../api/video:render_resolution", "../../api/video:render_resolution",
@ -689,7 +690,10 @@ if (current_os == "linux" || is_android) {
"../../rtc_base/synchronization:mutex", "../../rtc_base/synchronization:mutex",
"//third_party/libyuv", "//third_party/libyuv",
] ]
absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ] absl_deps = [
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/types:optional",
]
} }
# Sources here require -lEGL linker flag. It is separated from video_jni # Sources here require -lEGL linker flag. It is separated from video_jni
@ -908,6 +912,7 @@ if (current_os == "linux" || is_android) {
":libvpx_vp9_jni", ":libvpx_vp9_jni",
":native_api_jni", ":native_api_jni",
":video_jni", ":video_jni",
"../../api/environment",
"../../api/video_codecs:builtin_video_decoder_factory", "../../api/video_codecs:builtin_video_decoder_factory",
"../../api/video_codecs:builtin_video_encoder_factory", "../../api/video_codecs:builtin_video_encoder_factory",
"../../api/video_codecs:video_codecs_api", "../../api/video_codecs:video_codecs_api",

View file

@ -11,7 +11,6 @@
package org.webrtc; package org.webrtc;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.util.Arrays;
import java.util.List; import java.util.List;
public class SoftwareVideoDecoderFactory implements VideoDecoderFactory { public class SoftwareVideoDecoderFactory implements VideoDecoderFactory {
@ -26,16 +25,19 @@ public class SoftwareVideoDecoderFactory implements VideoDecoderFactory {
@Nullable @Nullable
@Override @Override
public VideoDecoder createDecoder(VideoCodecInfo info) { public VideoDecoder createDecoder(VideoCodecInfo info) {
long nativeDecoder = nativeCreateDecoder(nativeFactory, info); if (!nativeIsSupported(nativeFactory, info)) {
if (nativeDecoder == 0) {
Logging.w(TAG, "Trying to create decoder for unsupported format. " + info); Logging.w(TAG, "Trying to create decoder for unsupported format. " + info);
return null; return null;
} }
return new WrappedNativeVideoDecoder() { return new WrappedNativeVideoDecoder() {
@Override @Override
public long createNativeVideoDecoder() { public long createNativeVideoDecoder() {
return nativeDecoder; return nativeCreateDecoder(nativeFactory, info);
}
@Override
public long createNative(long webrtcEnvRef) {
return nativeCreate(nativeFactory, webrtcEnvRef, info);
} }
}; };
} }
@ -49,5 +51,10 @@ public class SoftwareVideoDecoderFactory implements VideoDecoderFactory {
private static native long nativeCreateDecoder(long factory, VideoCodecInfo videoCodecInfo); private static native long nativeCreateDecoder(long factory, VideoCodecInfo videoCodecInfo);
private static native boolean nativeIsSupported(long factory, VideoCodecInfo info);
private static native long nativeCreate(
long factory, long webrtcEnvRef, VideoCodecInfo info);
private static native List<VideoCodecInfo> nativeGetSupportedCodecs(long factory); private static native List<VideoCodecInfo> nativeGetSupportedCodecs(long factory);
} }

View file

@ -56,11 +56,11 @@ public interface VideoDecoder {
* decoder (e.g., an Android platform decoder), or alternatively 2) a native * decoder (e.g., an Android platform decoder), or alternatively 2) a native
* decoder (e.g., a software decoder or a C++ decoder adapter). * decoder (e.g., a software decoder or a C++ decoder adapter).
* *
* For case 1), createNativeVideoDecoder() should return zero. * For case 1), createNative() should return zero.
* In this case, we expect the native library to call the decoder through * In this case, we expect the native library to call the decoder through
* JNI using the Java interface declared below. * JNI using the Java interface declared below.
* *
* For case 2), createNativeVideoDecoder() should return a non-zero value. * For case 2), createNative() should return a non-zero value.
* In this case, we expect the native library to treat the returned value as * In this case, we expect the native library to treat the returned value as
* a raw pointer of type webrtc::VideoDecoder* (ownership is transferred to * a raw pointer of type webrtc::VideoDecoder* (ownership is transferred to
* the caller). The native library should then directly call the * the caller). The native library should then directly call the
@ -69,6 +69,12 @@ public interface VideoDecoder {
* UnsupportedOperationException. * UnsupportedOperationException.
*/ */
@CalledByNative @CalledByNative
default long createNative(long webrtcEnvRef) {
return createNativeVideoDecoder();
}
@CalledByNative
@Deprecated
default long createNativeVideoDecoder() { default long createNativeVideoDecoder() {
return 0; return 0;
} }

View file

@ -27,5 +27,13 @@ public class VideoDecoderFallback extends WrappedNativeVideoDecoder {
return nativeCreateDecoder(fallback, primary); return nativeCreateDecoder(fallback, primary);
} }
@Override
public long createNative(long webrtcEnvRef) {
return nativeCreate(webrtcEnvRef, fallback, primary);
}
private static native long nativeCreateDecoder(VideoDecoder fallback, VideoDecoder primary); private static native long nativeCreateDecoder(VideoDecoder fallback, VideoDecoder primary);
private static native long nativeCreate(
long webrtcEnvRef, VideoDecoder fallback, VideoDecoder primary);
} }

View file

@ -14,7 +14,9 @@ package org.webrtc;
* Wraps a native webrtc::VideoDecoder. * Wraps a native webrtc::VideoDecoder.
*/ */
public abstract class WrappedNativeVideoDecoder implements VideoDecoder { public abstract class WrappedNativeVideoDecoder implements VideoDecoder {
@Override public abstract long createNativeVideoDecoder(); // TODO: bugs.webrtc.org/15791 - uncomment when implemented by all
// derived classes instead of the createNativeVideoDecoder
// @Override public abstract long createNative(long webrtcEnvRef);
@Override @Override
public final VideoCodecStatus initDecode(Settings settings, Callback decodeCallback) { public final VideoCodecStatus initDecode(Settings settings, Callback decodeCallback) {

View file

@ -8,8 +8,12 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include <memory>
#include "api/environment/environment.h"
#include "api/video_codecs/builtin_video_decoder_factory.h" #include "api/video_codecs/builtin_video_decoder_factory.h"
#include "api/video_codecs/video_decoder.h" #include "api/video_codecs/video_decoder.h"
#include "api/video_codecs/video_decoder_factory.h"
#include "sdk/android/generated_swcodecs_jni/SoftwareVideoDecoderFactory_jni.h" #include "sdk/android/generated_swcodecs_jni/SoftwareVideoDecoderFactory_jni.h"
#include "sdk/android/native_api/jni/java_types.h" #include "sdk/android/native_api/jni/java_types.h"
#include "sdk/android/src/jni/jni_helpers.h" #include "sdk/android/src/jni/jni_helpers.h"
@ -39,6 +43,27 @@ static jlong JNI_SoftwareVideoDecoderFactory_CreateDecoder(
return webrtc::NativeToJavaPointer(decoder.release()); return webrtc::NativeToJavaPointer(decoder.release());
} }
jboolean JNI_SoftwareVideoDecoderFactory_IsSupported(
JNIEnv* env,
jlong j_factory,
const JavaParamRef<jobject>& j_info) {
return VideoCodecInfoToSdpVideoFormat(env, j_info)
.IsCodecInList(reinterpret_cast<VideoDecoderFactory*>(j_factory)
->GetSupportedFormats());
}
jlong JNI_SoftwareVideoDecoderFactory_Create(
JNIEnv* env,
jlong j_factory,
jlong j_webrtc_env_ref,
const JavaParamRef<jobject>& j_info) {
return NativeToJavaPointer(
reinterpret_cast<VideoDecoderFactory*>(j_factory)
->Create(*reinterpret_cast<const Environment*>(j_webrtc_env_ref),
VideoCodecInfoToSdpVideoFormat(env, j_info))
.release());
}
static webrtc::ScopedJavaLocalRef<jobject> static webrtc::ScopedJavaLocalRef<jobject>
JNI_SoftwareVideoDecoderFactory_GetSupportedCodecs(JNIEnv* env, JNI_SoftwareVideoDecoderFactory_GetSupportedCodecs(JNIEnv* env,
jlong j_factory) { jlong j_factory) {

View file

@ -10,6 +10,7 @@
#include "sdk/android/src/jni/video_decoder_factory_wrapper.h" #include "sdk/android/src/jni/video_decoder_factory_wrapper.h"
#include "api/environment/environment.h"
#include "api/video_codecs/sdp_video_format.h" #include "api/video_codecs/sdp_video_format.h"
#include "api/video_codecs/video_decoder.h" #include "api/video_codecs/video_decoder.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
@ -27,7 +28,8 @@ VideoDecoderFactoryWrapper::VideoDecoderFactoryWrapper(
: decoder_factory_(jni, decoder_factory) {} : decoder_factory_(jni, decoder_factory) {}
VideoDecoderFactoryWrapper::~VideoDecoderFactoryWrapper() = default; VideoDecoderFactoryWrapper::~VideoDecoderFactoryWrapper() = default;
std::unique_ptr<VideoDecoder> VideoDecoderFactoryWrapper::CreateVideoDecoder( std::unique_ptr<VideoDecoder> VideoDecoderFactoryWrapper::Create(
const Environment& env,
const SdpVideoFormat& format) { const SdpVideoFormat& format) {
JNIEnv* jni = AttachCurrentThreadIfNeeded(); JNIEnv* jni = AttachCurrentThreadIfNeeded();
ScopedJavaLocalRef<jobject> j_codec_info = ScopedJavaLocalRef<jobject> j_codec_info =
@ -36,7 +38,7 @@ std::unique_ptr<VideoDecoder> VideoDecoderFactoryWrapper::CreateVideoDecoder(
jni, decoder_factory_, j_codec_info); jni, decoder_factory_, j_codec_info);
if (!decoder.obj()) if (!decoder.obj())
return nullptr; return nullptr;
return JavaToNativeVideoDecoder(jni, decoder); return JavaToNativeVideoDecoder(jni, decoder, NativeToJavaPointer(&env));
} }
std::vector<SdpVideoFormat> VideoDecoderFactoryWrapper::GetSupportedFormats() std::vector<SdpVideoFormat> VideoDecoderFactoryWrapper::GetSupportedFormats()

View file

@ -13,6 +13,7 @@
#include <jni.h> #include <jni.h>
#include "api/environment/environment.h"
#include "api/video_codecs/video_decoder_factory.h" #include "api/video_codecs/video_decoder_factory.h"
#include "sdk/android/src/jni/jni_helpers.h" #include "sdk/android/src/jni/jni_helpers.h"
@ -28,8 +29,8 @@ class VideoDecoderFactoryWrapper : public VideoDecoderFactory {
~VideoDecoderFactoryWrapper() override; ~VideoDecoderFactoryWrapper() override;
std::vector<SdpVideoFormat> GetSupportedFormats() const override; std::vector<SdpVideoFormat> GetSupportedFormats() const override;
std::unique_ptr<VideoDecoder> CreateVideoDecoder( std::unique_ptr<VideoDecoder> Create(const Environment& env,
const SdpVideoFormat& format) override; const SdpVideoFormat& format) override;
private: private:
const ScopedJavaGlobalRef<jobject> decoder_factory_; const ScopedJavaGlobalRef<jobject> decoder_factory_;

View file

@ -35,5 +35,23 @@ static jlong JNI_VideoDecoderFallback_CreateDecoder(
return jlongFromPointer(nativeWrapper); return jlongFromPointer(nativeWrapper);
} }
static jlong JNI_VideoDecoderFallback_Create(
JNIEnv* jni,
jlong j_webrtc_env_ref,
const JavaParamRef<jobject>& j_fallback_decoder,
const JavaParamRef<jobject>& j_primary_decoder) {
std::unique_ptr<VideoDecoder> fallback_decoder =
JavaToNativeVideoDecoder(jni, j_fallback_decoder, j_webrtc_env_ref);
std::unique_ptr<VideoDecoder> primary_decoder =
JavaToNativeVideoDecoder(jni, j_primary_decoder, j_webrtc_env_ref);
VideoDecoder* native_wrapper =
CreateVideoDecoderSoftwareFallbackWrapper(std::move(fallback_decoder),
std::move(primary_decoder))
.release();
return NativeToJavaPointer(native_wrapper);
}
} // namespace jni } // namespace jni
} // namespace webrtc } // namespace webrtc

View file

@ -10,6 +10,8 @@
#include "sdk/android/src/jni/video_decoder_wrapper.h" #include "sdk/android/src/jni/video_decoder_wrapper.h"
#include "absl/memory/memory.h"
#include "api/environment/environment.h"
#include "api/video/render_resolution.h" #include "api/video/render_resolution.h"
#include "api/video/video_frame.h" #include "api/video/video_frame.h"
#include "api/video_codecs/video_decoder.h" #include "api/video_codecs/video_decoder.h"
@ -281,5 +283,18 @@ std::unique_ptr<VideoDecoder> JavaToNativeVideoDecoder(
return std::unique_ptr<VideoDecoder>(decoder); return std::unique_ptr<VideoDecoder>(decoder);
} }
std::unique_ptr<VideoDecoder> JavaToNativeVideoDecoder(
JNIEnv* jni,
const JavaRef<jobject>& j_decoder,
jlong webrtcEnvRef) {
if (jlong native_decoder =
Java_VideoDecoder_createNative(jni, j_decoder, webrtcEnvRef);
native_decoder != 0) {
return absl::WrapUnique(reinterpret_cast<VideoDecoder*>(native_decoder));
} else {
return std::make_unique<VideoDecoderWrapper>(jni, j_decoder);
}
}
} // namespace jni } // namespace jni
} // namespace webrtc } // namespace webrtc

View file

@ -116,10 +116,17 @@ class VideoDecoderWrapper : public VideoDecoder {
/* If the j_decoder is a wrapped native decoder, unwrap it. If it is not, /* If the j_decoder is a wrapped native decoder, unwrap it. If it is not,
* wrap it in a VideoDecoderWrapper. * wrap it in a VideoDecoderWrapper.
*/ */
// TODO: bugs.webrtc.org/15791 - delete variant without the webrtcEnvRef
// parameter when unused.
std::unique_ptr<VideoDecoder> JavaToNativeVideoDecoder( std::unique_ptr<VideoDecoder> JavaToNativeVideoDecoder(
JNIEnv* jni, JNIEnv* jni,
const JavaRef<jobject>& j_decoder); const JavaRef<jobject>& j_decoder);
std::unique_ptr<VideoDecoder> JavaToNativeVideoDecoder(
JNIEnv* jni,
const JavaRef<jobject>& j_decoder,
jlong webrtcEnvRef);
} // namespace jni } // namespace jni
} // namespace webrtc } // namespace webrtc