Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(370)

Unified Diff: talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java

Issue 1354393002: Android SurfaceViewRenderer: Block in release() until frames are returned and cleanup is done (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Add comments about interrupt flag Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java
diff --git a/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java b/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java
index fe3300c85f6dfdce1f1a11ca615ed2a3145e9b48..7e56e700c2e6f62acbb4bb4bc7f12d7b09d67ea1 100644
--- a/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java
+++ b/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java
@@ -54,11 +54,11 @@ public class SurfaceViewRenderer extends SurfaceView
implements SurfaceHolder.Callback, VideoRenderer.Callbacks {
private static final String TAG = "SurfaceViewRenderer";
- // These variables are synchronized on |threadLock|.
- private final Object threadLock = new Object();
// Dedicated render thread.
private HandlerThread renderThread;
- // Handler for inter-thread communication.
+ // |renderThreadHandler| is a handler for communicating with |renderThread|, and is synchronized
+ // on |handlerLock|.
+ private final Object handlerLock = new Object();
private Handler renderThreadHandler;
// EGL and GL resources for drawing YUV/OES textures. After initilization, these are only accessed
@@ -156,11 +156,13 @@ public class SurfaceViewRenderer extends SurfaceView
}
/**
- * Release all resources. This needs to be done manually, otherwise the resources are leaked. You
- * should call this before the Activity is destroyed, while the EGLContext is still valid.
+ * Block until any pending frame is returned and all GL resources released, even if an interrupt
+ * occurs. If an interrupt occurs during release(), the interrupt flag will be set. This function
+ * should be called before the Activity is destroyed and the EGLContext is still valid. If you
+ * don't call this function, the GL resources might leak.
*/
public void release() {
- synchronized (threadLock) {
+ synchronized (handlerLock) {
if (renderThreadHandler == null) {
Logging.d(TAG, "Already released");
return;
@@ -169,7 +171,7 @@ public class SurfaceViewRenderer extends SurfaceView
// TODO(magjed): This might not be necessary - all OpenGL resources are automatically deleted
// when the EGL context is lost. It might be dangerous to delete them manually in
// Activity.onDestroy().
- renderThreadHandler.post(new Runnable() {
+ renderThreadHandler.postAtFrontOfQueue(new Runnable() {
@Override public void run() {
drawer.release();
drawer = null;
@@ -181,19 +183,35 @@ public class SurfaceViewRenderer extends SurfaceView
eglBase = null;
}
});
- // Don't accept any more messages to the render thread.
+ // Don't accept any more frames or messages to the render thread.
renderThreadHandler = null;
- // Quit safely to make sure the EGL/GL cleanup posted above is executed.
- renderThread.quitSafely();
- renderThread = null;
}
- getHolder().removeCallback(this);
+ // Quit safely to make sure the EGL/GL cleanup posted above is executed.
+ renderThread.quitSafely();
synchronized (frameLock) {
if (pendingFrame != null) {
VideoRenderer.renderFrameDone(pendingFrame);
pendingFrame = null;
}
}
+ // The |renderThread| cleanup is not safe to cancel and we need to wait until it's done.
+ boolean wasInterrupted = false;
+ while (true) {
+ try {
+ renderThread.join();
+ renderThread = null;
+ break;
+ } catch (InterruptedException e) {
+ // Someone is asking us to return early at our convenience. We can't cancel this cleanup,
+ // but we should preserve the information and pass it along. Any rendering in progress
+ // should complete in a few ms.
+ wasInterrupted = true;
+ }
+ }
+ // Pass interruption information along.
+ if (wasInterrupted) {
+ Thread.currentThread().interrupt();
+ }
}
/**
@@ -220,7 +238,7 @@ public class SurfaceViewRenderer extends SurfaceView
synchronized (statisticsLock) {
++framesReceived;
}
- synchronized (threadLock) {
+ synchronized (handlerLock) {
if (renderThreadHandler == null) {
Logging.d(TAG, "Dropping frame - SurfaceViewRenderer not initialized or already released.");
} else {
@@ -322,7 +340,7 @@ public class SurfaceViewRenderer extends SurfaceView
* Private helper function to post tasks safely.
*/
private void runOnRenderThread(Runnable runnable) {
- synchronized (threadLock) {
+ synchronized (handlerLock) {
if (renderThreadHandler != null) {
renderThreadHandler.post(runnable);
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698