OLD | NEW |
---|---|
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2014 Google Inc. | 3 * Copyright 2014 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 Loading... | |
29 | 29 |
30 import java.util.ArrayList; | 30 import java.util.ArrayList; |
31 import java.util.concurrent.CountDownLatch; | 31 import java.util.concurrent.CountDownLatch; |
32 | 32 |
33 import javax.microedition.khronos.egl.EGLConfig; | 33 import javax.microedition.khronos.egl.EGLConfig; |
34 import javax.microedition.khronos.opengles.GL10; | 34 import javax.microedition.khronos.opengles.GL10; |
35 | 35 |
36 import android.annotation.SuppressLint; | 36 import android.annotation.SuppressLint; |
37 import android.graphics.Point; | 37 import android.graphics.Point; |
38 import android.graphics.Rect; | 38 import android.graphics.Rect; |
39 import android.graphics.SurfaceTexture; | |
40 import android.opengl.EGL14; | 39 import android.opengl.EGL14; |
41 import android.opengl.EGLContext; | 40 import android.opengl.EGLContext; |
42 import android.opengl.GLES20; | 41 import android.opengl.GLES20; |
43 import android.opengl.GLSurfaceView; | 42 import android.opengl.GLSurfaceView; |
44 import android.opengl.Matrix; | |
45 | 43 |
46 import org.webrtc.Logging; | 44 import org.webrtc.Logging; |
47 import org.webrtc.VideoRenderer.I420Frame; | 45 import org.webrtc.VideoRenderer.I420Frame; |
48 | 46 |
49 /** | 47 /** |
50 * Efficiently renders YUV frames using the GPU for CSC. | 48 * Efficiently renders YUV frames using the GPU for CSC. |
51 * Clients will want first to call setView() to pass GLSurfaceView | 49 * Clients will want first to call setView() to pass GLSurfaceView |
52 * and then for each video stream either create instance of VideoRenderer using | 50 * and then for each video stream either create instance of VideoRenderer using |
53 * createGui() call or VideoRenderer.Callbacks interface using create() call. | 51 * createGui() call or VideoRenderer.Callbacks interface using create() call. |
54 * Only one instance of the class can be created. | 52 * Only one instance of the class can be created. |
(...skipping 15 matching lines...) Expand all Loading... | |
70 private int screenHeight; | 68 private int screenHeight; |
71 // List of yuv renderers. | 69 // List of yuv renderers. |
72 private final ArrayList<YuvImageRenderer> yuvImageRenderers; | 70 private final ArrayList<YuvImageRenderer> yuvImageRenderers; |
73 // |drawer| is synchronized on |yuvImageRenderers|. | 71 // |drawer| is synchronized on |yuvImageRenderers|. |
74 private GlRectDrawer drawer; | 72 private GlRectDrawer drawer; |
75 private static final int EGL14_SDK_VERSION = | 73 private static final int EGL14_SDK_VERSION = |
76 android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; | 74 android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; |
77 // Current SDK version. | 75 // Current SDK version. |
78 private static final int CURRENT_SDK_VERSION = | 76 private static final int CURRENT_SDK_VERSION = |
79 android.os.Build.VERSION.SDK_INT; | 77 android.os.Build.VERSION.SDK_INT; |
78 // Render and draw threads. | |
79 private static Thread renderFrameThread; | |
80 private static Thread drawThread; | |
80 | 81 |
81 private VideoRendererGui(GLSurfaceView surface) { | 82 private VideoRendererGui(GLSurfaceView surface) { |
82 this.surface = surface; | 83 this.surface = surface; |
83 // Create an OpenGL ES 2.0 context. | 84 // Create an OpenGL ES 2.0 context. |
84 surface.setPreserveEGLContextOnPause(true); | 85 surface.setPreserveEGLContextOnPause(true); |
85 surface.setEGLContextClientVersion(2); | 86 surface.setEGLContextClientVersion(2); |
86 surface.setRenderer(this); | 87 surface.setRenderer(this); |
87 surface.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); | 88 surface.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); |
88 | 89 |
89 yuvImageRenderers = new ArrayList<YuvImageRenderer>(); | 90 yuvImageRenderers = new ArrayList<YuvImageRenderer>(); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
365 } | 366 } |
366 } | 367 } |
367 | 368 |
368 @Override | 369 @Override |
369 public synchronized void renderFrame(I420Frame frame) { | 370 public synchronized void renderFrame(I420Frame frame) { |
370 if (surface == null) { | 371 if (surface == null) { |
371 // This object has been released. | 372 // This object has been released. |
372 VideoRenderer.renderFrameDone(frame); | 373 VideoRenderer.renderFrameDone(frame); |
373 return; | 374 return; |
374 } | 375 } |
376 if (renderFrameThread == null) { | |
377 renderFrameThread = Thread.currentThread(); | |
378 } | |
375 if (!seenFrame && rendererEvents != null) { | 379 if (!seenFrame && rendererEvents != null) { |
376 Logging.d(TAG, "ID: " + id + ". Reporting first rendered frame."); | 380 Logging.d(TAG, "ID: " + id + ". Reporting first rendered frame."); |
377 rendererEvents.onFirstFrameRendered(); | 381 rendererEvents.onFirstFrameRendered(); |
378 } | 382 } |
379 framesReceived++; | 383 framesReceived++; |
380 synchronized (pendingFrameLock) { | 384 synchronized (pendingFrameLock) { |
381 // Check input frame parameters. | 385 // Check input frame parameters. |
382 if (frame.yuvFrame) { | 386 if (frame.yuvFrame) { |
383 if (frame.yuvStrides[0] < frame.width || | 387 if (frame.yuvStrides[0] < frame.width || |
384 frame.yuvStrides[1] < frame.width / 2 || | 388 frame.yuvStrides[1] < frame.width / 2 || |
385 frame.yuvStrides[2] < frame.width / 2) { | 389 frame.yuvStrides[2] < frame.width / 2) { |
386 Logging.e(TAG, "Incorrect strides " + frame.yuvStrides[0] + ", " + | 390 Logging.e(TAG, "Incorrect strides " + frame.yuvStrides[0] + ", " + |
387 frame.yuvStrides[1] + ", " + frame.yuvStrides[2]); | 391 frame.yuvStrides[1] + ", " + frame.yuvStrides[2]); |
388 VideoRenderer.renderFrameDone(frame); | 392 VideoRenderer.renderFrameDone(frame); |
389 return; | 393 return; |
390 } | 394 } |
391 } | 395 } |
392 | 396 |
393 if (pendingFrame != null) { | 397 if (pendingFrame != null) { |
394 // Skip rendering of this frame if previous frame was not rendered yet . | 398 // Skip rendering of this frame if previous frame was not rendered yet . |
395 framesDropped++; | 399 framesDropped++; |
396 VideoRenderer.renderFrameDone(frame); | 400 VideoRenderer.renderFrameDone(frame); |
401 seenFrame = true; | |
397 return; | 402 return; |
398 } | 403 } |
399 pendingFrame = frame; | 404 pendingFrame = frame; |
400 } | 405 } |
401 setSize(frame.width, frame.height, frame.rotationDegree); | 406 setSize(frame.width, frame.height, frame.rotationDegree); |
402 seenFrame = true; | 407 seenFrame = true; |
403 | 408 |
404 // Request rendering. | 409 // Request rendering. |
405 surface.requestRender(); | 410 surface.requestRender(); |
406 } | 411 } |
(...skipping 16 matching lines...) Expand all Loading... | |
423 if (instance == null){ | 428 if (instance == null){ |
424 return; | 429 return; |
425 } | 430 } |
426 Logging.d(TAG, "VideoRendererGui.dispose"); | 431 Logging.d(TAG, "VideoRendererGui.dispose"); |
427 synchronized (instance.yuvImageRenderers) { | 432 synchronized (instance.yuvImageRenderers) { |
428 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { | 433 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { |
429 yuvImageRenderer.release(); | 434 yuvImageRenderer.release(); |
430 } | 435 } |
431 instance.yuvImageRenderers.clear(); | 436 instance.yuvImageRenderers.clear(); |
432 } | 437 } |
438 renderFrameThread = null; | |
439 drawThread = null; | |
433 instance.surface = null; | 440 instance.surface = null; |
434 eglContext = null; | 441 eglContext = null; |
435 eglContextReady = null; | 442 eglContextReady = null; |
436 instance = null; | 443 instance = null; |
437 } | 444 } |
438 | 445 |
439 /** | 446 /** |
440 * Creates VideoRenderer with top left corner at (x, y) and resolution | 447 * Creates VideoRenderer with top left corner at (x, y) and resolution |
441 * (width, height). All parameters are in percentage of screen resolution. | 448 * (width, height). All parameters are in percentage of screen resolution. |
442 */ | 449 */ |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
558 } | 565 } |
559 synchronized (instance.yuvImageRenderers) { | 566 synchronized (instance.yuvImageRenderers) { |
560 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { | 567 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) { |
561 if (yuvImageRenderer == renderer) { | 568 if (yuvImageRenderer == renderer) { |
562 yuvImageRenderer.reset(); | 569 yuvImageRenderer.reset(); |
563 } | 570 } |
564 } | 571 } |
565 } | 572 } |
566 } | 573 } |
567 | 574 |
575 private static void printStackTrace(Thread thread, String threadName) { | |
wzh
2015/10/12 20:45:47
nit: if we can have a global util func for this, w
| |
576 if (thread != null) { | |
577 StackTraceElement[] stackTraces = thread.getStackTrace(); | |
578 if (stackTraces.length > 0) { | |
579 Logging.d(TAG, threadName + " stacks trace:"); | |
580 for (StackTraceElement stackTrace : stackTraces) { | |
581 Logging.d(TAG, stackTrace.toString()); | |
582 } | |
583 } | |
584 } | |
585 } | |
586 | |
587 public static synchronized void printStackTraces() { | |
588 if (instance == null) { | |
589 return; | |
590 } | |
591 printStackTrace(renderFrameThread, "Render frame thread"); | |
592 printStackTrace(drawThread, "Draw thread"); | |
593 } | |
594 | |
568 @SuppressLint("NewApi") | 595 @SuppressLint("NewApi") |
569 @Override | 596 @Override |
570 public void onSurfaceCreated(GL10 unused, EGLConfig config) { | 597 public void onSurfaceCreated(GL10 unused, EGLConfig config) { |
571 Logging.d(TAG, "VideoRendererGui.onSurfaceCreated"); | 598 Logging.d(TAG, "VideoRendererGui.onSurfaceCreated"); |
572 // Store render EGL context. | 599 // Store render EGL context. |
573 if (CURRENT_SDK_VERSION >= EGL14_SDK_VERSION) { | 600 if (CURRENT_SDK_VERSION >= EGL14_SDK_VERSION) { |
574 synchronized (VideoRendererGui.class) { | 601 synchronized (VideoRendererGui.class) { |
575 eglContext = EGL14.eglGetCurrentContext(); | 602 eglContext = EGL14.eglGetCurrentContext(); |
576 Logging.d(TAG, "VideoRendererGui EGL Context: " + eglContext); | 603 Logging.d(TAG, "VideoRendererGui EGL Context: " + eglContext); |
577 } | 604 } |
(...skipping 28 matching lines...) Expand all Loading... | |
606 screenHeight = height; | 633 screenHeight = height; |
607 synchronized (yuvImageRenderers) { | 634 synchronized (yuvImageRenderers) { |
608 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { | 635 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { |
609 yuvImageRenderer.setScreenSize(screenWidth, screenHeight); | 636 yuvImageRenderer.setScreenSize(screenWidth, screenHeight); |
610 } | 637 } |
611 } | 638 } |
612 } | 639 } |
613 | 640 |
614 @Override | 641 @Override |
615 public void onDrawFrame(GL10 unused) { | 642 public void onDrawFrame(GL10 unused) { |
643 if (drawThread == null) { | |
644 drawThread = Thread.currentThread(); | |
645 } | |
616 GLES20.glViewport(0, 0, screenWidth, screenHeight); | 646 GLES20.glViewport(0, 0, screenWidth, screenHeight); |
617 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); | 647 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); |
618 synchronized (yuvImageRenderers) { | 648 synchronized (yuvImageRenderers) { |
619 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { | 649 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) { |
620 yuvImageRenderer.draw(drawer); | 650 yuvImageRenderer.draw(drawer); |
621 } | 651 } |
622 } | 652 } |
623 } | 653 } |
624 | 654 |
625 } | 655 } |
OLD | NEW |