diff --git a/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java b/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java index 882fde1875..5a3b9b66e7 100644 --- a/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java +++ b/talk/app/webrtc/androidtests/src/org/webrtc/SurfaceTextureHelperTest.java @@ -313,7 +313,42 @@ public final class SurfaceTextureHelperTest extends ActivityTestCase { // Return the frame from this thread. surfaceTextureHelper.returnTextureFrame(); - surfaceTextureHelper.disconnect(); - thread.quitSafely(); + surfaceTextureHelper.disconnect(handler); + } + + /** + * Test use SurfaceTextureHelper on a separate thread. A uniform texture frame is created and + * received on a thread separate from the test thread and returned after disconnect. + */ + @MediumTest + public static void testLateReturnFrameOnSeparateThread() throws InterruptedException { + final HandlerThread thread = new HandlerThread("SurfaceTextureHelperTestThread"); + thread.start(); + final Handler handler = new Handler(thread.getLooper()); + + // Create SurfaceTextureHelper and listener. + final SurfaceTextureHelper surfaceTextureHelper = + SurfaceTextureHelper.create(EGL10.EGL_NO_CONTEXT, 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); + eglOesBase.createSurface(surfaceTextureHelper.getSurfaceTexture()); + eglOesBase.makeCurrent(); + // Draw a frame onto the SurfaceTexture. + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + // swapBuffers() will ultimately trigger onTextureFrameAvailable(). + eglOesBase.swapBuffers(); + eglOesBase.release(); + + // Wait for an OES texture to arrive. + listener.waitForNewFrame(); + + surfaceTextureHelper.disconnect(handler); + + surfaceTextureHelper.returnTextureFrame(); } } diff --git a/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java b/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java index 261191a750..2df7716446 100644 --- a/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java +++ b/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java @@ -95,7 +95,7 @@ class SurfaceTextureHelper { } private final Handler handler; - private final boolean isOwningThread; + private boolean isOwningThread; private final EglBase eglBase; private final SurfaceTexture surfaceTexture; private final int oesTextureId; @@ -170,6 +170,9 @@ class SurfaceTextureHelper { * onTextureFrameAvailable() after this function returns. */ public void disconnect() { + if (!isOwningThread) { + throw new IllegalStateException("Must call disconnect(handler)."); + } if (handler.getLooper().getThread() == Thread.currentThread()) { isQuitting = true; if (!isTextureInUse) { @@ -190,6 +193,20 @@ class SurfaceTextureHelper { ThreadUtils.awaitUninterruptibly(barrier); } + /** + * Call disconnect() to stop receiving frames and quit the looper used by |handler|. + * Resources are released when the texture frame has been returned by a call to + * returnTextureFrame(). You are guaranteed to not receive any more + * onTextureFrameAvailable() after this function returns. + */ + public void disconnect(Handler handler) { + if (this.handler != handler) { + throw new IllegalStateException("Wrong handler."); + } + isOwningThread = true; + disconnect(); + } + private void tryDeliverTextureFrame() { if (handler.getLooper().getThread() != Thread.currentThread()) { throw new IllegalStateException("Wrong thread."); @@ -222,8 +239,6 @@ class SurfaceTextureHelper { GLES20.glDeleteTextures(1, new int[] {oesTextureId}, 0); surfaceTexture.release(); eglBase.release(); - if (isOwningThread) { - handler.getLooper().quit(); - } + handler.getLooper().quit(); } } diff --git a/talk/app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java b/talk/app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java index 9fc4dd1f6b..9e1f8cd0c0 100644 --- a/talk/app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java +++ b/talk/app/webrtc/java/android/org/webrtc/VideoCapturerAndroid.java @@ -407,9 +407,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements } } }); - surfaceHelper.disconnect(); - cameraThread.quit(); - ThreadUtils.joinUninterruptibly(cameraThread); + surfaceHelper.disconnect(cameraThreadHandler); cameraThread = null; }