Index: talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java |
diff --git a/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java b/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java |
index dfd54544a5b46b75cd9afa05877f924e91caea9b..9ab38210d4b1e62b1f6d577d936c134624fbdec0 100644 |
--- a/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java |
+++ b/talk/app/webrtc/java/android/org/webrtc/SurfaceTextureHelper.java |
@@ -37,6 +37,7 @@ import android.os.HandlerThread; |
import android.os.SystemClock; |
import android.util.Log; |
+import java.util.concurrent.CountDownLatch; |
import java.util.concurrent.TimeUnit; |
/** |
@@ -45,8 +46,11 @@ import java.util.concurrent.TimeUnit; |
* the frame. Only one texture frame can be in flight at once, so returnTextureFrame() must be |
* called in order to receive a new frame. Call disconnect() to stop receiveing new frames and |
* release all resources. |
+ * Note that there is a C++ counter part of this class that optionally can be used. It is used for |
+ * wrapping texture frames into webrtc::VideoFrames and also handles calling returnTextureFrame() |
+ * when the webrtc::VideoFrame is no longer used. |
*/ |
-public final class SurfaceTextureHelper { |
+final class SurfaceTextureHelper { |
private static final String TAG = "SurfaceTextureHelper"; |
/** |
* Callback interface for being notified that a new texture frame is available. The calls will be |
@@ -65,18 +69,16 @@ public final class SurfaceTextureHelper { |
private final EglBase eglBase; |
private final SurfaceTexture surfaceTexture; |
private final int oesTextureId; |
- private final OnTextureFrameAvailableListener listener; |
+ private OnTextureFrameAvailableListener listener; |
// The possible states of this class. |
private boolean hasPendingTexture = false; |
private boolean isTextureInUse = false; |
private boolean isQuitting = false; |
/** |
- * Construct a new SurfaceTextureHelper to stream textures to the given |listener|, sharing OpenGL |
- * resources with |sharedContext|. |
+ * Construct a new SurfaceTextureHelper sharing OpenGL resources with |sharedContext|. |
*/ |
- public SurfaceTextureHelper(EGLContext sharedContext, OnTextureFrameAvailableListener listener) { |
- this.listener = listener; |
+ public SurfaceTextureHelper(EGLContext sharedContext) { |
thread = new HandlerThread(TAG); |
thread.start(); |
handler = new Handler(thread.getLooper()); |
@@ -87,13 +89,6 @@ public final class SurfaceTextureHelper { |
oesTextureId = GlUtil.generateTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES); |
surfaceTexture = new SurfaceTexture(oesTextureId); |
- surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() { |
- @Override |
- public void onFrameAvailable(SurfaceTexture surfaceTexture) { |
- hasPendingTexture = true; |
- tryDeliverTextureFrame(); |
- } |
- }, handler); |
// Reattach EGL context to private thread. |
eglBase.detachCurrent(); |
@@ -105,6 +100,24 @@ public final class SurfaceTextureHelper { |
} |
/** |
+ * Start to stream textures to the given |listener|. |
+ * A Listener can only be set once. |
+ */ |
+ public void setListener(OnTextureFrameAvailableListener listener) { |
+ if (this.listener != null) { |
+ throw new IllegalStateException("SurfaceTextureHelper listener has already been set."); |
+ } |
+ this.listener = listener; |
+ surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() { |
+ @Override |
+ public void onFrameAvailable(SurfaceTexture surfaceTexture) { |
+ hasPendingTexture = true; |
+ tryDeliverTextureFrame(); |
+ } |
+ }, handler); |
+ } |
+ |
+ /** |
* Retrieve the underlying SurfaceTexture. The SurfaceTexture should be passed in to a video |
* producer such as a camera or decoder. |
*/ |
@@ -131,23 +144,34 @@ public final class SurfaceTextureHelper { |
} |
/** |
- * Call disconnect() to stop receiving frames and release all resources. This function will block |
- * until all frames are returned and all resoureces are released. You are guaranteed to not |
- * receive any more onTextureFrameAvailable() after this function returns. |
+ * Call disconnect() to stop receiving frames. 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() { |
+ final CountDownLatch barrier = new CountDownLatch(1); |
handler.postAtFrontOfQueue(new Runnable() { |
@Override public void run() { |
isQuitting = true; |
+ barrier.countDown(); |
if (!isTextureInUse) { |
release(); |
} |
} |
}); |
- try { |
- thread.join(); |
- } catch (InterruptedException e) { |
- Log.e(TAG, "SurfaceTexture thread was interrupted in join()."); |
+ boolean wasInterrupted = true; |
+ while(true) { |
+ try { |
+ barrier.await(); |
+ break; |
+ } catch (InterruptedException e) { |
+ // Someone is asking us to return early at our convenience. We must wait until the |
+ // |isQuitting| flag has been set but we should preserve the information and pass it along. |
+ wasInterrupted = true; |
+ } |
+ } |
+ if (wasInterrupted) { |
+ Thread.currentThread().interrupt(); |
} |
} |