 Chromium Code Reviews
 Chromium Code Reviews Issue 1366413003:
  Add C++ SurfaceTextureHandler  (Closed) 
  Base URL: https://chromium.googlesource.com/external/webrtc.git@master
    
  
    Issue 1366413003:
  Add C++ SurfaceTextureHandler  (Closed) 
  Base URL: https://chromium.googlesource.com/external/webrtc.git@master| 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(); | 
| + } | 
| + } | 
| + }); | 
| + } | 
| } |