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

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

Issue 1420203003: SurfaceViewRenderer: Add resource name to log outputs and exceptions (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Addressing hbos@ comments. Created 5 years, 1 month 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 10 matching lines...) Expand all
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28 package org.webrtc; 28 package org.webrtc;
29 29
30 import android.content.Context; 30 import android.content.Context;
31 import android.content.res.Resources.NotFoundException;
31 import android.graphics.Point; 32 import android.graphics.Point;
32 import android.graphics.SurfaceTexture; 33 import android.graphics.SurfaceTexture;
33 import android.opengl.GLES20; 34 import android.opengl.GLES20;
34 import android.opengl.Matrix; 35 import android.opengl.Matrix;
35 import android.os.Handler; 36 import android.os.Handler;
36 import android.os.HandlerThread; 37 import android.os.HandlerThread;
37 import android.util.AttributeSet; 38 import android.util.AttributeSet;
38 import android.view.SurfaceHolder; 39 import android.view.SurfaceHolder;
39 import android.view.SurfaceView; 40 import android.view.SurfaceView;
40 41
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 } 146 }
146 147
147 /** 148 /**
148 * Initialize this class, sharing resources with |sharedContext|. It is allowe d to call init() to 149 * Initialize this class, sharing resources with |sharedContext|. It is allowe d to call init() to
149 * reinitialize the renderer after a previous init()/release() cycle. 150 * reinitialize the renderer after a previous init()/release() cycle.
150 */ 151 */
151 public void init( 152 public void init(
152 EGLContext sharedContext, RendererCommon.RendererEvents rendererEvents) { 153 EGLContext sharedContext, RendererCommon.RendererEvents rendererEvents) {
153 synchronized (handlerLock) { 154 synchronized (handlerLock) {
154 if (renderThreadHandler != null) { 155 if (renderThreadHandler != null) {
155 throw new IllegalStateException("Already initialized"); 156 throw new IllegalStateException(getResourceName() + "Already initialized ");
156 } 157 }
157 Logging.d(TAG, "Initializing"); 158 Logging.d(TAG, getResourceName() + "Initializing.");
158 this.rendererEvents = rendererEvents; 159 this.rendererEvents = rendererEvents;
159 renderThread = new HandlerThread(TAG); 160 renderThread = new HandlerThread(TAG);
160 renderThread.start(); 161 renderThread.start();
161 drawer = new GlRectDrawer(); 162 drawer = new GlRectDrawer();
162 eglBase = new EglBase(sharedContext, EglBase.ConfigType.PLAIN); 163 eglBase = new EglBase(sharedContext, EglBase.ConfigType.PLAIN);
163 renderThreadHandler = new Handler(renderThread.getLooper()); 164 renderThreadHandler = new Handler(renderThread.getLooper());
164 } 165 }
165 tryCreateEglSurface(); 166 tryCreateEglSurface();
166 } 167 }
167 168
(...skipping 20 matching lines...) Expand all
188 /** 189 /**
189 * Block until any pending frame is returned and all GL resources released, ev en if an interrupt 190 * Block until any pending frame is returned and all GL resources released, ev en if an interrupt
190 * occurs. If an interrupt occurs during release(), the interrupt flag will be set. This function 191 * occurs. If an interrupt occurs during release(), the interrupt flag will be set. This function
191 * should be called before the Activity is destroyed and the EGLContext is sti ll valid. If you 192 * should be called before the Activity is destroyed and the EGLContext is sti ll valid. If you
192 * don't call this function, the GL resources might leak. 193 * don't call this function, the GL resources might leak.
193 */ 194 */
194 public void release() { 195 public void release() {
195 final CountDownLatch eglCleanupBarrier = new CountDownLatch(1); 196 final CountDownLatch eglCleanupBarrier = new CountDownLatch(1);
196 synchronized (handlerLock) { 197 synchronized (handlerLock) {
197 if (renderThreadHandler == null) { 198 if (renderThreadHandler == null) {
198 Logging.d(TAG, "Already released"); 199 Logging.d(TAG, getResourceName() + "Already released");
199 return; 200 return;
200 } 201 }
201 // Release EGL and GL resources on render thread. 202 // Release EGL and GL resources on render thread.
202 // TODO(magjed): This might not be necessary - all OpenGL resources are au tomatically deleted 203 // TODO(magjed): This might not be necessary - all OpenGL resources are au tomatically deleted
203 // when the EGL context is lost. It might be dangerous to delete them manu ally in 204 // when the EGL context is lost. It might be dangerous to delete them manu ally in
204 // Activity.onDestroy(). 205 // Activity.onDestroy().
205 renderThreadHandler.postAtFrontOfQueue(new Runnable() { 206 renderThreadHandler.postAtFrontOfQueue(new Runnable() {
206 @Override public void run() { 207 @Override public void run() {
207 drawer.release(); 208 drawer.release();
208 drawer = null; 209 drawer = null;
209 if (yuvTextures != null) { 210 if (yuvTextures != null) {
210 GLES20.glDeleteTextures(3, yuvTextures, 0); 211 GLES20.glDeleteTextures(3, yuvTextures, 0);
211 yuvTextures = null; 212 yuvTextures = null;
212 } 213 }
213 if (eglBase.hasSurface()) { 214 if (eglBase.hasSurface()) {
214 // Clear last rendered image to black. 215 // Clear last rendered image to black.
215 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 216 makeBlack();
216 eglBase.swapBuffers();
217 } 217 }
218 eglBase.release(); 218 eglBase.release();
219 eglBase = null; 219 eglBase = null;
220 eglCleanupBarrier.countDown(); 220 eglCleanupBarrier.countDown();
221 } 221 }
222 }); 222 });
223 // Don't accept any more frames or messages to the render thread. 223 // Don't accept any more frames or messages to the render thread.
224 renderThreadHandler = null; 224 renderThreadHandler = null;
225 } 225 }
226 // Make sure the EGL/GL cleanup posted above is executed. 226 // Make sure the EGL/GL cleanup posted above is executed.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 } 270 }
271 271
272 // VideoRenderer.Callbacks interface. 272 // VideoRenderer.Callbacks interface.
273 @Override 273 @Override
274 public void renderFrame(VideoRenderer.I420Frame frame) { 274 public void renderFrame(VideoRenderer.I420Frame frame) {
275 synchronized (statisticsLock) { 275 synchronized (statisticsLock) {
276 ++framesReceived; 276 ++framesReceived;
277 } 277 }
278 synchronized (handlerLock) { 278 synchronized (handlerLock) {
279 if (renderThreadHandler == null) { 279 if (renderThreadHandler == null) {
280 Logging.d(TAG, "Dropping frame - SurfaceViewRenderer not initialized or already released."); 280 Logging.d(TAG, getResourceName()
281 + "Dropping frame - Not initialized or already released.");
281 VideoRenderer.renderFrameDone(frame); 282 VideoRenderer.renderFrameDone(frame);
282 return; 283 return;
283 } 284 }
284 synchronized (frameLock) { 285 synchronized (frameLock) {
285 if (pendingFrame != null) { 286 if (pendingFrame != null) {
286 // Drop old frame. 287 // Drop old frame.
287 synchronized (statisticsLock) { 288 synchronized (statisticsLock) {
288 ++framesDropped; 289 ++framesDropped;
289 } 290 }
290 VideoRenderer.renderFrameDone(pendingFrame); 291 VideoRenderer.renderFrameDone(pendingFrame);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 layoutWidth = right - left; 331 layoutWidth = right - left;
331 layoutHeight = bottom - top; 332 layoutHeight = bottom - top;
332 } 333 }
333 // Might have a pending frame waiting for a layout of correct size. 334 // Might have a pending frame waiting for a layout of correct size.
334 runOnRenderThread(renderFrameRunnable); 335 runOnRenderThread(renderFrameRunnable);
335 } 336 }
336 337
337 // SurfaceHolder.Callback interface. 338 // SurfaceHolder.Callback interface.
338 @Override 339 @Override
339 public void surfaceCreated(final SurfaceHolder holder) { 340 public void surfaceCreated(final SurfaceHolder holder) {
340 Logging.d(TAG, "Surface created"); 341 Logging.d(TAG, getResourceName() + "Surface created.");
341 synchronized (layoutLock) { 342 synchronized (layoutLock) {
342 isSurfaceCreated = true; 343 isSurfaceCreated = true;
343 } 344 }
344 tryCreateEglSurface(); 345 tryCreateEglSurface();
345 } 346 }
346 347
347 @Override 348 @Override
348 public void surfaceDestroyed(SurfaceHolder holder) { 349 public void surfaceDestroyed(SurfaceHolder holder) {
349 Logging.d(TAG, "Surface destroyed"); 350 Logging.d(TAG, getResourceName() + "Surface destroyed.");
350 synchronized (layoutLock) { 351 synchronized (layoutLock) {
351 isSurfaceCreated = false; 352 isSurfaceCreated = false;
352 surfaceWidth = 0; 353 surfaceWidth = 0;
353 surfaceHeight = 0; 354 surfaceHeight = 0;
354 } 355 }
355 runOnRenderThread(new Runnable() { 356 runOnRenderThread(new Runnable() {
356 @Override public void run() { 357 @Override public void run() {
357 eglBase.releaseSurface(); 358 eglBase.releaseSurface();
358 } 359 }
359 }); 360 });
360 } 361 }
361 362
362 @Override 363 @Override
363 public void surfaceChanged(SurfaceHolder holder, int format, int width, int he ight) { 364 public void surfaceChanged(SurfaceHolder holder, int format, int width, int he ight) {
364 Logging.d(TAG, "Surface changed: " + width + "x" + height); 365 Logging.d(TAG, getResourceName() + "Surface changed: " + width + "x" + heigh t);
365 synchronized (layoutLock) { 366 synchronized (layoutLock) {
366 surfaceWidth = width; 367 surfaceWidth = width;
367 surfaceHeight = height; 368 surfaceHeight = height;
368 } 369 }
369 // Might have a pending frame waiting for a surface of correct size. 370 // Might have a pending frame waiting for a surface of correct size.
370 runOnRenderThread(renderFrameRunnable); 371 runOnRenderThread(renderFrameRunnable);
371 } 372 }
372 373
373 /** 374 /**
374 * Private helper function to post tasks safely. 375 * Private helper function to post tasks safely.
375 */ 376 */
376 private void runOnRenderThread(Runnable runnable) { 377 private void runOnRenderThread(Runnable runnable) {
377 synchronized (handlerLock) { 378 synchronized (handlerLock) {
378 if (renderThreadHandler != null) { 379 if (renderThreadHandler != null) {
379 renderThreadHandler.post(runnable); 380 renderThreadHandler.post(runnable);
380 } 381 }
381 } 382 }
382 } 383 }
383 384
385 private String getResourceName() {
386 try {
387 return getResources().getResourceEntryName(getId()) + ": ";
388 } catch (NotFoundException e) {
389 return "";
390 }
391 }
392
393 private void makeBlack() {
394 if (Thread.currentThread() != renderThread) {
395 throw new IllegalStateException(getResourceName() + "Wrong thread.");
396 }
397 GLES20.glClearColor(0, 0, 0, 0);
398 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
399 eglBase.swapBuffers();
400 }
401
384 /** 402 /**
385 * Requests new layout if necessary. Returns true if layout and surface size a re consistent. 403 * Requests new layout if necessary. Returns true if layout and surface size a re consistent.
386 */ 404 */
387 private boolean checkConsistentLayout() { 405 private boolean checkConsistentLayout() {
388 synchronized (layoutLock) { 406 synchronized (layoutLock) {
389 final Point desiredLayoutSize = getDesiredLayoutSize(); 407 final Point desiredLayoutSize = getDesiredLayoutSize();
390 if (desiredLayoutSize.x != layoutWidth || desiredLayoutSize.y != layoutHei ght) { 408 if (desiredLayoutSize.x != layoutWidth || desiredLayoutSize.y != layoutHei ght) {
391 Logging.d(TAG, "Requesting new layout with size: " 409 Logging.d(TAG, getResourceName() + "Requesting new layout with size: "
392 + desiredLayoutSize.x + "x" + desiredLayoutSize.y); 410 + desiredLayoutSize.x + "x" + desiredLayoutSize.y);
393 // Request layout update on UI thread. 411 // Request layout update on UI thread.
394 post(new Runnable() { 412 post(new Runnable() {
395 @Override public void run() { 413 @Override public void run() {
396 requestLayout(); 414 requestLayout();
397 } 415 }
398 }); 416 });
399 return false; 417 return false;
400 } 418 }
401 // Wait for requestLayout() to propagate through this sequence before retu rning true: 419 // Wait for requestLayout() to propagate through this sequence before retu rning true:
402 // requestLayout() -> onMeasure() -> onLayout() -> surfaceChanged(). 420 // requestLayout() -> onMeasure() -> onLayout() -> surfaceChanged().
403 return surfaceWidth == layoutWidth && surfaceHeight == layoutHeight; 421 return surfaceWidth == layoutWidth && surfaceHeight == layoutHeight;
404 } 422 }
405 } 423 }
406 424
407 /** 425 /**
408 * Renders and releases |pendingFrame|. 426 * Renders and releases |pendingFrame|.
409 */ 427 */
410 private void renderFrameOnRenderThread() { 428 private void renderFrameOnRenderThread() {
429 if (Thread.currentThread() != renderThread) {
430 throw new IllegalStateException(getResourceName() + "Wrong thread.");
431 }
411 if (eglBase == null || !eglBase.hasSurface()) { 432 if (eglBase == null || !eglBase.hasSurface()) {
412 Logging.d(TAG, "No surface to draw on"); 433 Logging.d(TAG, getResourceName() + "No surface to draw on");
413 return; 434 return;
414 } 435 }
415 if (!checkConsistentLayout()) { 436 if (!checkConsistentLayout()) {
416 // Output intermediate black frames while the layout is updated. 437 // Output intermediate black frames while the layout is updated.
417 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 438 makeBlack();
418 eglBase.swapBuffers();
419 return; 439 return;
420 } 440 }
421 // After a surface size change, the EGLSurface might still have a buffer of the old size in the 441 // After a surface size change, the EGLSurface might still have a buffer of the old size in the
422 // pipeline. Querying the EGLSurface will show if the underlying buffer dime nsions haven't yet 442 // pipeline. Querying the EGLSurface will show if the underlying buffer dime nsions haven't yet
423 // changed. Such a buffer will be rendered incorrectly, so flush it with a b lack frame. 443 // changed. Such a buffer will be rendered incorrectly, so flush it with a b lack frame.
424 synchronized (layoutLock) { 444 synchronized (layoutLock) {
425 if (eglBase.surfaceWidth() != surfaceWidth || eglBase.surfaceHeight() != s urfaceHeight) { 445 if (eglBase.surfaceWidth() != surfaceWidth || eglBase.surfaceHeight() != s urfaceHeight) {
426 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 446 makeBlack();
427 eglBase.swapBuffers();
428 } 447 }
429 } 448 }
430 // Fetch and render |pendingFrame|. 449 // Fetch and render |pendingFrame|.
431 final VideoRenderer.I420Frame frame; 450 final VideoRenderer.I420Frame frame;
432 synchronized (frameLock) { 451 synchronized (frameLock) {
433 if (pendingFrame == null) { 452 if (pendingFrame == null) {
434 return; 453 return;
435 } 454 }
436 frame = pendingFrame; 455 frame = pendingFrame;
437 pendingFrame = null; 456 pendingFrame = null;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 : (float) frameHeight / frameWidth; 521 : (float) frameHeight / frameWidth;
503 } 522 }
504 } 523 }
505 524
506 // Update frame dimensions and report any changes to |rendererEvents|. 525 // Update frame dimensions and report any changes to |rendererEvents|.
507 private void updateFrameDimensionsAndReportEvents(VideoRenderer.I420Frame fram e) { 526 private void updateFrameDimensionsAndReportEvents(VideoRenderer.I420Frame fram e) {
508 synchronized (layoutLock) { 527 synchronized (layoutLock) {
509 if (frameWidth != frame.width || frameHeight != frame.height 528 if (frameWidth != frame.width || frameHeight != frame.height
510 || frameRotation != frame.rotationDegree) { 529 || frameRotation != frame.rotationDegree) {
511 if (rendererEvents != null) { 530 if (rendererEvents != null) {
512 final String id = getResources().getResourceEntryName(getId());
513 if (frameWidth == 0 || frameHeight == 0) { 531 if (frameWidth == 0 || frameHeight == 0) {
514 Logging.d(TAG, "ID: " + id + ". Reporting first rendered frame."); 532 Logging.d(TAG, getResourceName() + "Reporting first rendered frame." );
515 rendererEvents.onFirstFrameRendered(); 533 rendererEvents.onFirstFrameRendered();
516 } 534 }
517 Logging.d(TAG, "ID: " + id + ". Reporting frame resolution changed to " 535 Logging.d(TAG, getResourceName() + "Reporting frame resolution changed to "
518 + frame.width + "x" + frame.height + " with rotation " + frame.rot ationDegree); 536 + frame.width + "x" + frame.height + " with rotation " + frame.rot ationDegree);
519 rendererEvents.onFrameResolutionChanged(frame.width, frame.height, fra me.rotationDegree); 537 rendererEvents.onFrameResolutionChanged(frame.width, frame.height, fra me.rotationDegree);
520 } 538 }
521 frameWidth = frame.width; 539 frameWidth = frame.width;
522 frameHeight = frame.height; 540 frameHeight = frame.height;
523 frameRotation = frame.rotationDegree; 541 frameRotation = frame.rotationDegree;
524 } 542 }
525 } 543 }
526 } 544 }
527 545
528 private void logStatistics() { 546 private void logStatistics() {
529 synchronized (statisticsLock) { 547 synchronized (statisticsLock) {
530 Logging.d(TAG, "ID: " + getResources().getResourceEntryName(getId()) + ". Frames received: " 548 Logging.d(TAG, getResourceName() + "Frames received: "
531 + framesReceived + ". Dropped: " + framesDropped + ". Rendered: " + fr amesRendered); 549 + framesReceived + ". Dropped: " + framesDropped + ". Rendered: " + fr amesRendered);
532 if (framesReceived > 0 && framesRendered > 0) { 550 if (framesReceived > 0 && framesRendered > 0) {
533 final long timeSinceFirstFrameNs = System.nanoTime() - firstFrameTimeNs; 551 final long timeSinceFirstFrameNs = System.nanoTime() - firstFrameTimeNs;
534 Logging.d(TAG, "Duration: " + (int) (timeSinceFirstFrameNs / 1e6) + 552 Logging.d(TAG, getResourceName() + "Duration: " + (int) (timeSinceFirstF rameNs / 1e6) +
535 " ms. FPS: " + (float) framesRendered * 1e9 / timeSinceFirstFrameNs) ; 553 " ms. FPS: " + (float) framesRendered * 1e9 / timeSinceFirstFrameNs) ;
536 Logging.d(TAG, "Average render time: " 554 Logging.d(TAG, getResourceName() + "Average render time: "
537 + (int) (renderTimeNs / (1000 * framesRendered)) + " us."); 555 + (int) (renderTimeNs / (1000 * framesRendered)) + " us.");
538 } 556 }
539 } 557 }
540 } 558 }
541 } 559 }
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