Chromium Code Reviews| 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..69d6a0b3cbf2066b72a7690c65779922e8f5cb8e 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(); |
| @@ -104,6 +99,21 @@ public final class SurfaceTextureHelper { |
| }); |
| } |
| + // Start to stream textures to the given |listener|. |
|
magjed_webrtc
2015/09/27 11:26:40
Use Javadoc block comment like the rest of the cla
perkj_webrtc
2015/09/28 07:22:47
Done.
|
| + public void setListener(OnTextureFrameAvailableListener listener) { |
| + if (this.listener != null) { |
| + throw new RuntimeException("SurfaceTextureHelper listener has already been set."); |
|
magjed_webrtc
2015/09/27 11:26:40
s/RuntimeException/IllegalStateException/g
perkj_webrtc
2015/09/28 07:22:47
Done.
|
| + } |
| + 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. |
| @@ -113,41 +123,35 @@ public final class SurfaceTextureHelper { |
| } |
| /** |
| - * Call this function to signal that you are done with the frame received in |
| - * onTextureFrameAvailable(). Only one texture frame can be in flight at once, so you must call |
| - * this function in order to receive a new frame. |
| - */ |
| - public void returnTextureFrame() { |
| - handler.post(new Runnable() { |
| - @Override public void run() { |
| - isTextureInUse = false; |
| - if (isQuitting) { |
| - release(); |
| - } else { |
| - tryDeliverTextureFrame(); |
| - } |
| - } |
| - }); |
| - } |
| - |
| - /** |
| - * 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 textureFrame have been returned by a call to returnTextureFrame. |
|
magjed_webrtc
2015/09/27 11:26:40
s/textureFrame/texture frame/g.
s/have/has/g.
s/to
perkj_webrtc
2015/09/28 07:22:47
Done.
|
| + * 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(); |
|
magjed_webrtc
2015/09/27 11:26:40
This is duplicated boilerplate code from ThreadUti
perkj_webrtc
2015/09/28 07:22:47
ok, either land yours first or maybe you can refac
|
| + 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(); |
| } |
| } |
| @@ -185,4 +189,22 @@ public final class SurfaceTextureHelper { |
| // Quit safely to make sure the clean-up posted above is executed. |
| thread.quitSafely(); |
| } |
| + |
| + /** |
| + * Call this function to signal that you are done with the frame received in |
| + * onTextureFrameAvailable(). Only one texture frame can be in flight at once, so you must call |
| + * this function in order to receive a new frame. |
| + */ |
| + public void returnTextureFrame() { |
|
magjed_webrtc
2015/09/27 11:26:40
Why have you moved this public method below the pr
perkj_webrtc
2015/09/28 07:22:47
Done.
|
| + handler.post(new Runnable() { |
| + @Override public void run() { |
| + isTextureInUse = false; |
| + if (isQuitting) { |
| + release(); |
| + } else { |
| + tryDeliverTextureFrame(); |
| + } |
| + } |
| + }); |
| + } |
| } |