Android SurfaceTextureHelper: Don't wait for pending frames in disconnect()
This CL also makes some small non-functional changes in ThreadUtils and EglBase to support SurfaceTextures and SurfaceTextureHelper. BUG=webrtc:4993 R=hbos@webrtc.org Review URL: https://codereview.webrtc.org/1368093003 . Cr-Commit-Position: refs/heads/master@{#10085}
This commit is contained in:
@ -27,6 +27,7 @@
|
||||
|
||||
package org.webrtc;
|
||||
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.opengl.EGL14;
|
||||
import android.opengl.EGLConfig;
|
||||
import android.opengl.EGLContext;
|
||||
@ -85,6 +86,19 @@ public final class EglBase {
|
||||
|
||||
// Create EGLSurface from the Android Surface.
|
||||
public void createSurface(Surface surface) {
|
||||
createSurfaceInternal(surface);
|
||||
}
|
||||
|
||||
// Create EGLSurface from the Android SurfaceTexture.
|
||||
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");
|
||||
|
@ -35,7 +35,6 @@ import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -159,20 +158,7 @@ final class SurfaceTextureHelper {
|
||||
}
|
||||
}
|
||||
});
|
||||
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();
|
||||
}
|
||||
ThreadUtils.awaitUninterruptibly(barrier);
|
||||
}
|
||||
|
||||
private void tryDeliverTextureFrame() {
|
||||
@ -195,18 +181,15 @@ final class SurfaceTextureHelper {
|
||||
}
|
||||
|
||||
private void release() {
|
||||
if (Thread.currentThread() != thread) {
|
||||
throw new IllegalStateException("Wrong thread.");
|
||||
}
|
||||
if (isTextureInUse || !isQuitting) {
|
||||
throw new IllegalStateException("Unexpected release.");
|
||||
}
|
||||
// Release GL resources on dedicated thread.
|
||||
handler.post(new Runnable() {
|
||||
@Override public void run() {
|
||||
GLES20.glDeleteTextures(1, new int[] {oesTextureId}, 0);
|
||||
surfaceTexture.release();
|
||||
eglBase.release();
|
||||
}
|
||||
});
|
||||
// Quit safely to make sure the clean-up posted above is executed.
|
||||
GLES20.glDeleteTextures(1, new int[] {oesTextureId}, 0);
|
||||
surfaceTexture.release();
|
||||
eglBase.release();
|
||||
thread.quitSafely();
|
||||
}
|
||||
}
|
||||
|
@ -27,20 +27,32 @@
|
||||
|
||||
package org.webrtc;
|
||||
|
||||
public class ThreadUtils {
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
final class ThreadUtils {
|
||||
/**
|
||||
* Helper function to make sure a thread is joined without getting interrupted. This should be
|
||||
* used in cases where |thread| is doing some critical work, e.g. cleanup, that must complete
|
||||
* before returning. The thread interruption flag is set if an interrupt occurs during join().
|
||||
* Utility interface to be used with executeUninterruptibly() to wait for blocking operations
|
||||
* to complete without getting interrupted..
|
||||
*/
|
||||
public static void joinUninterruptibly(Thread thread) {
|
||||
public interface BlockingOperation {
|
||||
void run() throws InterruptedException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to make sure a blocking operation is executed to completion without getting
|
||||
* interrupted. This should be used in cases where the operation is waiting for some critical
|
||||
* work, e.g. cleanup, that must complete before returning. If the thread is interrupted during
|
||||
* the blocking operation, this function will re-run the operation until completion, and only then
|
||||
* re-interrupt the thread.
|
||||
*/
|
||||
public static void executeUninterruptibly(BlockingOperation operation) {
|
||||
boolean wasInterrupted = false;
|
||||
while (true) {
|
||||
try {
|
||||
thread.join();
|
||||
operation.run();
|
||||
break;
|
||||
} catch (InterruptedException e) {
|
||||
// Someone is asking us to return early at our convenience. We can't cancel this join(),
|
||||
// Someone is asking us to return early at our convenience. We can't cancel this operation,
|
||||
// but we should preserve the information and pass it along.
|
||||
wasInterrupted = true;
|
||||
}
|
||||
@ -50,4 +62,22 @@ public class ThreadUtils {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
public static void joinUninterruptibly(final Thread thread) {
|
||||
executeUninterruptibly(new BlockingOperation() {
|
||||
@Override
|
||||
public void run() throws InterruptedException {
|
||||
thread.join();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void awaitUninterruptibly(final CountDownLatch latch) {
|
||||
executeUninterruptibly(new BlockingOperation() {
|
||||
@Override
|
||||
public void run() throws InterruptedException {
|
||||
latch.await();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user