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

Side by Side Diff: talk/app/webrtc/java/android/org/webrtc/SurfaceViewRenderer.java

Issue 1389203003: Android SurfaceViewRenderer: Allow to re-init after release() has been called (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Move init check first Created 5 years, 2 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2015 Google Inc. 3 * Copyright 2015 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 // Current size on screen in pixels. Updated in onLayout(), and should be cons istent with 84 // Current size on screen in pixels. Updated in onLayout(), and should be cons istent with
85 // |widthSpec|/|heightSpec| after that. 85 // |widthSpec|/|heightSpec| after that.
86 private int layoutWidth; 86 private int layoutWidth;
87 private int layoutHeight; 87 private int layoutHeight;
88 // Current surface size of the underlying Surface. Updated in surfaceChanged() , and should be 88 // Current surface size of the underlying Surface. Updated in surfaceChanged() , and should be
89 // consistent with |layoutWidth|/|layoutHeight| after that. 89 // consistent with |layoutWidth|/|layoutHeight| after that.
90 // TODO(magjed): Enable hardware scaler with SurfaceHolder.setFixedSize(). Thi s will decouple 90 // TODO(magjed): Enable hardware scaler with SurfaceHolder.setFixedSize(). Thi s will decouple
91 // layout and surface size. 91 // layout and surface size.
92 private int surfaceWidth; 92 private int surfaceWidth;
93 private int surfaceHeight; 93 private int surfaceHeight;
94 // |isSurfaceCreated| keeps track of the current status in surfaceCreated()/su rfaceDestroyed().
95 private boolean isSurfaceCreated;
94 // Last rendered frame dimensions, or 0 if no frame has been rendered yet. 96 // Last rendered frame dimensions, or 0 if no frame has been rendered yet.
95 private int frameWidth; 97 private int frameWidth;
96 private int frameHeight; 98 private int frameHeight;
97 private int frameRotation; 99 private int frameRotation;
98 // |scalingType| determines how the video will fill the allowed layout area in onMeasure(). 100 // |scalingType| determines how the video will fill the allowed layout area in onMeasure().
99 private RendererCommon.ScalingType scalingType = RendererCommon.ScalingType.SC ALE_ASPECT_BALANCED; 101 private RendererCommon.ScalingType scalingType = RendererCommon.ScalingType.SC ALE_ASPECT_BALANCED;
100 // If true, mirrors the video stream horizontally. 102 // If true, mirrors the video stream horizontally.
101 private boolean mirror; 103 private boolean mirror;
102 // Callback for reporting renderer events. 104 // Callback for reporting renderer events.
103 private RendererCommon.RendererEvents rendererEvents; 105 private RendererCommon.RendererEvents rendererEvents;
(...skipping 17 matching lines...) Expand all
121 @Override public void run() { 123 @Override public void run() {
122 renderFrameOnRenderThread(); 124 renderFrameOnRenderThread();
123 } 125 }
124 }; 126 };
125 127
126 /** 128 /**
127 * Standard View constructor. In order to render something, you must first cal l init(). 129 * Standard View constructor. In order to render something, you must first cal l init().
128 */ 130 */
129 public SurfaceViewRenderer(Context context) { 131 public SurfaceViewRenderer(Context context) {
130 super(context); 132 super(context);
133 getHolder().addCallback(this);
131 } 134 }
132 135
133 /** 136 /**
134 * Standard View constructor. In order to render something, you must first cal l init(). 137 * Standard View constructor. In order to render something, you must first cal l init().
135 */ 138 */
136 public SurfaceViewRenderer(Context context, AttributeSet attrs) { 139 public SurfaceViewRenderer(Context context, AttributeSet attrs) {
137 super(context, attrs); 140 super(context, attrs);
138 }
139
140 /**
141 * Initialize this class, sharing resources with |sharedContext|.
142 */
143 public void init(
144 EGLContext sharedContext, RendererCommon.RendererEvents rendererEvents) {
145 if (renderThreadHandler != null) {
146 throw new IllegalStateException("Already initialized");
147 }
148 Logging.d(TAG, "Initializing");
149 this.rendererEvents = rendererEvents;
150 renderThread = new HandlerThread(TAG);
151 renderThread.start();
152 renderThreadHandler = new Handler(renderThread.getLooper());
153 eglBase = new EglBase(sharedContext, EglBase.ConfigType.PLAIN);
154 drawer = new GlRectDrawer();
155 getHolder().addCallback(this); 141 getHolder().addCallback(this);
156 } 142 }
157 143
158 /** 144 /**
145 * Initialize this class, sharing resources with |sharedContext|. It is allowe d to call init() to
146 * reinitialize the renderer after a previous init()/release() cycle.
147 */
148 public void init(
149 EGLContext sharedContext, RendererCommon.RendererEvents rendererEvents) {
150 synchronized (handlerLock) {
151 if (renderThreadHandler != null) {
152 throw new IllegalStateException("Already initialized");
153 }
154 Logging.d(TAG, "Initializing");
155 this.rendererEvents = rendererEvents;
156 renderThread = new HandlerThread(TAG);
157 renderThread.start();
158 drawer = new GlRectDrawer();
159 eglBase = new EglBase(sharedContext, EglBase.ConfigType.PLAIN);
160 renderThreadHandler = new Handler(renderThread.getLooper());
161 }
162 tryCreateEglSurface();
163 }
164
165 /**
166 * Create and make an EGLSurface current if both init() and surfaceCreated() h ave been called.
167 */
168 public void tryCreateEglSurface() {
169 // |renderThreadHandler| is only created after |eglBase| is created in init( ), so the
170 // following code will only execute if eglBase != null.
171 runOnRenderThread(new Runnable() {
172 @Override public void run() {
173 synchronized (layoutLock) {
174 if (isSurfaceCreated) {
175 eglBase.createSurface(getHolder().getSurface());
176 eglBase.makeCurrent();
177 // Necessary for YUV frames with odd width.
178 GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
179 }
180 }
181 }
182 });
183 }
184
185 /**
159 * Block until any pending frame is returned and all GL resources released, ev en if an interrupt 186 * Block until any pending frame is returned and all GL resources released, ev en if an interrupt
160 * occurs. If an interrupt occurs during release(), the interrupt flag will be set. This function 187 * occurs. If an interrupt occurs during release(), the interrupt flag will be set. This function
161 * should be called before the Activity is destroyed and the EGLContext is sti ll valid. If you 188 * should be called before the Activity is destroyed and the EGLContext is sti ll valid. If you
162 * don't call this function, the GL resources might leak. 189 * don't call this function, the GL resources might leak.
163 */ 190 */
164 public void release() { 191 public void release() {
165 synchronized (handlerLock) { 192 synchronized (handlerLock) {
166 if (renderThreadHandler == null) { 193 if (renderThreadHandler == null) {
167 Logging.d(TAG, "Already released"); 194 Logging.d(TAG, "Already released");
168 return; 195 return;
169 } 196 }
170 // Release EGL and GL resources on render thread. 197 // Release EGL and GL resources on render thread.
171 // TODO(magjed): This might not be necessary - all OpenGL resources are au tomatically deleted 198 // TODO(magjed): This might not be necessary - all OpenGL resources are au tomatically deleted
172 // when the EGL context is lost. It might be dangerous to delete them manu ally in 199 // when the EGL context is lost. It might be dangerous to delete them manu ally in
173 // Activity.onDestroy(). 200 // Activity.onDestroy().
174 renderThreadHandler.postAtFrontOfQueue(new Runnable() { 201 renderThreadHandler.postAtFrontOfQueue(new Runnable() {
175 @Override public void run() { 202 @Override public void run() {
176 drawer.release(); 203 drawer.release();
177 drawer = null; 204 drawer = null;
178 if (yuvTextures != null) { 205 if (yuvTextures != null) {
179 GLES20.glDeleteTextures(3, yuvTextures, 0); 206 GLES20.glDeleteTextures(3, yuvTextures, 0);
180 yuvTextures = null; 207 yuvTextures = null;
181 } 208 }
209 // Clear last rendered image to black.
210 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
211 eglBase.swapBuffers();
182 eglBase.release(); 212 eglBase.release();
183 eglBase = null; 213 eglBase = null;
184 } 214 }
185 }); 215 });
186 // Don't accept any more frames or messages to the render thread. 216 // Don't accept any more frames or messages to the render thread.
187 renderThreadHandler = null; 217 renderThreadHandler = null;
188 } 218 }
189 // Quit safely to make sure the EGL/GL cleanup posted above is executed. 219 // Quit safely to make sure the EGL/GL cleanup posted above is executed.
190 renderThread.quitSafely(); 220 renderThread.quitSafely();
191 synchronized (frameLock) { 221 synchronized (frameLock) {
192 if (pendingFrame != null) { 222 if (pendingFrame != null) {
193 VideoRenderer.renderFrameDone(pendingFrame); 223 VideoRenderer.renderFrameDone(pendingFrame);
194 pendingFrame = null; 224 pendingFrame = null;
195 } 225 }
196 } 226 }
197 // The |renderThread| cleanup is not safe to cancel and we need to wait unti l it's done. 227 // The |renderThread| cleanup is not safe to cancel and we need to wait unti l it's done.
198 ThreadUtils.joinUninterruptibly(renderThread); 228 ThreadUtils.joinUninterruptibly(renderThread);
199 renderThread = null; 229 renderThread = null;
230 // Reset statistics and event reporting.
231 synchronized (layoutLock) {
232 frameWidth = 0;
233 frameHeight = 0;
234 frameRotation = 0;
235 rendererEvents = null;
236 }
237 synchronized (statisticsLock) {
238 framesReceived = 0;
239 framesDropped = 0;
240 framesRendered = 0;
241 firstFrameTimeNs = 0;
242 renderTimeNs = 0;
243 }
200 } 244 }
201 245
202 /** 246 /**
203 * Set if the video stream should be mirrored or not. 247 * Set if the video stream should be mirrored or not.
204 */ 248 */
205 public void setMirror(final boolean mirror) { 249 public void setMirror(final boolean mirror) {
206 synchronized (layoutLock) { 250 synchronized (layoutLock) {
207 this.mirror = mirror; 251 this.mirror = mirror;
208 } 252 }
209 } 253 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 layoutHeight = bottom - top; 323 layoutHeight = bottom - top;
280 } 324 }
281 // Might have a pending frame waiting for a layout of correct size. 325 // Might have a pending frame waiting for a layout of correct size.
282 runOnRenderThread(renderFrameRunnable); 326 runOnRenderThread(renderFrameRunnable);
283 } 327 }
284 328
285 // SurfaceHolder.Callback interface. 329 // SurfaceHolder.Callback interface.
286 @Override 330 @Override
287 public void surfaceCreated(final SurfaceHolder holder) { 331 public void surfaceCreated(final SurfaceHolder holder) {
288 Logging.d(TAG, "Surface created"); 332 Logging.d(TAG, "Surface created");
289 runOnRenderThread(new Runnable() { 333 synchronized (layoutLock) {
290 @Override public void run() { 334 isSurfaceCreated = true;
291 eglBase.createSurface(holder.getSurface()); 335 }
292 eglBase.makeCurrent(); 336 tryCreateEglSurface();
293 // Necessary for YUV frames with odd width.
294 GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
295 }
296 });
297 } 337 }
298 338
299 @Override 339 @Override
300 public void surfaceDestroyed(SurfaceHolder holder) { 340 public void surfaceDestroyed(SurfaceHolder holder) {
301 Logging.d(TAG, "Surface destroyed"); 341 Logging.d(TAG, "Surface destroyed");
302 synchronized (layoutLock) { 342 synchronized (layoutLock) {
343 isSurfaceCreated = false;
303 surfaceWidth = 0; 344 surfaceWidth = 0;
304 surfaceHeight = 0; 345 surfaceHeight = 0;
305 } 346 }
306 runOnRenderThread(new Runnable() { 347 runOnRenderThread(new Runnable() {
307 @Override public void run() { 348 @Override public void run() {
308 eglBase.releaseSurface(); 349 eglBase.releaseSurface();
309 } 350 }
310 }); 351 });
311 } 352 }
312 353
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 return; 426 return;
386 } 427 }
387 frame = pendingFrame; 428 frame = pendingFrame;
388 pendingFrame = null; 429 pendingFrame = null;
389 } 430 }
390 431
391 final long startTimeNs = System.nanoTime(); 432 final long startTimeNs = System.nanoTime();
392 final float[] texMatrix; 433 final float[] texMatrix;
393 synchronized (layoutLock) { 434 synchronized (layoutLock) {
394 final float[] rotatedSamplingMatrix = 435 final float[] rotatedSamplingMatrix =
395 RendererCommon.rotateTextureMatrix(frame.samplingMatrix, frame.rotatio nDegree); 436 RendererCommon.rotateTextureMatrix(frame.samplingMatrix, frame.rotatio nDegree);
hbos 2015/10/08 11:19:35 Is this diff here a merge diff or cleanup? Woah on
magjed_webrtc 2015/10/08 12:44:43 You see unrelated rebase stuff when you diff patch
396 final float[] layoutMatrix = RendererCommon.getLayoutMatrix( 437 final float[] layoutMatrix = RendererCommon.getLayoutMatrix(
397 mirror, frameAspectRatio(), (float) layoutWidth / layoutHeight); 438 mirror, frameAspectRatio(), (float) layoutWidth / layoutHeight);
398 texMatrix = RendererCommon.multiplyMatrices(rotatedSamplingMatrix, layoutM atrix); 439 texMatrix = RendererCommon.multiplyMatrices(rotatedSamplingMatrix, layoutM atrix);
399 } 440 }
400 441
401 GLES20.glViewport(0, 0, surfaceWidth, surfaceHeight); 442 GLES20.glViewport(0, 0, surfaceWidth, surfaceHeight);
402 if (frame.yuvFrame) { 443 if (frame.yuvFrame) {
403 // Make sure YUV textures are allocated. 444 // Make sure YUV textures are allocated.
404 if (yuvTextures == null) { 445 if (yuvTextures == null) {
405 yuvTextures = new int[3]; 446 yuvTextures = new int[3];
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 if (framesReceived > 0 && framesRendered > 0) { 509 if (framesReceived > 0 && framesRendered > 0) {
469 final long timeSinceFirstFrameNs = System.nanoTime() - firstFrameTimeNs; 510 final long timeSinceFirstFrameNs = System.nanoTime() - firstFrameTimeNs;
470 Logging.d(TAG, "Duration: " + (int) (timeSinceFirstFrameNs / 1e6) + 511 Logging.d(TAG, "Duration: " + (int) (timeSinceFirstFrameNs / 1e6) +
471 " ms. FPS: " + (float) framesRendered * 1e9 / timeSinceFirstFrameNs) ; 512 " ms. FPS: " + (float) framesRendered * 1e9 / timeSinceFirstFrameNs) ;
472 Logging.d(TAG, "Average render time: " 513 Logging.d(TAG, "Average render time: "
473 + (int) (renderTimeNs / (1000 * framesRendered)) + " us."); 514 + (int) (renderTimeNs / (1000 * framesRendered)) + " us.");
474 } 515 }
475 } 516 }
476 } 517 }
477 } 518 }
OLDNEW
« 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