| 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 b4e687f79e1e75606258f014a4388ffb0c9fdef4..28404c9d6f13782562dd3d2c635e2a8a5e7defa4 100644
|
| --- a/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java
|
| +++ b/talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java
|
| @@ -91,6 +91,8 @@ public class SurfaceViewRenderer extends SurfaceView
|
| // layout and surface size.
|
| private int surfaceWidth;
|
| private int surfaceHeight;
|
| + // |isSurfaceCreated| keeps track of the current status in surfaceCreated()/surfaceDestroyed().
|
| + private boolean isSurfaceCreated;
|
| // Last rendered frame dimensions, or 0 if no frame has been rendered yet.
|
| private int frameWidth;
|
| private int frameHeight;
|
| @@ -128,6 +130,7 @@ public class SurfaceViewRenderer extends SurfaceView
|
| */
|
| public SurfaceViewRenderer(Context context) {
|
| super(context);
|
| + getHolder().addCallback(this);
|
| }
|
|
|
| /**
|
| @@ -135,24 +138,48 @@ public class SurfaceViewRenderer extends SurfaceView
|
| */
|
| public SurfaceViewRenderer(Context context, AttributeSet attrs) {
|
| super(context, attrs);
|
| + getHolder().addCallback(this);
|
| }
|
|
|
| /**
|
| - * Initialize this class, sharing resources with |sharedContext|.
|
| + * Initialize this class, sharing resources with |sharedContext|. It is allowed to call init() to
|
| + * reinitialize the renderer after a previous init()/release() cycle.
|
| */
|
| public void init(
|
| EGLContext sharedContext, RendererCommon.RendererEvents rendererEvents) {
|
| - if (renderThreadHandler != null) {
|
| - throw new IllegalStateException("Already initialized");
|
| + synchronized (handlerLock) {
|
| + if (renderThreadHandler != null) {
|
| + throw new IllegalStateException("Already initialized");
|
| + }
|
| + Logging.d(TAG, "Initializing");
|
| + this.rendererEvents = rendererEvents;
|
| + renderThread = new HandlerThread(TAG);
|
| + renderThread.start();
|
| + drawer = new GlRectDrawer();
|
| + eglBase = new EglBase(sharedContext, EglBase.ConfigType.PLAIN);
|
| + renderThreadHandler = new Handler(renderThread.getLooper());
|
| }
|
| - Logging.d(TAG, "Initializing");
|
| - this.rendererEvents = rendererEvents;
|
| - renderThread = new HandlerThread(TAG);
|
| - renderThread.start();
|
| - renderThreadHandler = new Handler(renderThread.getLooper());
|
| - eglBase = new EglBase(sharedContext, EglBase.ConfigType.PLAIN);
|
| - drawer = new GlRectDrawer();
|
| - getHolder().addCallback(this);
|
| + tryCreateEglSurface();
|
| + }
|
| +
|
| + /**
|
| + * Create and make an EGLSurface current if both init() and surfaceCreated() have been called.
|
| + */
|
| + public void tryCreateEglSurface() {
|
| + // |renderThreadHandler| is only created after |eglBase| is created in init(), so the
|
| + // following code will only execute if eglBase != null.
|
| + runOnRenderThread(new Runnable() {
|
| + @Override public void run() {
|
| + synchronized (layoutLock) {
|
| + if (isSurfaceCreated) {
|
| + eglBase.createSurface(getHolder().getSurface());
|
| + eglBase.makeCurrent();
|
| + // Necessary for YUV frames with odd width.
|
| + GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
|
| + }
|
| + }
|
| + }
|
| + });
|
| }
|
|
|
| /**
|
| @@ -179,6 +206,9 @@ public class SurfaceViewRenderer extends SurfaceView
|
| GLES20.glDeleteTextures(3, yuvTextures, 0);
|
| yuvTextures = null;
|
| }
|
| + // Clear last rendered image to black.
|
| + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
|
| + eglBase.swapBuffers();
|
| eglBase.release();
|
| eglBase = null;
|
| }
|
| @@ -197,6 +227,20 @@ public class SurfaceViewRenderer extends SurfaceView
|
| // The |renderThread| cleanup is not safe to cancel and we need to wait until it's done.
|
| ThreadUtils.joinUninterruptibly(renderThread);
|
| renderThread = null;
|
| + // Reset statistics and event reporting.
|
| + synchronized (layoutLock) {
|
| + frameWidth = 0;
|
| + frameHeight = 0;
|
| + frameRotation = 0;
|
| + rendererEvents = null;
|
| + }
|
| + synchronized (statisticsLock) {
|
| + framesReceived = 0;
|
| + framesDropped = 0;
|
| + framesRendered = 0;
|
| + firstFrameTimeNs = 0;
|
| + renderTimeNs = 0;
|
| + }
|
| }
|
|
|
| /**
|
| @@ -286,20 +330,17 @@ public class SurfaceViewRenderer extends SurfaceView
|
| @Override
|
| public void surfaceCreated(final SurfaceHolder holder) {
|
| Logging.d(TAG, "Surface created");
|
| - runOnRenderThread(new Runnable() {
|
| - @Override public void run() {
|
| - eglBase.createSurface(holder.getSurface());
|
| - eglBase.makeCurrent();
|
| - // Necessary for YUV frames with odd width.
|
| - GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
|
| - }
|
| - });
|
| + synchronized (layoutLock) {
|
| + isSurfaceCreated = true;
|
| + }
|
| + tryCreateEglSurface();
|
| }
|
|
|
| @Override
|
| public void surfaceDestroyed(SurfaceHolder holder) {
|
| Logging.d(TAG, "Surface destroyed");
|
| synchronized (layoutLock) {
|
| + isSurfaceCreated = false;
|
| surfaceWidth = 0;
|
| surfaceHeight = 0;
|
| }
|
|
|