diff --git a/talk/app/webrtc/androidtests/src/org/webrtc/GlRectDrawerTest.java b/talk/app/webrtc/androidtests/src/org/webrtc/GlRectDrawerTest.java index 1c01ffa0b8..36424aa144 100644 --- a/talk/app/webrtc/androidtests/src/org/webrtc/GlRectDrawerTest.java +++ b/talk/app/webrtc/androidtests/src/org/webrtc/GlRectDrawerTest.java @@ -28,7 +28,6 @@ package org.webrtc; import android.graphics.SurfaceTexture; import android.opengl.GLES20; -import android.opengl.Matrix; import android.test.ActivityTestCase; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; @@ -36,9 +35,6 @@ import android.test.suitebuilder.annotation.SmallTest; import java.nio.ByteBuffer; import java.util.Random; -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLContext; - public final class GlRectDrawerTest extends ActivityTestCase { // Resolution of the test image. private static final int WIDTH = 16; @@ -46,7 +42,7 @@ public final class GlRectDrawerTest extends ActivityTestCase { // Seed for random pixel creation. private static final int SEED = 42; // When comparing pixels, allow some slack for float arithmetic and integer rounding. - private static final float MAX_DIFF = 1.0f; + private static final float MAX_DIFF = 1.5f; private static float normalizedByte(byte b) { return (b & 0xFF) / 255.0f; @@ -100,7 +96,7 @@ public final class GlRectDrawerTest extends ActivityTestCase { @SmallTest public void testRgbRendering() { // Create EGL base with a pixel buffer as display output. - final EglBase eglBase = new EglBase(EGL10.EGL_NO_CONTEXT, EglBase.ConfigType.PIXEL_BUFFER); + final EglBase eglBase = EglBase.create(null, EglBase.ConfigType.PIXEL_BUFFER); eglBase.createPbufferSurface(WIDTH, HEIGHT); eglBase.makeCurrent(); @@ -137,7 +133,7 @@ public final class GlRectDrawerTest extends ActivityTestCase { @SmallTest public void testYuvRendering() { // Create EGL base with a pixel buffer as display output. - EglBase eglBase = new EglBase(EGL10.EGL_NO_CONTEXT, EglBase.ConfigType.PIXEL_BUFFER); + EglBase eglBase = EglBase.create(null, EglBase.ConfigType.PIXEL_BUFFER); eglBase.createPbufferSurface(WIDTH, HEIGHT); eglBase.makeCurrent(); @@ -231,8 +227,9 @@ public final class GlRectDrawerTest extends ActivityTestCase { private final int rgbTexture; public StubOesTextureProducer( - EGLContext sharedContext, SurfaceTexture surfaceTexture, int width, int height) { - eglBase = new EglBase(sharedContext, EglBase.ConfigType.PLAIN); + EglBase.Context sharedContext, SurfaceTexture surfaceTexture, int width, + int height) { + eglBase = EglBase.create(sharedContext, EglBase.ConfigType.PLAIN); surfaceTexture.setDefaultBufferSize(width, height); eglBase.createSurface(surfaceTexture); assertEquals(eglBase.surfaceWidth(), width); @@ -266,14 +263,14 @@ public final class GlRectDrawerTest extends ActivityTestCase { } // Create EGL base with a pixel buffer as display output. - final EglBase eglBase = new EglBase(EGL10.EGL_NO_CONTEXT, EglBase.ConfigType.PIXEL_BUFFER); + final EglBase eglBase = EglBase.create(null, EglBase.ConfigType.PIXEL_BUFFER); eglBase.createPbufferSurface(WIDTH, HEIGHT); // Create resources for generating OES textures. final SurfaceTextureHelper surfaceTextureHelper = - SurfaceTextureHelper.create(eglBase.getContext()); + SurfaceTextureHelper.create(eglBase.getEglBaseContext()); final StubOesTextureProducer oesProducer = new StubOesTextureProducer( - eglBase.getContext(), surfaceTextureHelper.getSurfaceTexture(), WIDTH, HEIGHT); + eglBase.getEglBaseContext(), surfaceTextureHelper.getSurfaceTexture(), WIDTH, HEIGHT); final SurfaceTextureHelperTest.MockTextureListener listener = new SurfaceTextureHelperTest.MockTextureListener(); surfaceTextureHelper.setListener(listener); diff --git a/talk/app/webrtc/androidtests/src/org/webrtc/MediaCodecVideoEncoderTest.java b/talk/app/webrtc/androidtests/src/org/webrtc/MediaCodecVideoEncoderTest.java index ee62008010..1367189fe3 100644 --- a/talk/app/webrtc/androidtests/src/org/webrtc/MediaCodecVideoEncoderTest.java +++ b/talk/app/webrtc/androidtests/src/org/webrtc/MediaCodecVideoEncoderTest.java @@ -38,8 +38,6 @@ import org.webrtc.MediaCodecVideoEncoder.OutputBufferInfo; import java.nio.ByteBuffer; -import javax.microedition.khronos.egl.EGL10; - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) public final class MediaCodecVideoEncoderTest extends ActivityTestCase { final static String TAG = "MediaCodecVideoEncoderTest"; @@ -63,11 +61,13 @@ public final class MediaCodecVideoEncoderTest extends ActivityTestCase { Log.i(TAG, "hardware does not support VP8 encoding, skipping testEncoderUsingTextures"); return; } + EglBase eglBase = EglBase.create(); MediaCodecVideoEncoder encoder = new MediaCodecVideoEncoder(); assertTrue(encoder.initEncode( MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, 640, 480, 300, 30, - EGL10.EGL_NO_CONTEXT)); + eglBase.getEglBaseContext())); encoder.release(); + eglBase.release(); } @SmallTest @@ -81,10 +81,12 @@ public final class MediaCodecVideoEncoderTest extends ActivityTestCase { MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, 640, 480, 300, 30, null)); encoder.release(); + EglBase eglBase = EglBase.create(); assertTrue(encoder.initEncode( MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, 640, 480, 300, 30, - EGL10.EGL_NO_CONTEXT)); + eglBase.getEglBaseContext())); encoder.release(); + eglBase.release(); } @SmallTest @@ -141,7 +143,7 @@ public final class MediaCodecVideoEncoderTest extends ActivityTestCase { final int height = 480; final long presentationTs = 2; - final EglBase eglOesBase = new EglBase(EGL10.EGL_NO_CONTEXT, EglBase.ConfigType.PIXEL_BUFFER); + final EglBase eglOesBase = EglBase.create(null, EglBase.ConfigType.PIXEL_BUFFER); eglOesBase.createDummyPbufferSurface(); eglOesBase.makeCurrent(); int oesTextureId = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES); @@ -154,7 +156,7 @@ public final class MediaCodecVideoEncoderTest extends ActivityTestCase { assertTrue(encoder.initEncode( MediaCodecVideoEncoder.VideoCodecType.VIDEO_CODEC_VP8, width, height, 300, 30, - eglOesBase.getContext())); + eglOesBase.getEglBaseContext())); assertTrue(encoder.encodeTexture(true, oesTextureId, RendererCommon.identityMatrix(), presentationTs)); GlUtil.checkNoGLES2Error("encodeTexture"); diff --git a/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java b/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java index 5a3b9b66e7..9879522cc9 100644 --- a/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java +++ b/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java @@ -37,8 +37,6 @@ import android.test.suitebuilder.annotation.SmallTest; import java.nio.ByteBuffer; -import javax.microedition.khronos.egl.EGL10; - public final class SurfaceTextureHelperTest extends ActivityTestCase { /** * Mock texture listener with blocking wait functionality. @@ -109,20 +107,21 @@ public final class SurfaceTextureHelperTest extends ActivityTestCase { final int width = 16; final int height = 16; // Create EGL base with a pixel buffer as display output. - final EglBase eglBase = new EglBase(EGL10.EGL_NO_CONTEXT, EglBase.ConfigType.PIXEL_BUFFER); + final EglBase eglBase = EglBase.create(null, EglBase.ConfigType.PIXEL_BUFFER); eglBase.createPbufferSurface(width, height); final GlRectDrawer drawer = new GlRectDrawer(); // Create SurfaceTextureHelper and listener. final SurfaceTextureHelper surfaceTextureHelper = - SurfaceTextureHelper.create(eglBase.getContext()); + SurfaceTextureHelper.create(eglBase.getEglBaseContext()); final MockTextureListener listener = new MockTextureListener(); surfaceTextureHelper.setListener(listener); surfaceTextureHelper.getSurfaceTexture().setDefaultBufferSize(width, height); // Create resources for stubbing an OES texture producer. |eglOesBase| has the SurfaceTexture in // |surfaceTextureHelper| as the target EGLSurface. - final EglBase eglOesBase = new EglBase(eglBase.getContext(), EglBase.ConfigType.PLAIN); + final EglBase eglOesBase = + EglBase.create(eglBase.getEglBaseContext(), EglBase.ConfigType.PLAIN); eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture()); assertEquals(eglOesBase.surfaceWidth(), width); assertEquals(eglOesBase.surfaceHeight(), height); @@ -176,19 +175,20 @@ public final class SurfaceTextureHelperTest extends ActivityTestCase { final int width = 16; final int height = 16; // Create EGL base with a pixel buffer as display output. - final EglBase eglBase = new EglBase(EGL10.EGL_NO_CONTEXT, EglBase.ConfigType.PIXEL_BUFFER); + final EglBase eglBase = EglBase.create(null, EglBase.ConfigType.PIXEL_BUFFER); eglBase.createPbufferSurface(width, height); // Create SurfaceTextureHelper and listener. final SurfaceTextureHelper surfaceTextureHelper = - SurfaceTextureHelper.create(eglBase.getContext()); + SurfaceTextureHelper.create(eglBase.getEglBaseContext()); final MockTextureListener listener = new MockTextureListener(); surfaceTextureHelper.setListener(listener); surfaceTextureHelper.getSurfaceTexture().setDefaultBufferSize(width, height); // Create resources for stubbing an OES texture producer. |eglOesBase| has the SurfaceTexture in // |surfaceTextureHelper| as the target EGLSurface. - final EglBase eglOesBase = new EglBase(eglBase.getContext(), EglBase.ConfigType.PLAIN); + final EglBase eglOesBase = + EglBase.create(eglBase.getEglBaseContext(), EglBase.ConfigType.PLAIN); eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture()); assertEquals(eglOesBase.surfaceWidth(), width); assertEquals(eglOesBase.surfaceHeight(), height); @@ -240,11 +240,11 @@ public final class SurfaceTextureHelperTest extends ActivityTestCase { public static void testDisconnect() throws InterruptedException { // Create SurfaceTextureHelper and listener. final SurfaceTextureHelper surfaceTextureHelper = - SurfaceTextureHelper.create(EGL10.EGL_NO_CONTEXT); + SurfaceTextureHelper.create(null); final MockTextureListener listener = new MockTextureListener(); surfaceTextureHelper.setListener(listener); // Create EglBase with the SurfaceTexture as target EGLSurface. - final EglBase eglBase = new EglBase(EGL10.EGL_NO_CONTEXT, EglBase.ConfigType.PLAIN); + final EglBase eglBase = EglBase.create(null, EglBase.ConfigType.PLAIN); eglBase.createSurface(surfaceTextureHelper.getSurfaceTexture()); eglBase.makeCurrent(); // Assert no frame has been received yet. @@ -276,7 +276,7 @@ public final class SurfaceTextureHelperTest extends ActivityTestCase { @SmallTest public static void testDisconnectImmediately() { final SurfaceTextureHelper surfaceTextureHelper = - SurfaceTextureHelper.create(EGL10.EGL_NO_CONTEXT); + SurfaceTextureHelper.create(null); surfaceTextureHelper.disconnect(); } @@ -292,14 +292,14 @@ public final class SurfaceTextureHelperTest extends ActivityTestCase { // Create SurfaceTextureHelper and listener. final SurfaceTextureHelper surfaceTextureHelper = - SurfaceTextureHelper.create(EGL10.EGL_NO_CONTEXT, handler); + SurfaceTextureHelper.create(null, handler); // Create a mock listener and expect frames to be delivered on |thread|. final MockTextureListener listener = new MockTextureListener(thread); surfaceTextureHelper.setListener(listener); // Create resources for stubbing an OES texture producer. |eglOesBase| has the // SurfaceTexture in |surfaceTextureHelper| as the target EGLSurface. - final EglBase eglOesBase = new EglBase(EGL10.EGL_NO_CONTEXT, EglBase.ConfigType.PLAIN); + final EglBase eglOesBase = EglBase.create(null, EglBase.ConfigType.PLAIN); eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture()); eglOesBase.makeCurrent(); // Draw a frame onto the SurfaceTexture. @@ -328,14 +328,14 @@ public final class SurfaceTextureHelperTest extends ActivityTestCase { // Create SurfaceTextureHelper and listener. final SurfaceTextureHelper surfaceTextureHelper = - SurfaceTextureHelper.create(EGL10.EGL_NO_CONTEXT, handler); + SurfaceTextureHelper.create(null, handler); // Create a mock listener and expect frames to be delivered on |thread|. final MockTextureListener listener = new MockTextureListener(thread); surfaceTextureHelper.setListener(listener); // Create resources for stubbing an OES texture producer. |eglOesBase| has the // SurfaceTexture in |surfaceTextureHelper| as the target EGLSurface. - final EglBase eglOesBase = new EglBase(EGL10.EGL_NO_CONTEXT, EglBase.ConfigType.PLAIN); + final EglBase eglOesBase = EglBase.create(null, EglBase.ConfigType.PLAIN); eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture()); eglOesBase.makeCurrent(); // Draw a frame onto the SurfaceTexture. diff --git a/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceViewRendererOnMeasureTest.java b/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceViewRendererOnMeasureTest.java index 47fe780124..341c632b58 100644 --- a/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceViewRendererOnMeasureTest.java +++ b/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceViewRendererOnMeasureTest.java @@ -36,8 +36,6 @@ import java.nio.ByteBuffer; import java.util.Arrays; import java.util.List; -import javax.microedition.khronos.egl.EGL10; - public final class SurfaceViewRendererOnMeasureTest extends ActivityTestCase { /** * List with all possible scaling types. @@ -111,7 +109,7 @@ public final class SurfaceViewRendererOnMeasureTest extends ActivityTestCase { } // Test behaviour after SurfaceViewRenderer.init() is called, but still no frame. - surfaceViewRenderer.init(EGL10.EGL_NO_CONTEXT, null); + surfaceViewRenderer.init((EglBase.Context) null, null); for (RendererCommon.ScalingType scalingType : scalingTypes) { for (int measureSpecMode : measureSpecModes) { final int zeroMeasureSize = MeasureSpec.makeMeasureSpec(0, measureSpecMode); @@ -134,7 +132,7 @@ public final class SurfaceViewRendererOnMeasureTest extends ActivityTestCase { public void testFrame1280x720() { final SurfaceViewRenderer surfaceViewRenderer = new SurfaceViewRenderer(getInstrumentation().getContext()); - surfaceViewRenderer.init(EGL10.EGL_NO_CONTEXT, null); + surfaceViewRenderer.init((EglBase.Context) null, null); // Test different rotation degress, but same rotated size. for (int rotationDegree : new int[] {0, 90, 180, 270}) { diff --git a/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java b/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java index f89d222428..dfa7c0a298 100644 --- a/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java +++ b/talk/app/webrtc/androidtests/src/org/webrtc/VideoCapturerAndroidTest.java @@ -36,8 +36,6 @@ import org.webrtc.CameraEnumerationAndroid.CaptureFormat; import java.util.HashSet; import java.util.Set; -import javax.microedition.khronos.egl.EGL10; - @SuppressWarnings("deprecation") public class VideoCapturerAndroidTest extends ActivityTestCase { static final String TAG = "VideoCapturerAndroidTest"; @@ -86,8 +84,10 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { @SmallTest public void testCreateAndReleaseUsingTextures() { + EglBase eglBase = EglBase.create(); VideoCapturerAndroidTestFixtures.release( - VideoCapturerAndroid.create("", null, EGL10.EGL_NO_CONTEXT)); + VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext())); + eglBase.release(); } @SmallTest @@ -109,9 +109,11 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { @SmallTest public void testStartVideoCapturerUsingTextures() throws InterruptedException { + EglBase eglBase = EglBase.create(); VideoCapturerAndroid capturer = - VideoCapturerAndroid.create("", null, EGL10.EGL_NO_CONTEXT); + VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext()); VideoCapturerAndroidTestFixtures.startCapturerAndRender(capturer); + eglBase.release(); } @SmallTest @@ -151,8 +153,11 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { @SmallTest public void testSwitchVideoCapturerUsingTextures() throws InterruptedException { - VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null, EGL10.EGL_NO_CONTEXT); + EglBase eglBase = EglBase.create(); + VideoCapturerAndroid capturer = + VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext()); VideoCapturerAndroidTestFixtures.switchCamera(capturer); + eglBase.release(); } @MediumTest @@ -176,12 +181,14 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { @MediumTest public void testCameraCallsAfterStopUsingTextures() throws InterruptedException { + EglBase eglBase = EglBase.create(); final String deviceName = CameraEnumerationAndroid.getDeviceName(0); final VideoCapturerAndroid capturer = VideoCapturerAndroid.create(deviceName, null, - EGL10.EGL_NO_CONTEXT); + eglBase.getEglBaseContext()); VideoCapturerAndroidTestFixtures.cameraCallsAfterStop(capturer, getInstrumentation().getContext()); + eglBase.release(); } @SmallTest @@ -194,8 +201,11 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { @SmallTest public void testStopRestartVideoSourceUsingTextures() throws InterruptedException { - VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null, EGL10.EGL_NO_CONTEXT); + EglBase eglBase = EglBase.create(); + VideoCapturerAndroid capturer = + VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext()); VideoCapturerAndroidTestFixtures.stopRestartVideoSource(capturer); + eglBase.release(); } @SmallTest @@ -211,11 +221,13 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { @SmallTest public void testStartStopWithDifferentResolutionsUsingTextures() throws InterruptedException { + EglBase eglBase = EglBase.create(); String deviceName = CameraEnumerationAndroid.getDeviceName(0); VideoCapturerAndroid capturer = - VideoCapturerAndroid.create(deviceName, null, EGL10.EGL_NO_CONTEXT); + VideoCapturerAndroid.create(deviceName, null, eglBase.getEglBaseContext()); VideoCapturerAndroidTestFixtures.startStopWithDifferentResolutions(capturer, getInstrumentation().getContext()); + eglBase.release(); } @SmallTest @@ -266,11 +278,13 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { @SmallTest public void testReturnBufferLateUsingTextures() throws InterruptedException { + EglBase eglBase = EglBase.create(); String deviceName = CameraEnumerationAndroid.getDeviceName(0); VideoCapturerAndroid capturer = - VideoCapturerAndroid.create(deviceName, null, EGL10.EGL_NO_CONTEXT); + VideoCapturerAndroid.create(deviceName, null, eglBase.getEglBaseContext()); VideoCapturerAndroidTestFixtures.returnBufferLate(capturer, getInstrumentation().getContext()); + eglBase.release(); } @MediumTest @@ -284,9 +298,11 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { @MediumTest public void testReturnBufferLateEndToEndUsingTextures() throws InterruptedException { + EglBase eglBase = EglBase.create(); final VideoCapturerAndroid capturer = - VideoCapturerAndroid.create("", null, EGL10.EGL_NO_CONTEXT); + VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext()); VideoCapturerAndroidTestFixtures.returnBufferLateEndToEnd(capturer); + eglBase.release(); } @MediumTest @@ -312,7 +328,10 @@ public class VideoCapturerAndroidTest extends ActivityTestCase { // This test that frames forwarded to a renderer is scaled if onOutputFormatRequest is // called. This test both Java and C++ parts of of the stack. public void testScaleCameraOutputUsingTextures() throws InterruptedException { - VideoCapturerAndroid capturer = VideoCapturerAndroid.create("", null, EGL10.EGL_NO_CONTEXT); + EglBase eglBase = EglBase.create(); + VideoCapturerAndroid capturer = + VideoCapturerAndroid.create("", null, eglBase.getEglBaseContext()); VideoCapturerAndroidTestFixtures.scaleCameraOutput(capturer); + eglBase.release(); } } diff --git a/talk/app/webrtc/java/android/org/webrtc/EglBase.java b/talk/app/webrtc/java/android/org/webrtc/EglBase.java index 1de34d254e..a68840c8c8 100644 --- a/talk/app/webrtc/java/android/org/webrtc/EglBase.java +++ b/talk/app/webrtc/java/android/org/webrtc/EglBase.java @@ -34,6 +34,8 @@ import android.view.Surface; import android.view.SurfaceHolder; import org.webrtc.Logging; +import org.webrtc.EglBase.ConfigType; +import org.webrtc.EglBase.Context; import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGLConfig; @@ -42,7 +44,8 @@ import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLSurface; /** - * Holds EGL state and utility methods for handling an EGLContext, an EGLDisplay, and an EGLSurface. + * Holds EGL state and utility methods for handling an egl 1.0 EGLContext, an EGLDisplay, + * and an EGLSurface. */ public class EglBase { private static final String TAG = "EglBase"; @@ -62,6 +65,15 @@ public class EglBase { private EGLDisplay eglDisplay; private EGLSurface eglSurface = EGL10.EGL_NO_SURFACE; + // EGL wrapper for an actual EGLContext. + public static class Context { + private final EGLContext eglContext; + + public Context(EGLContext eglContext) { + this.eglContext = eglContext; + } + } + // EGLConfig constructor type. Influences eglChooseConfig arguments. public static enum ConfigType { // No special parameters. @@ -74,14 +86,39 @@ public class EglBase { RECORDABLE } - // Create root context without any EGLSurface or parent EGLContext. This can be used for branching + // Create a new context with the specified config type, sharing data with sharedContext. + // |sharedContext| can be null. + public static EglBase create(Context sharedContext, ConfigType configType) { + return (EglBase14.isEGL14Supported() + && (sharedContext == null || sharedContext instanceof EglBase14.Context)) + ? new EglBase14((EglBase14.Context) sharedContext, configType) + : new EglBase(sharedContext, configType); + } + + public static EglBase create() { + return create(null, ConfigType.PLAIN); + } + + //Create root context without any EGLSurface or parent EGLContext. This can be used for branching // new contexts that share data. + @Deprecated public EglBase() { - this(EGL10.EGL_NO_CONTEXT, ConfigType.PLAIN); + this((Context) null, ConfigType.PLAIN); + } + + @Deprecated + public EglBase(EGLContext sharedContext, ConfigType configType) { + this(new Context(sharedContext), configType); + Logging.d(TAG, "EglBase created"); + } + + @Deprecated + public EGLContext getContext() { + return eglContext; } // Create a new context with the specified config type, sharing data with sharedContext. - public EglBase(EGLContext sharedContext, ConfigType configType) { + EglBase(Context sharedContext, ConfigType configType) { this.egl = (EGL10) EGLContext.getEGL(); this.configType = configType; eglDisplay = getEglDisplay(); @@ -89,7 +126,13 @@ public class EglBase { eglContext = createEglContext(sharedContext, eglDisplay, eglConfig); } - // Create EGLSurface from the Android Surface. + // TODO(perkj): This is a hacky ctor used to allow us to create an EGLBase14. Remove this and + // make EglBase an abstract class once all applications have started using the create factory + // method. + protected EglBase(boolean dummy) { + this.egl = null; + } + public void createSurface(Surface surface) { /** * We have to wrap Surface in a SurfaceHolder because for some reason eglCreateWindowSurface @@ -114,6 +157,7 @@ public class EglBase { return false; } + @Deprecated @Override public void setType(int i) {} @@ -201,8 +245,8 @@ public class EglBase { } } - public EGLContext getContext() { - return eglContext; + public Context getEglBaseContext() { + return new Context(eglContext); } public boolean hasSurface() { @@ -324,10 +368,12 @@ public class EglBase { // Return an EGLConfig, or die trying. private EGLContext createEglContext( - EGLContext sharedContext, EGLDisplay eglDisplay, EGLConfig eglConfig) { + Context sharedContext, EGLDisplay eglDisplay, EGLConfig eglConfig) { int[] contextAttributes = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE}; + EGLContext rootContext = + sharedContext == null ? EGL10.EGL_NO_CONTEXT : sharedContext.eglContext; EGLContext eglContext = - egl.eglCreateContext(eglDisplay, eglConfig, sharedContext, contextAttributes); + egl.eglCreateContext(eglDisplay, eglConfig, rootContext, contextAttributes); if (eglContext == EGL10.EGL_NO_CONTEXT) { throw new RuntimeException("Failed to create EGL context"); } diff --git a/talk/app/webrtc/java/android/org/webrtc/EglBase14.java b/talk/app/webrtc/java/android/org/webrtc/EglBase14.java new file mode 100644 index 0000000000..20db000a43 --- /dev/null +++ b/talk/app/webrtc/java/android/org/webrtc/EglBase14.java @@ -0,0 +1,281 @@ +/* + * libjingle + * Copyright 2015 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.webrtc; + +import android.annotation.TargetApi; +import android.graphics.SurfaceTexture; +import android.opengl.EGL14; +import android.opengl.EGLConfig; +import android.opengl.EGLContext; +import android.opengl.EGLDisplay; +import android.opengl.EGLSurface; +import android.view.Surface; + +import org.webrtc.Logging; + +/** + * Holds EGL state and utility methods for handling an EGL14 EGLContext, an EGLDisplay, + * and an EGLSurface. + */ +@TargetApi(17) +final class EglBase14 extends EglBase { + private static final String TAG = "EglBase14"; + private static final int EGL14_SDK_VERSION = android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; + private static final int CURRENT_SDK_VERSION = android.os.Build.VERSION.SDK_INT; + // Android-specific extension. + private static final int EGL_RECORDABLE_ANDROID = 0x3142; + + private EGLContext eglContext; + private ConfigType configType; + private EGLConfig eglConfig; + private EGLDisplay eglDisplay; + private EGLSurface eglSurface = EGL14.EGL_NO_SURFACE; + + public static boolean isEGL14Supported() { + Logging.d(TAG, "SDK version: " + CURRENT_SDK_VERSION + + ". isEGL14Supported: " + (CURRENT_SDK_VERSION >= EGL14_SDK_VERSION)); + return (CURRENT_SDK_VERSION >= EGL14_SDK_VERSION); + } + + public static class Context extends EglBase.Context { + private final android.opengl.EGLContext egl14Context; + + Context(android.opengl.EGLContext eglContext) { + super(null); + this.egl14Context = eglContext; + } + } + + // Create a new context with the specified config type, sharing data with sharedContext. + // |sharedContext| may be null. + EglBase14(EglBase14.Context sharedContext, ConfigType configType) { + super(true /* dummy */); + this.configType = configType; + eglDisplay = getEglDisplay(); + eglConfig = getEglConfig(eglDisplay, configType); + eglContext = createEglContext(sharedContext, eglDisplay, eglConfig); + } + + // Create EGLSurface from the Android Surface. + @Override + public void createSurface(Surface surface) { + createSurfaceInternal(surface); + } + + // Create EGLSurface from the Android SurfaceTexture. + @Override + public void createSurface(SurfaceTexture surfaceTexture) { + createSurfaceInternal(surfaceTexture); + } + + // Create EGLSurface from either Surface or SurfaceTexture. + private void createSurfaceInternal(Object surface) { + if (!(surface instanceof Surface) && !(surface instanceof SurfaceTexture)) { + throw new IllegalStateException("Input must be either a Surface or SurfaceTexture"); + } + checkIsNotReleased(); + if (configType == ConfigType.PIXEL_BUFFER) { + Logging.w(TAG, "This EGL context is configured for PIXEL_BUFFER, but uses regular Surface"); + } + if (eglSurface != EGL14.EGL_NO_SURFACE) { + throw new RuntimeException("Already has an EGLSurface"); + } + int[] surfaceAttribs = {EGL14.EGL_NONE}; + eglSurface = EGL14.eglCreateWindowSurface(eglDisplay, eglConfig, surface, surfaceAttribs, 0); + if (eglSurface == EGL14.EGL_NO_SURFACE) { + throw new RuntimeException("Failed to create window surface"); + } + } + + @Override + public void createDummyPbufferSurface() { + createPbufferSurface(1, 1); + } + + @Override + public void createPbufferSurface(int width, int height) { + checkIsNotReleased(); + if (configType != ConfigType.PIXEL_BUFFER) { + throw new RuntimeException( + "This EGL context is not configured to use a pixel buffer: " + configType); + } + if (eglSurface != EGL14.EGL_NO_SURFACE) { + throw new RuntimeException("Already has an EGLSurface"); + } + int[] surfaceAttribs = {EGL14.EGL_WIDTH, width, EGL14.EGL_HEIGHT, height, EGL14.EGL_NONE}; + eglSurface = EGL14.eglCreatePbufferSurface(eglDisplay, eglConfig, surfaceAttribs, 0); + if (eglSurface == EGL14.EGL_NO_SURFACE) { + throw new RuntimeException("Failed to create pixel buffer surface"); + } + } + + @Override + public Context getEglBaseContext() { + return new EglBase14.Context(eglContext); + } + + @Override + public boolean hasSurface() { + return eglSurface != EGL14.EGL_NO_SURFACE; + } + + @Override + public int surfaceWidth() { + final int widthArray[] = new int[1]; + EGL14.eglQuerySurface(eglDisplay, eglSurface, EGL14.EGL_WIDTH, widthArray, 0); + return widthArray[0]; + } + + @Override + public int surfaceHeight() { + final int heightArray[] = new int[1]; + EGL14.eglQuerySurface(eglDisplay, eglSurface, EGL14.EGL_HEIGHT, heightArray, 0); + return heightArray[0]; + } + + @Override + public void releaseSurface() { + if (eglSurface != EGL14.EGL_NO_SURFACE) { + EGL14.eglDestroySurface(eglDisplay, eglSurface); + eglSurface = EGL14.EGL_NO_SURFACE; + } + } + + private void checkIsNotReleased() { + if (eglDisplay == EGL14.EGL_NO_DISPLAY || eglContext == EGL14.EGL_NO_CONTEXT + || eglConfig == null) { + throw new RuntimeException("This object has been released"); + } + } + + @Override + public void release() { + checkIsNotReleased(); + releaseSurface(); + detachCurrent(); + EGL14.eglDestroyContext(eglDisplay, eglContext); + EGL14.eglReleaseThread(); + EGL14.eglTerminate(eglDisplay); + eglContext = EGL14.EGL_NO_CONTEXT; + eglDisplay = EGL14.EGL_NO_DISPLAY; + eglConfig = null; + } + + @Override + public void makeCurrent() { + checkIsNotReleased(); + if (eglSurface == EGL14.EGL_NO_SURFACE) { + throw new RuntimeException("No EGLSurface - can't make current"); + } + if (!EGL14.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { + throw new RuntimeException("eglMakeCurrent failed"); + } + } + + // Detach the current EGL context, so that it can be made current on another thread. + @Override + public void detachCurrent() { + if (!EGL14.eglMakeCurrent( + eglDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT)) { + throw new RuntimeException("eglMakeCurrent failed"); + } + } + + @Override + public void swapBuffers() { + checkIsNotReleased(); + if (eglSurface == EGL14.EGL_NO_SURFACE) { + throw new RuntimeException("No EGLSurface - can't swap buffers"); + } + EGL14.eglSwapBuffers(eglDisplay, eglSurface); + } + + // Return an EGLDisplay, or die trying. + private static EGLDisplay getEglDisplay() { + EGLDisplay eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY); + if (eglDisplay == EGL14.EGL_NO_DISPLAY) { + throw new RuntimeException("Unable to get EGL14 display"); + } + int[] version = new int[2]; + if (!EGL14.eglInitialize(eglDisplay, version, 0, version, 1)) { + throw new RuntimeException("Unable to initialize EGL14"); + } + return eglDisplay; + } + + // Return an EGLConfig, or die trying. + private static EGLConfig getEglConfig(EGLDisplay eglDisplay, ConfigType configType) { + // Always RGB888, GLES2. + int[] configAttributes = { + EGL14.EGL_RED_SIZE, 8, + EGL14.EGL_GREEN_SIZE, 8, + EGL14.EGL_BLUE_SIZE, 8, + EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT, + EGL14.EGL_NONE, 0, // Allocate dummy fields for specific options. + EGL14.EGL_NONE + }; + + // Fill in dummy fields based on configType. + switch (configType) { + case PLAIN: + break; + case PIXEL_BUFFER: + configAttributes[configAttributes.length - 3] = EGL14.EGL_SURFACE_TYPE; + configAttributes[configAttributes.length - 2] = EGL14.EGL_PBUFFER_BIT; + break; + case RECORDABLE: + configAttributes[configAttributes.length - 3] = EGL_RECORDABLE_ANDROID; + configAttributes[configAttributes.length - 2] = 1; + break; + default: + throw new IllegalArgumentException(); + } + + EGLConfig[] configs = new EGLConfig[1]; + int[] numConfigs = new int[1]; + if (!EGL14.eglChooseConfig( + eglDisplay, configAttributes, 0, configs, 0, configs.length, numConfigs, 0)) { + throw new RuntimeException("Unable to find RGB888 " + configType + " EGL config"); + } + return configs[0]; + } + + // Return an EGLConfig, or die trying. + private static EGLContext createEglContext( + EglBase14.Context sharedContext, EGLDisplay eglDisplay, EGLConfig eglConfig) { + int[] contextAttributes = {EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE}; + EGLContext rootContext = + sharedContext == null ? EGL14.EGL_NO_CONTEXT : sharedContext.egl14Context; + EGLContext eglContext = + EGL14.eglCreateContext(eglDisplay, eglConfig, rootContext, contextAttributes, 0); + if (eglContext == EGL14.EGL_NO_CONTEXT) { + throw new RuntimeException("Failed to create EGL context"); + } + return eglContext; + } +} diff --git a/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java b/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java index 2df7716446..193ebd9676 100644 --- a/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java +++ b/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java @@ -39,8 +39,6 @@ import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import javax.microedition.khronos.egl.EGLContext; - /** * Helper class to create and synchronize access to a SurfaceTexture. The caller will get notified * of new frames in onTextureFrameAvailable(), and should call returnTextureFrame() when done with @@ -65,7 +63,7 @@ class SurfaceTextureHelper { int oesTextureId, float[] transformMatrix, long timestampNs); } - public static SurfaceTextureHelper create(EGLContext sharedContext) { + public static SurfaceTextureHelper create(EglBase.Context sharedContext) { return create(sharedContext, null); } @@ -74,7 +72,8 @@ class SurfaceTextureHelper { * |handler| is non-null, the callback will be executed on that handler's thread. If |handler| is * null, a dedicated private thread is created for the callbacks. */ - public static SurfaceTextureHelper create(final EGLContext sharedContext, final Handler handler) { + public static SurfaceTextureHelper create(final EglBase.Context sharedContext, + final Handler handler) { final Handler finalHandler; if (handler != null) { finalHandler = handler; @@ -105,14 +104,15 @@ class SurfaceTextureHelper { private boolean isTextureInUse = false; private boolean isQuitting = false; - private SurfaceTextureHelper(EGLContext sharedContext, Handler handler, boolean isOwningThread) { + private SurfaceTextureHelper(EglBase.Context sharedContext, + Handler handler, boolean isOwningThread) { if (handler.getLooper().getThread() != Thread.currentThread()) { throw new IllegalStateException("SurfaceTextureHelper must be created on the handler thread"); } this.handler = handler; this.isOwningThread = isOwningThread; - eglBase = new EglBase(sharedContext, EglBase.ConfigType.PIXEL_BUFFER); + eglBase = EglBase.create(sharedContext, EglBase.ConfigType.PIXEL_BUFFER); eglBase.createDummyPbufferSurface(); eglBase.makeCurrent(); diff --git a/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java b/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java index ed6e8dd2d6..9ca7a9e66f 100644 --- a/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java +++ b/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java @@ -153,7 +153,7 @@ public class SurfaceViewRenderer extends SurfaceView * reinitialize the renderer after a previous init()/release() cycle. */ public void init( - EGLContext sharedContext, RendererCommon.RendererEvents rendererEvents) { + EglBase.Context sharedContext, RendererCommon.RendererEvents rendererEvents) { synchronized (handlerLock) { if (renderThreadHandler != null) { throw new IllegalStateException(getResourceName() + "Already initialized"); @@ -163,12 +163,19 @@ public class SurfaceViewRenderer extends SurfaceView renderThread = new HandlerThread(TAG); renderThread.start(); drawer = new GlRectDrawer(); - eglBase = new EglBase(sharedContext, EglBase.ConfigType.PLAIN); + eglBase = EglBase.create(sharedContext, EglBase.ConfigType.PLAIN); renderThreadHandler = new Handler(renderThread.getLooper()); } tryCreateEglSurface(); } + @Deprecated + // TODO(perkj): Remove when applications has been updated. + public void init( + EGLContext sharedContext, RendererCommon.RendererEvents rendererEvents) { + init(sharedContext != null ? new EglBase.Context(sharedContext) : null, rendererEvents); + } + /** * Create and make an EGLSurface current if both init() and surfaceCreated() have been called. */ @@ -560,7 +567,7 @@ public class SurfaceViewRenderer extends SurfaceView if (framesReceived > 0 && framesRendered > 0) { final long timeSinceFirstFrameNs = System.nanoTime() - firstFrameTimeNs; Logging.d(TAG, getResourceName() + "Duration: " + (int) (timeSinceFirstFrameNs / 1e6) + - " ms. FPS: " + (float) framesRendered * 1e9 / timeSinceFirstFrameNs); + " ms. FPS: " + framesRendered * 1e9 / timeSinceFirstFrameNs); Logging.d(TAG, getResourceName() + "Average render time: " + (int) (renderTimeNs / (1000 * framesRendered)) + " us."); } diff --git a/talk/app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java b/talk/app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java index 66b4048b9d..72ef309de3 100644 --- a/talk/app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java +++ b/talk/app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java @@ -50,9 +50,6 @@ import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGL10; - // Android specific implementation of VideoCapturer. // An instance of this class can be created by an application using // VideoCapturerAndroid.create(); @@ -235,7 +232,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements } public static VideoCapturerAndroid create(String name, - CameraEventsHandler eventsHandler, EGLContext sharedEglContext) { + CameraEventsHandler eventsHandler, EglBase.Context sharedEglContext) { final int cameraId = lookupDeviceName(name); if (cameraId == -1) { return null; @@ -351,7 +348,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements } private VideoCapturerAndroid(int cameraId, CameraEventsHandler eventsHandler, - EGLContext sharedContext) { + EglBase.Context sharedContext) { Logging.d(TAG, "VideoCapturerAndroid"); this.id = cameraId; this.eventsHandler = eventsHandler; @@ -362,8 +359,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements isCapturingToTexture = (sharedContext != null); cameraStatistics = new CameraStatistics(isCapturingToTexture ? 1 : videoBuffers.numCaptureBuffers); - surfaceHelper = SurfaceTextureHelper.create( - isCapturingToTexture ? sharedContext : EGL10.EGL_NO_CONTEXT, cameraThreadHandler); + surfaceHelper = SurfaceTextureHelper.create(sharedContext, cameraThreadHandler); if (isCapturingToTexture) { surfaceHelper.setListener(this); } diff --git a/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java b/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java index da6e51bc29..e9e95abedf 100644 --- a/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java +++ b/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java @@ -415,10 +415,15 @@ public class VideoRendererGui implements GLSurfaceView.Renderer { eglContextReady = eglContextReadyCallback; } + @Deprecated public static synchronized EGLContext getEGLContext() { return eglContext; } + public static synchronized EglBase.Context getEglBaseContext() { + return new EglBase.Context(eglContext); + } + /** Releases GLSurfaceView video renderer. */ public static synchronized void dispose() { if (instance == null){ diff --git a/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc b/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc index 4554e7b59c..fa111968f6 100644 --- a/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc +++ b/talk/app/webrtc/java/jni/androidmediadecoder_jni.cc @@ -858,7 +858,7 @@ void MediaCodecVideoDecoderFactory::SetEGLContext( render_egl_context_ = NULL; } else { jclass j_egl_context_class = - FindClass(jni, "javax/microedition/khronos/egl/EGLContext"); + FindClass(jni, "org/webrtc/EglBase$Context"); if (!jni->IsInstanceOf(render_egl_context_, j_egl_context_class)) { ALOGE << "Wrong EGL Context."; jni->DeleteGlobalRef(render_egl_context_); diff --git a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc index 37eeb6ccc5..92ec4f05cf 100644 --- a/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc +++ b/talk/app/webrtc/java/jni/androidmediaencoder_jni.cc @@ -278,7 +278,7 @@ MediaCodecVideoEncoder::MediaCodecVideoEncoder( *j_media_codec_video_encoder_class_, "initEncode", "(Lorg/webrtc/MediaCodecVideoEncoder$VideoCodecType;" - "IIIILjavax/microedition/khronos/egl/EGLContext;)Z"); + "IIIILorg/webrtc/EglBase$Context;)Z"); j_get_input_buffers_method_ = GetMethodID( jni, *j_media_codec_video_encoder_class_, @@ -1123,7 +1123,7 @@ void MediaCodecVideoEncoderFactory::SetEGLContext( egl_context_ = NULL; } else { jclass j_egl_context_class = - FindClass(jni, "javax/microedition/khronos/egl/EGLContext"); + FindClass(jni, "org/webrtc/EglBase$Context"); if (!jni->IsInstanceOf(egl_context_, j_egl_context_class)) { ALOGE << "Wrong EGL Context."; jni->DeleteGlobalRef(egl_context_); diff --git a/talk/app/webrtc/java/jni/classreferenceholder.cc b/talk/app/webrtc/java/jni/classreferenceholder.cc index 13883bedbe..ea56c25e5d 100644 --- a/talk/app/webrtc/java/jni/classreferenceholder.cc +++ b/talk/app/webrtc/java/jni/classreferenceholder.cc @@ -79,6 +79,7 @@ ClassReferenceHolder::ClassReferenceHolder(JNIEnv* jni) { LoadClass(jni, "org/webrtc/VideoCapturerAndroid"); LoadClass(jni, "org/webrtc/VideoCapturerAndroid$NativeObserver"); LoadClass(jni, "org/webrtc/EglBase"); + LoadClass(jni, "org/webrtc/EglBase$Context"); LoadClass(jni, "org/webrtc/NetworkMonitor"); LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder"); LoadClass(jni, "org/webrtc/MediaCodecVideoEncoder$OutputBufferInfo"); diff --git a/talk/app/webrtc/java/jni/peerconnection_jni.cc b/talk/app/webrtc/java/jni/peerconnection_jni.cc index 194f9ff98c..560b61cf3c 100644 --- a/talk/app/webrtc/java/jni/peerconnection_jni.cc +++ b/talk/app/webrtc/java/jni/peerconnection_jni.cc @@ -1338,12 +1338,40 @@ JOW(void, PeerConnectionFactory_nativeSetVideoHwAccelerationOptions)( OwnedFactoryAndThreads* owned_factory = reinterpret_cast(native_factory); + // TODO(perkj): In order to not break existing applications we need to + // check if |local_egl_context| or |remote_egl_context| is an + // EGL10 context. If so, create an EGLBase10.EGL10Context instead. + // Remove this once existing applications has been updated. + jobject local_eglbase_context = local_egl_context; + jobject remote_eglbase_context = remote_egl_context; + + jclass j_egl10_context_class = + FindClass(jni, "javax/microedition/khronos/egl/EGLContext"); + jclass j_eglbase_context_class = + FindClass(jni, "org/webrtc/EglBase$Context"); + + jmethodID j_eglbase_context_ctor = GetMethodID( + jni, j_eglbase_context_class, + "", "(Ljavax/microedition/khronos/egl/EGLContext;)V"); + if (local_egl_context != nullptr && + jni->IsInstanceOf(local_egl_context, j_egl10_context_class)) { + local_eglbase_context = jni->NewObject( + j_eglbase_context_class, j_eglbase_context_ctor, + local_egl_context); + } + if (remote_egl_context != nullptr && + jni->IsInstanceOf(remote_egl_context, j_egl10_context_class)) { + remote_eglbase_context = jni->NewObject( + j_eglbase_context_class, j_eglbase_context_ctor, + remote_egl_context); + } + MediaCodecVideoEncoderFactory* encoder_factory = static_cast (owned_factory->encoder_factory()); if (encoder_factory) { LOG(LS_INFO) << "Set EGL context for HW encoding."; - encoder_factory->SetEGLContext(jni, local_egl_context); + encoder_factory->SetEGLContext(jni, local_eglbase_context); } MediaCodecVideoDecoderFactory* decoder_factory = @@ -1351,7 +1379,7 @@ JOW(void, PeerConnectionFactory_nativeSetVideoHwAccelerationOptions)( (owned_factory->decoder_factory()); if (decoder_factory) { LOG(LS_INFO) << "Set EGL context for HW decoding."; - decoder_factory->SetEGLContext(jni, remote_egl_context); + decoder_factory->SetEGLContext(jni, remote_eglbase_context); } #endif } diff --git a/talk/app/webrtc/java/jni/surfacetexturehelper_jni.cc b/talk/app/webrtc/java/jni/surfacetexturehelper_jni.cc index 65c1737268..8fd42a0a58 100644 --- a/talk/app/webrtc/java/jni/surfacetexturehelper_jni.cc +++ b/talk/app/webrtc/java/jni/surfacetexturehelper_jni.cc @@ -47,7 +47,7 @@ SurfaceTextureHelper::SurfaceTextureHelper(JNIEnv* jni, GetStaticMethodID(jni, *j_surface_texture_helper_class_, "create", - "(Ljavax/microedition/khronos/egl/EGLContext;)" + "(Lorg/webrtc/EglBase$Context;)" "Lorg/webrtc/SurfaceTextureHelper;"), egl_shared_context)), j_return_texture_method_(GetMethodID(jni, diff --git a/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java b/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java index 47886effd7..f10df98f9f 100644 --- a/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java +++ b/talk/app/webrtc/java/src/org/webrtc/MediaCodecVideoEncoder.java @@ -45,8 +45,6 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.CountDownLatch; -import javax.microedition.khronos.egl.EGLContext; - // Java-side of peerconnection_jni.cc:MediaCodecVideoEncoder. // This class is an implementation detail of the Java PeerConnection API. @TargetApi(19) @@ -270,7 +268,7 @@ public class MediaCodecVideoEncoder { } boolean initEncode(VideoCodecType type, int width, int height, int kbps, int fps, - EGLContext sharedContext) { + EglBase.Context sharedContext) { final boolean useSurface = sharedContext != null; Logging.d(TAG, "Java initEncode: " + type + " : " + width + " x " + height + ". @ " + kbps + " kbps. Fps: " + fps + ". Encode from texture : " + useSurface); @@ -323,7 +321,7 @@ public class MediaCodecVideoEncoder { format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); if (useSurface) { - eglBase = new EglBase(sharedContext, EglBase.ConfigType.RECORDABLE); + eglBase = EglBase.create(sharedContext, EglBase.ConfigType.RECORDABLE); // Create an input surface and keep a reference since we must release the surface when done. inputSurface = mediaCodec.createInputSurface(); eglBase.createSurface(inputSurface); diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp index 4f32102232..0a272c7be9 100755 --- a/talk/libjingle.gyp +++ b/talk/libjingle.gyp @@ -149,6 +149,7 @@ 'app/webrtc/java/android/org/webrtc/CameraEnumerationAndroid.java', 'app/webrtc/java/android/org/webrtc/CameraEnumerator.java', 'app/webrtc/java/android/org/webrtc/EglBase.java', + 'app/webrtc/java/android/org/webrtc/EglBase14.java', 'app/webrtc/java/android/org/webrtc/GlRectDrawer.java', 'app/webrtc/java/android/org/webrtc/GlShader.java', 'app/webrtc/java/android/org/webrtc/GlUtil.java', diff --git a/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java b/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java index 77e78c4a22..1bdbc3b6fc 100644 --- a/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java +++ b/webrtc/examples/androidapp/src/org/appspot/apprtc/PeerConnectionClient.java @@ -17,6 +17,7 @@ import org.appspot.apprtc.AppRTCClient.SignalingParameters; import org.appspot.apprtc.util.LooperExecutor; import org.webrtc.CameraEnumerationAndroid; import org.webrtc.DataChannel; +import org.webrtc.EglBase; import org.webrtc.IceCandidate; import org.webrtc.Logging; import org.webrtc.MediaCodecVideoEncoder; @@ -465,7 +466,7 @@ public class PeerConnectionClient { } Log.d(TAG, "Opening camera: " + cameraDeviceName); videoCapturer = VideoCapturerAndroid.create(cameraDeviceName, null, - peerConnectionParameters.captureToTexture ? renderEGLContext : null); + peerConnectionParameters.captureToTexture ? new EglBase.Context(renderEGLContext) : null); if (videoCapturer == null) { reportError("Failed to open camera"); return;