diff --git a/webrtc/api/api.gyp b/webrtc/api/api.gyp index 34a75f60f5..061d9c1554 100644 --- a/webrtc/api/api.gyp +++ b/webrtc/api/api.gyp @@ -43,8 +43,6 @@ 'java/jni/androidnetworkmonitor_jni.h', 'java/jni/androidvideocapturer_jni.cc', 'java/jni/androidvideocapturer_jni.h', - 'java/jni/eglbase_jni.cc', - 'java/jni/eglbase_jni.h', 'java/jni/surfacetexturehelper_jni.cc', 'java/jni/surfacetexturehelper_jni.h', 'java/jni/classreferenceholder.cc', diff --git a/webrtc/api/java/jni/androidmediadecoder_jni.cc b/webrtc/api/java/jni/androidmediadecoder_jni.cc index 93f253d18f..f7966cc44a 100644 --- a/webrtc/api/java/jni/androidmediadecoder_jni.cc +++ b/webrtc/api/java/jni/androidmediadecoder_jni.cc @@ -843,7 +843,8 @@ void MediaCodecVideoDecoder::OnMessage(rtc::Message* msg) { codec_thread_->PostDelayed(kMediaCodecPollMs, this); } -MediaCodecVideoDecoderFactory::MediaCodecVideoDecoderFactory() { +MediaCodecVideoDecoderFactory::MediaCodecVideoDecoderFactory() + : egl_context_(nullptr) { ALOGD << "MediaCodecVideoDecoderFactory ctor"; JNIEnv* jni = AttachCurrentThreadIfNeeded(); ScopedLocalRefFrame local_ref_frame(jni); @@ -886,13 +887,19 @@ MediaCodecVideoDecoderFactory::MediaCodecVideoDecoderFactory() { MediaCodecVideoDecoderFactory::~MediaCodecVideoDecoderFactory() { ALOGD << "MediaCodecVideoDecoderFactory dtor"; + if (egl_context_) { + JNIEnv* jni = AttachCurrentThreadIfNeeded(); + jni->DeleteGlobalRef(egl_context_); + } } void MediaCodecVideoDecoderFactory::SetEGLContext( - JNIEnv* jni, jobject render_egl_context) { + JNIEnv* jni, jobject egl_context) { ALOGD << "MediaCodecVideoDecoderFactory::SetEGLContext"; - if (!egl_.CreateEglBase(jni, render_egl_context)) { - ALOGW << "Invalid EGL context - HW surface decoding is disabled."; + RTC_DCHECK(!egl_context_); + egl_context_ = jni->NewGlobalRef(egl_context); + if (CheckException(jni)) { + ALOGE << "error calling NewGlobalRef for EGL Context."; } } @@ -906,7 +913,7 @@ webrtc::VideoDecoder* MediaCodecVideoDecoderFactory::CreateVideoDecoder( if (codec_type == type) { ALOGD << "Create HW video decoder for type " << (int)type; return new MediaCodecVideoDecoder(AttachCurrentThreadIfNeeded(), type, - egl_.egl_base_context()); + egl_context_); } } ALOGW << "Can not find HW video decoder for type " << (int)type; diff --git a/webrtc/api/java/jni/androidmediadecoder_jni.h b/webrtc/api/java/jni/androidmediadecoder_jni.h index 8ee23bec0a..07199260b6 100644 --- a/webrtc/api/java/jni/androidmediadecoder_jni.h +++ b/webrtc/api/java/jni/androidmediadecoder_jni.h @@ -11,7 +11,7 @@ #ifndef WEBRTC_API_JAVA_JNI_ANDROIDMEDIADECODER_JNI_H_ #define WEBRTC_API_JAVA_JNI_ANDROIDMEDIADECODER_JNI_H_ -#include "webrtc/api/java/jni/eglbase_jni.h" +#include "webrtc/api/java/jni/jni_helpers.h" #include "webrtc/media/engine/webrtcvideodecoderfactory.h" namespace webrtc_jni { @@ -32,7 +32,7 @@ class MediaCodecVideoDecoderFactory void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) override; private: - EglBase egl_; + jobject egl_context_; std::vector supported_codec_types_; }; diff --git a/webrtc/api/java/jni/androidmediaencoder_jni.cc b/webrtc/api/java/jni/androidmediaencoder_jni.cc index 7acb73bbd2..ddfa85affa 100644 --- a/webrtc/api/java/jni/androidmediaencoder_jni.cc +++ b/webrtc/api/java/jni/androidmediaencoder_jni.cc @@ -1164,7 +1164,8 @@ const char* MediaCodecVideoEncoder::ImplementationName() const { return "MediaCodec"; } -MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() { +MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() + : egl_context_(nullptr) { JNIEnv* jni = AttachCurrentThreadIfNeeded(); ScopedLocalRefFrame local_ref_frame(jni); jclass j_encoder_class = FindClass(jni, "org/webrtc/MediaCodecVideoEncoder"); @@ -1203,13 +1204,19 @@ MediaCodecVideoEncoderFactory::MediaCodecVideoEncoderFactory() { MediaCodecVideoEncoderFactory::~MediaCodecVideoEncoderFactory() { ALOGD << "MediaCodecVideoEncoderFactory dtor"; + if (egl_context_) { + JNIEnv* jni = AttachCurrentThreadIfNeeded(); + jni->DeleteGlobalRef(egl_context_); + } } void MediaCodecVideoEncoderFactory::SetEGLContext( - JNIEnv* jni, jobject render_egl_context) { + JNIEnv* jni, jobject egl_context) { ALOGD << "MediaCodecVideoEncoderFactory::SetEGLContext"; - if (!egl_base_.CreateEglBase(jni, render_egl_context)) { - ALOGW << "Invalid EGL context - HW surface encoding is disabled."; + RTC_DCHECK(!egl_context_); + egl_context_ = jni->NewGlobalRef(egl_context); + if (CheckException(jni)) { + ALOGE << "error calling NewGlobalRef for EGL Context."; } } @@ -1225,7 +1232,7 @@ webrtc::VideoEncoder* MediaCodecVideoEncoderFactory::CreateVideoEncoder( ALOGD << "Create HW video encoder for type " << (int)type << " (" << it->name << ")."; return new MediaCodecVideoEncoder(AttachCurrentThreadIfNeeded(), type, - egl_base_.egl_base_context()); + egl_context_); } } ALOGW << "Can not find HW video encoder for type " << (int)type; diff --git a/webrtc/api/java/jni/androidmediaencoder_jni.h b/webrtc/api/java/jni/androidmediaencoder_jni.h index c0b5f028bd..4e50700710 100644 --- a/webrtc/api/java/jni/androidmediaencoder_jni.h +++ b/webrtc/api/java/jni/androidmediaencoder_jni.h @@ -13,7 +13,7 @@ #include -#include "webrtc/api/java/jni/eglbase_jni.h" +#include "webrtc/api/java/jni/jni_helpers.h" #include "webrtc/media/engine/webrtcvideoencoderfactory.h" namespace webrtc_jni { @@ -25,7 +25,7 @@ class MediaCodecVideoEncoderFactory MediaCodecVideoEncoderFactory(); virtual ~MediaCodecVideoEncoderFactory(); - void SetEGLContext(JNIEnv* jni, jobject render_egl_context); + void SetEGLContext(JNIEnv* jni, jobject egl_context); // WebRtcVideoEncoderFactory implementation. webrtc::VideoEncoder* CreateVideoEncoder(webrtc::VideoCodecType type) @@ -34,7 +34,7 @@ class MediaCodecVideoEncoderFactory void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override; private: - EglBase egl_base_; + jobject egl_context_; // Empty if platform support is lacking, const after ctor returns. std::vector supported_codecs_; diff --git a/webrtc/api/java/jni/eglbase_jni.cc b/webrtc/api/java/jni/eglbase_jni.cc deleted file mode 100644 index e146024dbe..0000000000 --- a/webrtc/api/java/jni/eglbase_jni.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2016 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/api/java/jni/eglbase_jni.h" - -#include "webrtc/api/java/jni/androidmediacodeccommon.h" -#include "webrtc/api/java/jni/classreferenceholder.h" -#include "webrtc/api/java/jni/jni_helpers.h" - -namespace webrtc_jni { - -EglBase::EglBase() { -} - -EglBase::~EglBase() { - if (egl_base_) { - JNIEnv* jni = AttachCurrentThreadIfNeeded(); - jni->DeleteGlobalRef(egl_base_context_); - egl_base_context_ = nullptr; - jni->CallVoidMethod(egl_base_, - GetMethodID(jni, - FindClass(jni, "org/webrtc/EglBase"), - "release", "()V")); - jni->DeleteGlobalRef(egl_base_); - } -} - -bool EglBase::CreateEglBase(JNIEnv* jni, jobject egl_context) { - if (egl_base_) { - jni->DeleteGlobalRef(egl_base_context_); - egl_base_context_ = nullptr; - jni->CallVoidMethod(egl_base_, - GetMethodID(jni, - FindClass(jni, "org/webrtc/EglBase"), - "release", "()V")); - jni->DeleteGlobalRef(egl_base_); - egl_base_ = nullptr; - } - - if (IsNull(jni, egl_context)) - return false; - - jobject egl_base = jni->CallStaticObjectMethod( - FindClass(jni, "org/webrtc/EglBase"), - GetStaticMethodID(jni, - FindClass(jni, "org/webrtc/EglBase"), - "create", - "(Lorg/webrtc/EglBase$Context;)Lorg/webrtc/EglBase;"), - egl_context); - if (CheckException(jni)) - return false; - - egl_base_ = jni->NewGlobalRef(egl_base); - egl_base_context_ = jni->NewGlobalRef( - jni->CallObjectMethod( - egl_base_, - GetMethodID(jni, - FindClass(jni, "org/webrtc/EglBase"), - "getEglBaseContext", - "()Lorg/webrtc/EglBase$Context;"))); - RTC_CHECK(egl_base_context_); - return true; -} - -} // namespace webrtc_jni diff --git a/webrtc/api/java/jni/eglbase_jni.h b/webrtc/api/java/jni/eglbase_jni.h deleted file mode 100644 index 983cc191d0..0000000000 --- a/webrtc/api/java/jni/eglbase_jni.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2016 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_API_JAVA_JNI_EGLBASE_JNI_H_ -#define WEBRTC_API_JAVA_JNI_EGLBASE_JNI_H_ - -#include - -#include "webrtc/base/constructormagic.h" - -namespace webrtc_jni { - -// Helper class used for creating a Java instance of org/webrtc/EglBase. -class EglBase { - public: - EglBase(); - ~EglBase(); - - // Creates an new java EglBase instance. |egl_base_context| must be a valid - // EglBase$Context. - // Returns false if |egl_base_context| is a null Java object or if an - // exception occur in Java. - bool CreateEglBase(JNIEnv* jni, jobject egl_base_context); - jobject egl_base_context() const { return egl_base_context_; } - - private: - jobject egl_base_ = nullptr; // instance of org/webrtc/EglBase - jobject egl_base_context_ = nullptr; // instance of EglBase$Context - - RTC_DISALLOW_COPY_AND_ASSIGN(EglBase); -}; - -} // namespace webrtc_jni - -#endif // WEBRTC_API_JAVA_JNI_EGLBASE_JNI_H_ diff --git a/webrtc/api/java/src/org/webrtc/PeerConnectionFactory.java b/webrtc/api/java/src/org/webrtc/PeerConnectionFactory.java index 96a161b83d..51e593e655 100644 --- a/webrtc/api/java/src/org/webrtc/PeerConnectionFactory.java +++ b/webrtc/api/java/src/org/webrtc/PeerConnectionFactory.java @@ -26,6 +26,8 @@ public class PeerConnectionFactory { private final long nativeFactory; private static Thread workerThread; private static Thread signalingThread; + private EglBase localEglbase; + private EglBase remoteEglbase; public static class Options { // Keep in sync with webrtc/base/network.h! @@ -163,20 +165,29 @@ public class PeerConnectionFactory { /** Set the EGL context used by HW Video encoding and decoding. * - * @param localEGLContext An instance of EglBase.Context. - * Must be the same as used by VideoCapturerAndroid and any local - * video renderer. - * @param remoteEGLContext An instance of EglBase.Context. - * Must be the same as used by any remote video renderer. + * @param localEglContext Must be the same as used by VideoCapturerAndroid and any local video + * renderer. + * @param remoteEglContext Must be the same as used by any remote video renderer. */ - public void setVideoHwAccelerationOptions(Object localEGLContext, Object remoteEGLContext) { - nativeSetVideoHwAccelerationOptions(nativeFactory, localEGLContext, remoteEGLContext); + public void setVideoHwAccelerationOptions(EglBase.Context localEglContext, + EglBase.Context remoteEglContext) { + if (localEglbase != null || remoteEglbase != null) { + throw new IllegalStateException("Egl context already set."); + } + localEglbase = EglBase.create(localEglContext); + remoteEglbase = EglBase.create(remoteEglContext); + nativeSetVideoHwAccelerationOptions(nativeFactory, localEglbase.getEglBaseContext(), + remoteEglbase.getEglBaseContext()); } public void dispose() { nativeFreeFactory(nativeFactory); signalingThread = null; workerThread = null; + if (localEglbase != null) + localEglbase.release(); + if (remoteEglbase != null) + remoteEglbase.release(); } public void threadsCallbacks() { diff --git a/webrtc/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java b/webrtc/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java index f7a16eec98..e5fd9526af 100644 --- a/webrtc/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java +++ b/webrtc/examples/androidtests/src/org/appspot/apprtc/test/PeerConnectionClientTest.java @@ -400,19 +400,6 @@ public class PeerConnectionClientTest extends InstrumentationTestCase doLoopbackTest(createParametersForVideoCall(VIDEO_CODEC_VP8, true), true); } - - // Test that a call can be setup even if a released EGL context is used during setup. - // The HW encoder and decoder will fallback to encode and decode from byte buffers. - public void testLoopbackEglContextReleasedBeforeSetup() throws InterruptedException { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { - Log.i(TAG, "Decode to textures is not supported, requires SDK version 19."); - return; - } - eglBase.release(); - doLoopbackTest(createParametersForVideoCall(VIDEO_CODEC_VP8, false), true); - eglBase = null; - } - // Test that a call can be setup even if the EGL context used during initialization is // released before the Video codecs are created. The HW encoder and decoder is setup to use // textures. @@ -423,7 +410,7 @@ public class PeerConnectionClientTest extends InstrumentationTestCase } loopback = true; - PeerConnectionParameters parameters = createParametersForVideoCall(VIDEO_CODEC_VP8, false); + PeerConnectionParameters parameters = createParametersForVideoCall(VIDEO_CODEC_VP8, true); MockRenderer localRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, LOCAL_RENDERER_NAME); MockRenderer remoteRenderer = new MockRenderer(EXPECTED_VIDEO_FRAMES, REMOTE_RENDERER_NAME); pcClient = createPeerConnectionClient(