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

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

Issue 1273803002: Android VideoRendererGui: Add dispose function (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: rebase Created 5 years, 4 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 | talk/app/webrtc/java/src/org/webrtc/VideoRenderer.java » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java
diff --git a/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java b/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java
index 26285252f3a9bac244cbe09083ec0611ebd6c2e8..9dd2f02c4bd2aff331724f175259de4e071644dd 100644
--- a/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java
+++ b/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java
@@ -55,6 +55,8 @@ import org.webrtc.VideoRenderer.I420Frame;
* Only one instance of the class can be created.
*/
public class VideoRendererGui implements GLSurfaceView.Renderer {
+ // |instance|, |instance.surface|, |eglContext|, and |eglContextReady| are synchronized on
+ // |VideoRendererGui.class|.
private static VideoRendererGui instance = null;
private static Runnable eglContextReady = null;
private static final String TAG = "VideoRendererGui";
@@ -68,7 +70,8 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
private int screenWidth;
private int screenHeight;
// List of yuv renderers.
- private ArrayList<YuvImageRenderer> yuvImageRenderers;
+ private final ArrayList<YuvImageRenderer> yuvImageRenderers;
+ // |drawer| is synchronized on |yuvImageRenderers|.
private GlRectDrawer drawer;
// The minimum fraction of the frame content that will be shown for |SCALE_ASPECT_BALANCED|.
// This limits excessive cropping when adjusting display size.
@@ -101,12 +104,32 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
yuvImageRenderers = new ArrayList<YuvImageRenderer>();
}
+ public static synchronized void dispose() {
+ if (instance == null){
+ return;
+ }
+ synchronized (instance.yuvImageRenderers) {
+ for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) {
+ yuvImageRenderer.release();
+ }
+ instance.yuvImageRenderers.clear();
+ if (instance.drawer != null) {
+ instance.drawer.release();
+ }
+ }
+ instance.surface = null;
+ instance.eglContext = null;
+ instance.eglContextReady = null;
+ instance = null;
+ }
+
/**
* Class used to display stream of YUV420 frames at particular location
* on a screen. New video frames are sent to display using renderFrame()
* call.
*/
private static class YuvImageRenderer implements VideoRenderer.Callbacks {
+ // |surface| is synchronized on |this|.
private GLSurfaceView surface;
private int id;
private int[] yuvTextures = { -1, -1, -1 };
@@ -116,8 +139,8 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
// an offer (writing I420Frame to render) and early-returns (recording
// a dropped frame) if that queue is full. draw() call does a peek(),
// copies frame to texture and then removes it from a queue using poll().
- LinkedBlockingQueue<I420Frame> frameToRenderQueue;
- // Local copy of incoming video frame.
+ private final LinkedBlockingQueue<I420Frame> frameToRenderQueue;
+ // Local copy of incoming video frame. Synchronized on |frameToRenderQueue|.
private I420Frame yuvFrameToRender;
private I420Frame textureFrameToRender;
// Type of video frame used for recent frame rendering.
@@ -178,6 +201,15 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
rotationDegree = 0;
}
+ private synchronized void release() {
+ surface = null;
+ synchronized (frameToRenderQueue) {
+ frameToRenderQueue.clear();
+ yuvFrameToRender = null;
+ textureFrameToRender = null;
+ }
+ }
+
private void createTextures() {
Log.d(TAG, " YuvImageRenderer.createTextures " + id + " on GL thread:" +
Thread.currentThread().getId());
@@ -425,46 +457,52 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
@Override
public synchronized void renderFrame(I420Frame frame) {
+ if (surface == null) {
+ // This object has been released.
+ return;
+ }
setSize(frame.width, frame.height, frame.rotationDegree);
long now = System.nanoTime();
framesReceived++;
- // Skip rendering of this frame if setSize() was not called.
- if (yuvFrameToRender == null || textureFrameToRender == null) {
- framesDropped++;
- return;
- }
- // Check input frame parameters.
- if (frame.yuvFrame) {
- if (frame.yuvStrides[0] < frame.width ||
- frame.yuvStrides[1] < frame.width / 2 ||
- frame.yuvStrides[2] < frame.width / 2) {
- Log.e(TAG, "Incorrect strides " + frame.yuvStrides[0] + ", " +
- frame.yuvStrides[1] + ", " + frame.yuvStrides[2]);
+ synchronized (frameToRenderQueue) {
+ // Skip rendering of this frame if setSize() was not called.
+ if (yuvFrameToRender == null || textureFrameToRender == null) {
+ framesDropped++;
return;
}
- // Check incoming frame dimensions.
- if (frame.width != yuvFrameToRender.width ||
- frame.height != yuvFrameToRender.height) {
- throw new RuntimeException("Wrong frame size " +
- frame.width + " x " + frame.height);
+ // Check input frame parameters.
+ if (frame.yuvFrame) {
+ if (frame.yuvStrides[0] < frame.width ||
+ frame.yuvStrides[1] < frame.width / 2 ||
+ frame.yuvStrides[2] < frame.width / 2) {
+ Log.e(TAG, "Incorrect strides " + frame.yuvStrides[0] + ", " +
+ frame.yuvStrides[1] + ", " + frame.yuvStrides[2]);
+ return;
+ }
+ // Check incoming frame dimensions.
+ if (frame.width != yuvFrameToRender.width ||
+ frame.height != yuvFrameToRender.height) {
+ throw new RuntimeException("Wrong frame size " +
+ frame.width + " x " + frame.height);
+ }
}
- }
- if (frameToRenderQueue.size() > 0) {
- // Skip rendering of this frame if previous frame was not rendered yet.
- framesDropped++;
- return;
- }
+ if (frameToRenderQueue.size() > 0) {
+ // Skip rendering of this frame if previous frame was not rendered yet.
+ framesDropped++;
+ return;
+ }
- // Create a local copy of the frame.
- if (frame.yuvFrame) {
- yuvFrameToRender.copyFrom(frame);
- rendererType = RendererType.RENDERER_YUV;
- frameToRenderQueue.offer(yuvFrameToRender);
- } else {
- textureFrameToRender.copyFrom(frame);
- rendererType = RendererType.RENDERER_TEXTURE;
- frameToRenderQueue.offer(textureFrameToRender);
+ // Create a local copy of the frame.
+ if (frame.yuvFrame) {
+ yuvFrameToRender.copyFrom(frame);
+ rendererType = RendererType.RENDERER_YUV;
+ frameToRenderQueue.offer(yuvFrameToRender);
+ } else {
+ textureFrameToRender.copyFrom(frame);
+ rendererType = RendererType.RENDERER_TEXTURE;
+ frameToRenderQueue.offer(textureFrameToRender);
+ }
}
copyTimeNs += (System.nanoTime() - now);
seenFrame = true;
@@ -481,14 +519,14 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
}
/** Passes GLSurfaceView to video renderer. */
- public static void setView(GLSurfaceView surface,
+ public static synchronized void setView(GLSurfaceView surface,
Runnable eglContextReadyCallback) {
Log.d(TAG, "VideoRendererGui.setView");
instance = new VideoRendererGui(surface);
eglContextReady = eglContextReadyCallback;
}
- public static EGLContext getEGLContext() {
+ public static synchronized EGLContext getEGLContext() {
return eglContext;
}
@@ -514,7 +552,7 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
* resolution (width, height). All parameters are in percentage of
* screen resolution.
*/
- public static YuvImageRenderer create(int x, int y, int width, int height,
+ public static synchronized YuvImageRenderer create(int x, int y, int width, int height,
ScalingType scalingType, boolean mirror) {
// Check display region parameters.
if (x < 0 || x > 100 || y < 0 || y > 100 ||
@@ -557,7 +595,7 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
return yuvImageRenderer;
}
- public static void update(
+ public static synchronized void update(
VideoRenderer.Callbacks renderer,
int x, int y, int width, int height, ScalingType scalingType, boolean mirror) {
Log.d(TAG, "VideoRendererGui.update");
@@ -574,15 +612,18 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
}
}
- public static void remove(VideoRenderer.Callbacks renderer) {
+ public static synchronized void remove(VideoRenderer.Callbacks renderer) {
Log.d(TAG, "VideoRendererGui.remove");
if (instance == null) {
throw new RuntimeException(
"Attempt to remove yuv renderer before setting GLSurfaceView");
}
synchronized (instance.yuvImageRenderers) {
- if (!instance.yuvImageRenderers.remove(renderer)) {
+ final int index = instance.yuvImageRenderers.indexOf(renderer);
+ if (index == -1) {
Log.w(TAG, "Couldn't remove renderer (not present in current list)");
+ } else {
+ instance.yuvImageRenderers.remove(index).release();
}
}
}
@@ -593,14 +634,15 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
Log.d(TAG, "VideoRendererGui.onSurfaceCreated");
// Store render EGL context.
if (CURRENT_SDK_VERSION >= EGL14_SDK_VERSION) {
- eglContext = EGL14.eglGetCurrentContext();
- Log.d(TAG, "VideoRendererGui EGL Context: " + eglContext);
+ synchronized (VideoRendererGui.class) {
+ eglContext = EGL14.eglGetCurrentContext();
+ Log.d(TAG, "VideoRendererGui EGL Context: " + eglContext);
+ }
}
- // Create drawer for YUV/OES frames.
- drawer = new GlRectDrawer();
-
synchronized (yuvImageRenderers) {
+ // Create drawer for YUV/OES frames.
+ drawer = new GlRectDrawer();
// Create textures for all images.
for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) {
yuvImageRenderer.createTextures();
@@ -612,8 +654,10 @@ public class VideoRendererGui implements GLSurfaceView.Renderer {
GLES20.glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
// Fire EGL context ready event.
- if (eglContextReady != null) {
- eglContextReady.run();
+ synchronized (VideoRendererGui.class) {
+ if (eglContextReady != null) {
+ eglContextReady.run();
+ }
}
}
« no previous file with comments | « no previous file | talk/app/webrtc/java/src/org/webrtc/VideoRenderer.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698