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

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

Issue 1338033003: Log to webrtc logging stream from java code. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: 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 unified diff | Download patch
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 18 matching lines...) Expand all
29 29
30 import android.content.Context; 30 import android.content.Context;
31 import android.graphics.Point; 31 import android.graphics.Point;
32 import android.graphics.SurfaceTexture; 32 import android.graphics.SurfaceTexture;
33 import android.opengl.EGLContext; 33 import android.opengl.EGLContext;
34 import android.opengl.GLES20; 34 import android.opengl.GLES20;
35 import android.opengl.Matrix; 35 import android.opengl.Matrix;
36 import android.os.Handler; 36 import android.os.Handler;
37 import android.os.HandlerThread; 37 import android.os.HandlerThread;
38 import android.util.AttributeSet; 38 import android.util.AttributeSet;
39 import android.util.Log;
40 import android.view.SurfaceHolder; 39 import android.view.SurfaceHolder;
41 import android.view.SurfaceView; 40 import android.view.SurfaceView;
42 41
42 import org.webrtc.Logging;
43
43 /** 44 /**
44 * Implements org.webrtc.VideoRenderer.Callbacks by displaying the video stream on a SurfaceView. 45 * Implements org.webrtc.VideoRenderer.Callbacks by displaying the video stream on a SurfaceView.
45 * renderFrame() is asynchronous to avoid blocking the calling thread. 46 * renderFrame() is asynchronous to avoid blocking the calling thread.
46 * This class is thread safe and handles access from potentially four different threads: 47 * This class is thread safe and handles access from potentially four different threads:
47 * Interaction from the main app in init, release, setMirror, and setScalingtype . 48 * Interaction from the main app in init, release, setMirror, and setScalingtype .
48 * Interaction from C++ webrtc::VideoRendererInterface in renderFrame and canApp lyRotation. 49 * Interaction from C++ webrtc::VideoRendererInterface in renderFrame and canApp lyRotation.
49 * Interaction from the Activity lifecycle in surfaceCreated, surfaceChanged, an d surfaceDestroyed. 50 * Interaction from the Activity lifecycle in surfaceCreated, surfaceChanged, an d surfaceDestroyed.
50 * Interaction with the layout framework in onMeasure and onSizeChanged. 51 * Interaction with the layout framework in onMeasure and onSizeChanged.
51 */ 52 */
52 public class SurfaceViewRenderer extends SurfaceView 53 public class SurfaceViewRenderer extends SurfaceView
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 } 138 }
138 139
139 /** 140 /**
140 * Initialize this class, sharing resources with |sharedContext|. 141 * Initialize this class, sharing resources with |sharedContext|.
141 */ 142 */
142 public void init( 143 public void init(
143 EGLContext sharedContext, RendererCommon.RendererEvents rendererEvents) { 144 EGLContext sharedContext, RendererCommon.RendererEvents rendererEvents) {
144 if (renderThreadHandler != null) { 145 if (renderThreadHandler != null) {
145 throw new IllegalStateException("Already initialized"); 146 throw new IllegalStateException("Already initialized");
146 } 147 }
147 Log.d(TAG, "Initializing"); 148 Logging.d(TAG, "Initializing");
148 this.rendererEvents = rendererEvents; 149 this.rendererEvents = rendererEvents;
149 renderThread = new HandlerThread(TAG); 150 renderThread = new HandlerThread(TAG);
150 renderThread.start(); 151 renderThread.start();
151 renderThreadHandler = new Handler(renderThread.getLooper()); 152 renderThreadHandler = new Handler(renderThread.getLooper());
152 eglBase = new EglBase(sharedContext, EglBase.ConfigType.PLAIN); 153 eglBase = new EglBase(sharedContext, EglBase.ConfigType.PLAIN);
153 drawer = new GlRectDrawer(); 154 drawer = new GlRectDrawer();
154 getHolder().addCallback(this); 155 getHolder().addCallback(this);
155 } 156 }
156 157
157 /** 158 /**
158 * Release all resources. This needs to be done manually, otherwise the resour ces are leaked. You 159 * Release all resources. This needs to be done manually, otherwise the resour ces are leaked. You
159 * should call this before the Activity is destroyed, while the EGLContext is still valid. 160 * should call this before the Activity is destroyed, while the EGLContext is still valid.
160 */ 161 */
161 public void release() { 162 public void release() {
162 synchronized (threadLock) { 163 synchronized (threadLock) {
163 if (renderThreadHandler == null) { 164 if (renderThreadHandler == null) {
164 Log.d(TAG, "Already released"); 165 Logging.d(TAG, "Already released");
165 return; 166 return;
166 } 167 }
167 // Release EGL and GL resources on render thread. 168 // Release EGL and GL resources on render thread.
168 // TODO(magjed): This might not be necessary - all OpenGL resources are au tomatically deleted 169 // TODO(magjed): This might not be necessary - all OpenGL resources are au tomatically deleted
169 // when the EGL context is lost. It might be dangerous to delete them manu ally in 170 // when the EGL context is lost. It might be dangerous to delete them manu ally in
170 // Activity.onDestroy(). 171 // Activity.onDestroy().
171 renderThreadHandler.post(new Runnable() { 172 renderThreadHandler.post(new Runnable() {
172 @Override public void run() { 173 @Override public void run() {
173 drawer.release(); 174 drawer.release();
174 drawer = null; 175 drawer = null;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 } 215 }
215 216
216 // VideoRenderer.Callbacks interface. 217 // VideoRenderer.Callbacks interface.
217 @Override 218 @Override
218 public void renderFrame(VideoRenderer.I420Frame frame) { 219 public void renderFrame(VideoRenderer.I420Frame frame) {
219 synchronized (statisticsLock) { 220 synchronized (statisticsLock) {
220 ++framesReceived; 221 ++framesReceived;
221 } 222 }
222 synchronized (threadLock) { 223 synchronized (threadLock) {
223 if (renderThreadHandler == null) { 224 if (renderThreadHandler == null) {
224 Log.d(TAG, "Dropping frame - SurfaceViewRenderer not initialized or alre ady released."); 225 Logging.d(TAG, "Dropping frame - SurfaceViewRenderer not initialized or already released.");
225 } else { 226 } else {
226 synchronized (frameLock) { 227 synchronized (frameLock) {
227 if (pendingFrame == null) { 228 if (pendingFrame == null) {
228 updateFrameDimensionsAndReportEvents(frame); 229 updateFrameDimensionsAndReportEvents(frame);
229 pendingFrame = frame; 230 pendingFrame = frame;
230 renderThreadHandler.post(renderFrameRunnable); 231 renderThreadHandler.post(renderFrameRunnable);
231 return; 232 return;
232 } 233 }
233 } 234 }
234 } 235 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 layoutWidth = right - left; 275 layoutWidth = right - left;
275 layoutHeight = bottom - top; 276 layoutHeight = bottom - top;
276 } 277 }
277 // Might have a pending frame waiting for a layout of correct size. 278 // Might have a pending frame waiting for a layout of correct size.
278 runOnRenderThread(renderFrameRunnable); 279 runOnRenderThread(renderFrameRunnable);
279 } 280 }
280 281
281 // SurfaceHolder.Callback interface. 282 // SurfaceHolder.Callback interface.
282 @Override 283 @Override
283 public void surfaceCreated(final SurfaceHolder holder) { 284 public void surfaceCreated(final SurfaceHolder holder) {
284 Log.d(TAG, "Surface created"); 285 Logging.d(TAG, "Surface created");
285 runOnRenderThread(new Runnable() { 286 runOnRenderThread(new Runnable() {
286 @Override public void run() { 287 @Override public void run() {
287 eglBase.createSurface(holder.getSurface()); 288 eglBase.createSurface(holder.getSurface());
288 eglBase.makeCurrent(); 289 eglBase.makeCurrent();
289 // Necessary for YUV frames with odd width. 290 // Necessary for YUV frames with odd width.
290 GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1); 291 GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
291 } 292 }
292 }); 293 });
293 } 294 }
294 295
295 @Override 296 @Override
296 public void surfaceDestroyed(SurfaceHolder holder) { 297 public void surfaceDestroyed(SurfaceHolder holder) {
297 Log.d(TAG, "Surface destroyed"); 298 Logging.d(TAG, "Surface destroyed");
298 synchronized (layoutLock) { 299 synchronized (layoutLock) {
299 surfaceWidth = 0; 300 surfaceWidth = 0;
300 surfaceHeight = 0; 301 surfaceHeight = 0;
301 } 302 }
302 runOnRenderThread(new Runnable() { 303 runOnRenderThread(new Runnable() {
303 @Override public void run() { 304 @Override public void run() {
304 eglBase.releaseSurface(); 305 eglBase.releaseSurface();
305 } 306 }
306 }); 307 });
307 } 308 }
308 309
309 @Override 310 @Override
310 public void surfaceChanged(SurfaceHolder holder, int format, int width, int he ight) { 311 public void surfaceChanged(SurfaceHolder holder, int format, int width, int he ight) {
311 Log.d(TAG, "Surface changed: " + width + "x" + height); 312 Logging.d(TAG, "Surface changed: " + width + "x" + height);
312 synchronized (layoutLock) { 313 synchronized (layoutLock) {
313 surfaceWidth = width; 314 surfaceWidth = width;
314 surfaceHeight = height; 315 surfaceHeight = height;
315 } 316 }
316 // Might have a pending frame waiting for a surface of correct size. 317 // Might have a pending frame waiting for a surface of correct size.
317 runOnRenderThread(renderFrameRunnable); 318 runOnRenderThread(renderFrameRunnable);
318 } 319 }
319 320
320 /** 321 /**
321 * Private helper function to post tasks safely. 322 * Private helper function to post tasks safely.
322 */ 323 */
323 private void runOnRenderThread(Runnable runnable) { 324 private void runOnRenderThread(Runnable runnable) {
324 synchronized (threadLock) { 325 synchronized (threadLock) {
325 if (renderThreadHandler != null) { 326 if (renderThreadHandler != null) {
326 renderThreadHandler.post(runnable); 327 renderThreadHandler.post(runnable);
327 } 328 }
328 } 329 }
329 } 330 }
330 331
331 /** 332 /**
332 * Requests new layout if necessary. Returns true if layout and surface size a re consistent. 333 * Requests new layout if necessary. Returns true if layout and surface size a re consistent.
333 */ 334 */
334 private boolean checkConsistentLayout() { 335 private boolean checkConsistentLayout() {
335 synchronized (layoutLock) { 336 synchronized (layoutLock) {
336 final Point desiredLayoutSize = getDesiredLayoutSize(); 337 final Point desiredLayoutSize = getDesiredLayoutSize();
337 if (desiredLayoutSize.x != layoutWidth || desiredLayoutSize.y != layoutHei ght) { 338 if (desiredLayoutSize.x != layoutWidth || desiredLayoutSize.y != layoutHei ght) {
338 Log.d(TAG, "Requesting new layout with size: " 339 Logging.d(TAG, "Requesting new layout with size: "
339 + desiredLayoutSize.x + "x" + desiredLayoutSize.y); 340 + desiredLayoutSize.x + "x" + desiredLayoutSize.y);
340 // Request layout update on UI thread. 341 // Request layout update on UI thread.
341 post(new Runnable() { 342 post(new Runnable() {
342 @Override public void run() { 343 @Override public void run() {
343 requestLayout(); 344 requestLayout();
344 } 345 }
345 }); 346 });
346 return false; 347 return false;
347 } 348 }
348 // Wait for requestLayout() to propagate through this sequence before retu rning true: 349 // Wait for requestLayout() to propagate through this sequence before retu rning true:
349 // requestLayout() -> onMeasure() -> onLayout() -> surfaceChanged(). 350 // requestLayout() -> onMeasure() -> onLayout() -> surfaceChanged().
350 return surfaceWidth == layoutWidth && surfaceHeight == layoutHeight; 351 return surfaceWidth == layoutWidth && surfaceHeight == layoutHeight;
351 } 352 }
352 } 353 }
353 354
354 /** 355 /**
355 * Renders and releases |pendingFrame|. 356 * Renders and releases |pendingFrame|.
356 */ 357 */
357 private void renderFrameOnRenderThread() { 358 private void renderFrameOnRenderThread() {
358 if (eglBase == null || !eglBase.hasSurface()) { 359 if (eglBase == null || !eglBase.hasSurface()) {
359 Log.d(TAG, "No surface to draw on"); 360 Logging.d(TAG, "No surface to draw on");
360 return; 361 return;
361 } 362 }
362 if (!checkConsistentLayout()) { 363 if (!checkConsistentLayout()) {
363 // Output intermediate black frames while the layout is updated. 364 // Output intermediate black frames while the layout is updated.
364 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 365 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
365 eglBase.swapBuffers(); 366 eglBase.swapBuffers();
366 return; 367 return;
367 } 368 }
368 // After a surface size change, the EGLSurface might still have a buffer of the old size in the 369 // After a surface size change, the EGLSurface might still have a buffer of the old size in the
369 // pipeline. Querying the EGLSurface will show if the underlying buffer dime nsions haven't yet 370 // pipeline. Querying the EGLSurface will show if the underlying buffer dime nsions haven't yet
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 } 443 }
443 444
444 // Update frame dimensions and report any changes to |rendererEvents|. 445 // Update frame dimensions and report any changes to |rendererEvents|.
445 private void updateFrameDimensionsAndReportEvents(VideoRenderer.I420Frame fram e) { 446 private void updateFrameDimensionsAndReportEvents(VideoRenderer.I420Frame fram e) {
446 synchronized (layoutLock) { 447 synchronized (layoutLock) {
447 if (frameWidth != frame.width || frameHeight != frame.height 448 if (frameWidth != frame.width || frameHeight != frame.height
448 || frameRotation != frame.rotationDegree) { 449 || frameRotation != frame.rotationDegree) {
449 if (rendererEvents != null) { 450 if (rendererEvents != null) {
450 final String id = getResources().getResourceEntryName(getId()); 451 final String id = getResources().getResourceEntryName(getId());
451 if (frameWidth == 0 || frameHeight == 0) { 452 if (frameWidth == 0 || frameHeight == 0) {
452 Log.d(TAG, "ID: " + id + ". Reporting first rendered frame."); 453 Logging.d(TAG, "ID: " + id + ". Reporting first rendered frame.");
453 rendererEvents.onFirstFrameRendered(); 454 rendererEvents.onFirstFrameRendered();
454 } 455 }
455 Log.d(TAG, "ID: " + id + ". Reporting frame resolution changed to " 456 Logging.d(TAG, "ID: " + id + ". Reporting frame resolution changed to "
456 + frame.width + "x" + frame.height + " with rotation " + frame.rot ationDegree); 457 + frame.width + "x" + frame.height + " with rotation " + frame.rot ationDegree);
457 rendererEvents.onFrameResolutionChanged(frame.width, frame.height, fra me.rotationDegree); 458 rendererEvents.onFrameResolutionChanged(frame.width, frame.height, fra me.rotationDegree);
458 } 459 }
459 frameWidth = frame.width; 460 frameWidth = frame.width;
460 frameHeight = frame.height; 461 frameHeight = frame.height;
461 frameRotation = frame.rotationDegree; 462 frameRotation = frame.rotationDegree;
462 } 463 }
463 } 464 }
464 } 465 }
465 466
466 private void logStatistics() { 467 private void logStatistics() {
467 synchronized (statisticsLock) { 468 synchronized (statisticsLock) {
468 Log.d(TAG, "ID: " + getResources().getResourceEntryName(getId()) + ". Fram es received: " 469 Logging.d(TAG, "ID: " + getResources().getResourceEntryName(getId()) + ". Frames received: "
469 + framesReceived + ". Dropped: " + framesDropped + ". Rendered: " + fr amesRendered); 470 + framesReceived + ". Dropped: " + framesDropped + ". Rendered: " + fr amesRendered);
470 if (framesReceived > 0 && framesRendered > 0) { 471 if (framesReceived > 0 && framesRendered > 0) {
471 final long timeSinceFirstFrameNs = System.nanoTime() - firstFrameTimeNs; 472 final long timeSinceFirstFrameNs = System.nanoTime() - firstFrameTimeNs;
472 Log.d(TAG, "Duration: " + (int) (timeSinceFirstFrameNs / 1e6) + 473 Logging.d(TAG, "Duration: " + (int) (timeSinceFirstFrameNs / 1e6) +
473 " ms. FPS: " + (float) framesRendered * 1e9 / timeSinceFirstFrameNs) ; 474 " ms. FPS: " + (float) framesRendered * 1e9 / timeSinceFirstFrameNs) ;
474 Log.d(TAG, "Average render time: " 475 Logging.d(TAG, "Average render time: "
475 + (int) (renderTimeNs / (1000 * framesRendered)) + " us."); 476 + (int) (renderTimeNs / (1000 * framesRendered)) + " us.");
476 } 477 }
477 } 478 }
478 } 479 }
479 } 480 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698