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

Side by Side Diff: webrtc/api/android/java/src/org/webrtc/VideoRendererGui.java

Issue 2106333005: Revert of Combine webrtc/api/java/android and webrtc/api/java/src. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 5 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
(Empty)
1 /*
2 * Copyright 2014 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 package org.webrtc;
12
13 import java.util.ArrayList;
14 import java.util.concurrent.CountDownLatch;
15
16 import javax.microedition.khronos.egl.EGLConfig;
17 import javax.microedition.khronos.egl.EGL10;
18 import javax.microedition.khronos.egl.EGLContext;
19 import javax.microedition.khronos.opengles.GL10;
20
21 import android.annotation.SuppressLint;
22 import android.graphics.Point;
23 import android.graphics.Rect;
24 import android.opengl.EGL14;
25 import android.opengl.GLES20;
26 import android.opengl.GLSurfaceView;
27
28 import org.webrtc.Logging;
29 import org.webrtc.VideoRenderer.I420Frame;
30
31 /**
32 * Efficiently renders YUV frames using the GPU for CSC.
33 * Clients will want first to call setView() to pass GLSurfaceView
34 * and then for each video stream either create instance of VideoRenderer using
35 * createGui() call or VideoRenderer.Callbacks interface using create() call.
36 * Only one instance of the class can be created.
37 */
38 public class VideoRendererGui implements GLSurfaceView.Renderer {
39 // |instance|, |instance.surface|, |eglContext|, and |eglContextReady| are syn chronized on
40 // |VideoRendererGui.class|.
41 private static VideoRendererGui instance = null;
42 private static Runnable eglContextReady = null;
43 private static final String TAG = "VideoRendererGui";
44 private GLSurfaceView surface;
45 private static EglBase.Context eglContext = null;
46 // Indicates if SurfaceView.Renderer.onSurfaceCreated was called.
47 // If true then for every newly created yuv image renderer createTexture()
48 // should be called. The variable is accessed on multiple threads and
49 // all accesses are synchronized on yuvImageRenderers' object lock.
50 private boolean onSurfaceCreatedCalled;
51 private int screenWidth;
52 private int screenHeight;
53 // List of yuv renderers.
54 private final ArrayList<YuvImageRenderer> yuvImageRenderers;
55 // Render and draw threads.
56 private static Thread renderFrameThread;
57 private static Thread drawThread;
58
59 private VideoRendererGui(GLSurfaceView surface) {
60 this.surface = surface;
61 // Create an OpenGL ES 2.0 context.
62 surface.setPreserveEGLContextOnPause(true);
63 surface.setEGLContextClientVersion(2);
64 surface.setRenderer(this);
65 surface.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
66
67 yuvImageRenderers = new ArrayList<YuvImageRenderer>();
68 }
69
70 /**
71 * Class used to display stream of YUV420 frames at particular location
72 * on a screen. New video frames are sent to display using renderFrame()
73 * call.
74 */
75 private static class YuvImageRenderer implements VideoRenderer.Callbacks {
76 // |surface| is synchronized on |this|.
77 private GLSurfaceView surface;
78 private int id;
79 // TODO(magjed): Delete GL resources in release(). Must be synchronized with draw(). We are
80 // currently leaking resources to avoid a rare crash in release() where the EGLContext has
81 // become invalid beforehand.
82 private int[] yuvTextures = { 0, 0, 0 };
83 private final RendererCommon.YuvUploader yuvUploader = new RendererCommon.Yu vUploader();
84 private final RendererCommon.GlDrawer drawer;
85 // Resources for making a deep copy of incoming OES texture frame.
86 private GlTextureFrameBuffer textureCopy;
87
88 // Pending frame to render. Serves as a queue with size 1. |pendingFrame| is accessed by two
89 // threads - frames are received in renderFrame() and consumed in draw(). Fr ames are dropped in
90 // renderFrame() if the previous frame has not been rendered yet.
91 private I420Frame pendingFrame;
92 private final Object pendingFrameLock = new Object();
93 // Type of video frame used for recent frame rendering.
94 private static enum RendererType { RENDERER_YUV, RENDERER_TEXTURE };
95 private RendererType rendererType;
96 private RendererCommon.ScalingType scalingType;
97 private boolean mirror;
98 private RendererCommon.RendererEvents rendererEvents;
99 // Flag if renderFrame() was ever called.
100 boolean seenFrame;
101 // Total number of video frames received in renderFrame() call.
102 private int framesReceived;
103 // Number of video frames dropped by renderFrame() because previous
104 // frame has not been rendered yet.
105 private int framesDropped;
106 // Number of rendered video frames.
107 private int framesRendered;
108 // Time in ns when the first video frame was rendered.
109 private long startTimeNs = -1;
110 // Time in ns spent in draw() function.
111 private long drawTimeNs;
112 // Time in ns spent in draw() copying resources from |pendingFrame| - includ ing uploading frame
113 // data to rendering planes.
114 private long copyTimeNs;
115 // The allowed view area in percentage of screen size.
116 private final Rect layoutInPercentage;
117 // The actual view area in pixels. It is a centered subrectangle of the rect angle defined by
118 // |layoutInPercentage|.
119 private final Rect displayLayout = new Rect();
120 // Cached layout transformation matrix, calculated from current layout param eters.
121 private float[] layoutMatrix;
122 // Flag if layout transformation matrix update is needed.
123 private boolean updateLayoutProperties;
124 // Layout properties update lock. Guards |updateLayoutProperties|, |screenWi dth|,
125 // |screenHeight|, |videoWidth|, |videoHeight|, |rotationDegree|, |scalingTy pe|, and |mirror|.
126 private final Object updateLayoutLock = new Object();
127 // Texture sampling matrix.
128 private float[] rotatedSamplingMatrix;
129 // Viewport dimensions.
130 private int screenWidth;
131 private int screenHeight;
132 // Video dimension.
133 private int videoWidth;
134 private int videoHeight;
135
136 // This is the degree that the frame should be rotated clockwisely to have
137 // it rendered up right.
138 private int rotationDegree;
139
140 private YuvImageRenderer(
141 GLSurfaceView surface, int id,
142 int x, int y, int width, int height,
143 RendererCommon.ScalingType scalingType, boolean mirror, RendererCommon.G lDrawer drawer) {
144 Logging.d(TAG, "YuvImageRenderer.Create id: " + id);
145 this.surface = surface;
146 this.id = id;
147 this.scalingType = scalingType;
148 this.mirror = mirror;
149 this.drawer = drawer;
150 layoutInPercentage = new Rect(x, y, Math.min(100, x + width), Math.min(100 , y + height));
151 updateLayoutProperties = false;
152 rotationDegree = 0;
153 }
154
155 public synchronized void reset() {
156 seenFrame = false;
157 }
158
159 private synchronized void release() {
160 surface = null;
161 drawer.release();
162 synchronized (pendingFrameLock) {
163 if (pendingFrame != null) {
164 VideoRenderer.renderFrameDone(pendingFrame);
165 pendingFrame = null;
166 }
167 }
168 }
169
170 private void createTextures() {
171 Logging.d(TAG, " YuvImageRenderer.createTextures " + id + " on GL thread: " +
172 Thread.currentThread().getId());
173
174 // Generate 3 texture ids for Y/U/V and place them into |yuvTextures|.
175 for (int i = 0; i < 3; i++) {
176 yuvTextures[i] = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D);
177 }
178 // Generate texture and framebuffer for offscreen texture copy.
179 textureCopy = new GlTextureFrameBuffer(GLES20.GL_RGB);
180 }
181
182 private void updateLayoutMatrix() {
183 synchronized(updateLayoutLock) {
184 if (!updateLayoutProperties) {
185 return;
186 }
187 // Initialize to maximum allowed area. Round to integer coordinates inwa rds the layout
188 // bounding box (ceil left/top and floor right/bottom) to not break cons traints.
189 displayLayout.set(
190 (screenWidth * layoutInPercentage.left + 99) / 100,
191 (screenHeight * layoutInPercentage.top + 99) / 100,
192 (screenWidth * layoutInPercentage.right) / 100,
193 (screenHeight * layoutInPercentage.bottom) / 100);
194 Logging.d(TAG, "ID: " + id + ". AdjustTextureCoords. Allowed display si ze: "
195 + displayLayout.width() + " x " + displayLayout.height() + ". Video: " + videoWidth
196 + " x " + videoHeight + ". Rotation: " + rotationDegree + ". Mirror: " + mirror);
197 final float videoAspectRatio = (rotationDegree % 180 == 0)
198 ? (float) videoWidth / videoHeight
199 : (float) videoHeight / videoWidth;
200 // Adjust display size based on |scalingType|.
201 final Point displaySize = RendererCommon.getDisplaySize(scalingType,
202 videoAspectRatio, displayLayout.width(), displayLayout.height());
203 displayLayout.inset((displayLayout.width() - displaySize.x) / 2,
204 (displayLayout.height() - displaySize.y) / 2);
205 Logging.d(TAG, " Adjusted display size: " + displayLayout.width() + " x "
206 + displayLayout.height());
207 layoutMatrix = RendererCommon.getLayoutMatrix(
208 mirror, videoAspectRatio, (float) displayLayout.width() / displayLay out.height());
209 updateLayoutProperties = false;
210 Logging.d(TAG, " AdjustTextureCoords done");
211 }
212 }
213
214 private void draw() {
215 if (!seenFrame) {
216 // No frame received yet - nothing to render.
217 return;
218 }
219 long now = System.nanoTime();
220
221 final boolean isNewFrame;
222 synchronized (pendingFrameLock) {
223 isNewFrame = (pendingFrame != null);
224 if (isNewFrame && startTimeNs == -1) {
225 startTimeNs = now;
226 }
227
228 if (isNewFrame) {
229 rotatedSamplingMatrix = RendererCommon.rotateTextureMatrix(
230 pendingFrame.samplingMatrix, pendingFrame.rotationDegree);
231 if (pendingFrame.yuvFrame) {
232 rendererType = RendererType.RENDERER_YUV;
233 yuvUploader.uploadYuvData(yuvTextures, pendingFrame.width, pendingFr ame.height,
234 pendingFrame.yuvStrides, pendingFrame.yuvPlanes);
235 } else {
236 rendererType = RendererType.RENDERER_TEXTURE;
237 // External texture rendering. Make a deep copy of the external text ure.
238 // Reallocate offscreen texture if necessary.
239 textureCopy.setSize(pendingFrame.rotatedWidth(), pendingFrame.rotate dHeight());
240
241 // Bind our offscreen framebuffer.
242 GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, textureCopy.getFrame BufferId());
243 GlUtil.checkNoGLES2Error("glBindFramebuffer");
244
245 // Copy the OES texture content. This will also normalize the sampli ng matrix.
246 drawer.drawOes(pendingFrame.textureId, rotatedSamplingMatrix,
247 textureCopy.getWidth(), textureCopy.getHeight(),
248 0, 0, textureCopy.getWidth(), textureCopy.getHeight());
249 rotatedSamplingMatrix = RendererCommon.identityMatrix();
250
251 // Restore normal framebuffer.
252 GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
253 GLES20.glFinish();
254 }
255 copyTimeNs += (System.nanoTime() - now);
256 VideoRenderer.renderFrameDone(pendingFrame);
257 pendingFrame = null;
258 }
259 }
260
261 updateLayoutMatrix();
262 final float[] texMatrix =
263 RendererCommon.multiplyMatrices(rotatedSamplingMatrix, layoutMatrix);
264 // OpenGL defaults to lower left origin - flip viewport position verticall y.
265 final int viewportY = screenHeight - displayLayout.bottom;
266 if (rendererType == RendererType.RENDERER_YUV) {
267 drawer.drawYuv(yuvTextures, texMatrix, videoWidth, videoHeight,
268 displayLayout.left, viewportY, displayLayout.width(), displayLayout. height());
269 } else {
270 drawer.drawRgb(textureCopy.getTextureId(), texMatrix, videoWidth, videoH eight,
271 displayLayout.left, viewportY, displayLayout.width(), displayLayout. height());
272 }
273
274 if (isNewFrame) {
275 framesRendered++;
276 drawTimeNs += (System.nanoTime() - now);
277 if ((framesRendered % 300) == 0) {
278 logStatistics();
279 }
280 }
281 }
282
283 private void logStatistics() {
284 long timeSinceFirstFrameNs = System.nanoTime() - startTimeNs;
285 Logging.d(TAG, "ID: " + id + ". Type: " + rendererType +
286 ". Frames received: " + framesReceived +
287 ". Dropped: " + framesDropped + ". Rendered: " + framesRendered);
288 if (framesReceived > 0 && framesRendered > 0) {
289 Logging.d(TAG, "Duration: " + (int)(timeSinceFirstFrameNs / 1e6) +
290 " ms. FPS: " + framesRendered * 1e9 / timeSinceFirstFrameNs);
291 Logging.d(TAG, "Draw time: " +
292 (int) (drawTimeNs / (1000 * framesRendered)) + " us. Copy time: " +
293 (int) (copyTimeNs / (1000 * framesReceived)) + " us");
294 }
295 }
296
297 public void setScreenSize(final int screenWidth, final int screenHeight) {
298 synchronized(updateLayoutLock) {
299 if (screenWidth == this.screenWidth && screenHeight == this.screenHeight ) {
300 return;
301 }
302 Logging.d(TAG, "ID: " + id + ". YuvImageRenderer.setScreenSize: " +
303 screenWidth + " x " + screenHeight);
304 this.screenWidth = screenWidth;
305 this.screenHeight = screenHeight;
306 updateLayoutProperties = true;
307 }
308 }
309
310 public void setPosition(int x, int y, int width, int height,
311 RendererCommon.ScalingType scalingType, boolean mirror) {
312 final Rect layoutInPercentage =
313 new Rect(x, y, Math.min(100, x + width), Math.min(100, y + height));
314 synchronized(updateLayoutLock) {
315 if (layoutInPercentage.equals(this.layoutInPercentage) && scalingType == this.scalingType
316 && mirror == this.mirror) {
317 return;
318 }
319 Logging.d(TAG, "ID: " + id + ". YuvImageRenderer.setPosition: (" + x + " , " + y +
320 ") " + width + " x " + height + ". Scaling: " + scalingType +
321 ". Mirror: " + mirror);
322 this.layoutInPercentage.set(layoutInPercentage);
323 this.scalingType = scalingType;
324 this.mirror = mirror;
325 updateLayoutProperties = true;
326 }
327 }
328
329 private void setSize(final int videoWidth, final int videoHeight, final int rotation) {
330 if (videoWidth == this.videoWidth && videoHeight == this.videoHeight
331 && rotation == rotationDegree) {
332 return;
333 }
334 if (rendererEvents != null) {
335 Logging.d(TAG, "ID: " + id +
336 ". Reporting frame resolution changed to " + videoWidth + " x " + vi deoHeight);
337 rendererEvents.onFrameResolutionChanged(videoWidth, videoHeight, rotatio n);
338 }
339
340 synchronized (updateLayoutLock) {
341 Logging.d(TAG, "ID: " + id + ". YuvImageRenderer.setSize: " +
342 videoWidth + " x " + videoHeight + " rotation " + rotation);
343
344 this.videoWidth = videoWidth;
345 this.videoHeight = videoHeight;
346 rotationDegree = rotation;
347 updateLayoutProperties = true;
348 Logging.d(TAG, " YuvImageRenderer.setSize done.");
349 }
350 }
351
352 @Override
353 public synchronized void renderFrame(I420Frame frame) {
354 if (surface == null) {
355 // This object has been released.
356 VideoRenderer.renderFrameDone(frame);
357 return;
358 }
359 if (renderFrameThread == null) {
360 renderFrameThread = Thread.currentThread();
361 }
362 if (!seenFrame && rendererEvents != null) {
363 Logging.d(TAG, "ID: " + id + ". Reporting first rendered frame.");
364 rendererEvents.onFirstFrameRendered();
365 }
366 framesReceived++;
367 synchronized (pendingFrameLock) {
368 // Check input frame parameters.
369 if (frame.yuvFrame) {
370 if (frame.yuvStrides[0] < frame.width ||
371 frame.yuvStrides[1] < frame.width / 2 ||
372 frame.yuvStrides[2] < frame.width / 2) {
373 Logging.e(TAG, "Incorrect strides " + frame.yuvStrides[0] + ", " +
374 frame.yuvStrides[1] + ", " + frame.yuvStrides[2]);
375 VideoRenderer.renderFrameDone(frame);
376 return;
377 }
378 }
379
380 if (pendingFrame != null) {
381 // Skip rendering of this frame if previous frame was not rendered yet .
382 framesDropped++;
383 VideoRenderer.renderFrameDone(frame);
384 seenFrame = true;
385 return;
386 }
387 pendingFrame = frame;
388 }
389 setSize(frame.width, frame.height, frame.rotationDegree);
390 seenFrame = true;
391
392 // Request rendering.
393 surface.requestRender();
394 }
395 }
396
397 /** Passes GLSurfaceView to video renderer. */
398 public static synchronized void setView(GLSurfaceView surface,
399 Runnable eglContextReadyCallback) {
400 Logging.d(TAG, "VideoRendererGui.setView");
401 instance = new VideoRendererGui(surface);
402 eglContextReady = eglContextReadyCallback;
403 }
404
405 public static synchronized EglBase.Context getEglBaseContext() {
406 return eglContext;
407 }
408
409 /** Releases GLSurfaceView video renderer. */
410 public static synchronized void dispose() {
411 if (instance == null){
412 return;
413 }
414 Logging.d(TAG, "VideoRendererGui.dispose");
415 synchronized (instance.yuvImageRenderers) {
416 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) {
417 yuvImageRenderer.release();
418 }
419 instance.yuvImageRenderers.clear();
420 }
421 renderFrameThread = null;
422 drawThread = null;
423 instance.surface = null;
424 eglContext = null;
425 eglContextReady = null;
426 instance = null;
427 }
428
429 /**
430 * Creates VideoRenderer with top left corner at (x, y) and resolution
431 * (width, height). All parameters are in percentage of screen resolution.
432 */
433 public static VideoRenderer createGui(int x, int y, int width, int height,
434 RendererCommon.ScalingType scalingType, boolean mirror) throws Exception {
435 YuvImageRenderer javaGuiRenderer = create(
436 x, y, width, height, scalingType, mirror);
437 return new VideoRenderer(javaGuiRenderer);
438 }
439
440 public static VideoRenderer.Callbacks createGuiRenderer(
441 int x, int y, int width, int height,
442 RendererCommon.ScalingType scalingType, boolean mirror) {
443 return create(x, y, width, height, scalingType, mirror);
444 }
445
446 /**
447 * Creates VideoRenderer.Callbacks with top left corner at (x, y) and
448 * resolution (width, height). All parameters are in percentage of
449 * screen resolution.
450 */
451 public static synchronized YuvImageRenderer create(int x, int y, int width, in t height,
452 RendererCommon.ScalingType scalingType, boolean mirror) {
453 return create(x, y, width, height, scalingType, mirror, new GlRectDrawer());
454 }
455
456 /**
457 * Creates VideoRenderer.Callbacks with top left corner at (x, y) and resoluti on (width, height).
458 * All parameters are in percentage of screen resolution. The custom |drawer| will be used for
459 * drawing frames on the EGLSurface. This class is responsible for calling rel ease() on |drawer|.
460 */
461 public static synchronized YuvImageRenderer create(int x, int y, int width, in t height,
462 RendererCommon.ScalingType scalingType, boolean mirror, RendererCommon.GlD rawer drawer) {
463 // Check display region parameters.
464 if (x < 0 || x > 100 || y < 0 || y > 100 ||
465 width < 0 || width > 100 || height < 0 || height > 100 ||
466 x + width > 100 || y + height > 100) {
467 throw new RuntimeException("Incorrect window parameters.");
468 }
469
470 if (instance == null) {
471 throw new RuntimeException(
472 "Attempt to create yuv renderer before setting GLSurfaceView");
473 }
474 final YuvImageRenderer yuvImageRenderer = new YuvImageRenderer(
475 instance.surface, instance.yuvImageRenderers.size(),
476 x, y, width, height, scalingType, mirror, drawer);
477 synchronized (instance.yuvImageRenderers) {
478 if (instance.onSurfaceCreatedCalled) {
479 // onSurfaceCreated has already been called for VideoRendererGui -
480 // need to create texture for new image and add image to the
481 // rendering list.
482 final CountDownLatch countDownLatch = new CountDownLatch(1);
483 instance.surface.queueEvent(new Runnable() {
484 @Override
485 public void run() {
486 yuvImageRenderer.createTextures();
487 yuvImageRenderer.setScreenSize(
488 instance.screenWidth, instance.screenHeight);
489 countDownLatch.countDown();
490 }
491 });
492 // Wait for task completion.
493 try {
494 countDownLatch.await();
495 } catch (InterruptedException e) {
496 throw new RuntimeException(e);
497 }
498 }
499 // Add yuv renderer to rendering list.
500 instance.yuvImageRenderers.add(yuvImageRenderer);
501 }
502 return yuvImageRenderer;
503 }
504
505 public static synchronized void update(
506 VideoRenderer.Callbacks renderer, int x, int y, int width, int height,
507 RendererCommon.ScalingType scalingType, boolean mirror) {
508 Logging.d(TAG, "VideoRendererGui.update");
509 if (instance == null) {
510 throw new RuntimeException(
511 "Attempt to update yuv renderer before setting GLSurfaceView");
512 }
513 synchronized (instance.yuvImageRenderers) {
514 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) {
515 if (yuvImageRenderer == renderer) {
516 yuvImageRenderer.setPosition(x, y, width, height, scalingType, mirror) ;
517 }
518 }
519 }
520 }
521
522 public static synchronized void setRendererEvents(
523 VideoRenderer.Callbacks renderer, RendererCommon.RendererEvents rendererEv ents) {
524 Logging.d(TAG, "VideoRendererGui.setRendererEvents");
525 if (instance == null) {
526 throw new RuntimeException(
527 "Attempt to set renderer events before setting GLSurfaceView");
528 }
529 synchronized (instance.yuvImageRenderers) {
530 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) {
531 if (yuvImageRenderer == renderer) {
532 yuvImageRenderer.rendererEvents = rendererEvents;
533 }
534 }
535 }
536 }
537
538 public static synchronized void remove(VideoRenderer.Callbacks renderer) {
539 Logging.d(TAG, "VideoRendererGui.remove");
540 if (instance == null) {
541 throw new RuntimeException(
542 "Attempt to remove renderer before setting GLSurfaceView");
543 }
544 synchronized (instance.yuvImageRenderers) {
545 final int index = instance.yuvImageRenderers.indexOf(renderer);
546 if (index == -1) {
547 Logging.w(TAG, "Couldn't remove renderer (not present in current list)") ;
548 } else {
549 instance.yuvImageRenderers.remove(index).release();
550 }
551 }
552 }
553
554 public static synchronized void reset(VideoRenderer.Callbacks renderer) {
555 Logging.d(TAG, "VideoRendererGui.reset");
556 if (instance == null) {
557 throw new RuntimeException(
558 "Attempt to reset renderer before setting GLSurfaceView");
559 }
560 synchronized (instance.yuvImageRenderers) {
561 for (YuvImageRenderer yuvImageRenderer : instance.yuvImageRenderers) {
562 if (yuvImageRenderer == renderer) {
563 yuvImageRenderer.reset();
564 }
565 }
566 }
567 }
568
569 private static void printStackTrace(Thread thread, String threadName) {
570 if (thread != null) {
571 StackTraceElement[] stackTraces = thread.getStackTrace();
572 if (stackTraces.length > 0) {
573 Logging.d(TAG, threadName + " stacks trace:");
574 for (StackTraceElement stackTrace : stackTraces) {
575 Logging.d(TAG, stackTrace.toString());
576 }
577 }
578 }
579 }
580
581 public static synchronized void printStackTraces() {
582 if (instance == null) {
583 return;
584 }
585 printStackTrace(renderFrameThread, "Render frame thread");
586 printStackTrace(drawThread, "Draw thread");
587 }
588
589 @SuppressLint("NewApi")
590 @Override
591 public void onSurfaceCreated(GL10 unused, EGLConfig config) {
592 Logging.d(TAG, "VideoRendererGui.onSurfaceCreated");
593 // Store render EGL context.
594 synchronized (VideoRendererGui.class) {
595 if (EglBase14.isEGL14Supported()) {
596 eglContext = new EglBase14.Context(EGL14.eglGetCurrentContext());
597 } else {
598 eglContext = new EglBase10.Context(((EGL10) EGLContext.getEGL()).eglGetC urrentContext());
599 }
600
601 Logging.d(TAG, "VideoRendererGui EGL Context: " + eglContext);
602 }
603
604 synchronized (yuvImageRenderers) {
605 // Create textures for all images.
606 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) {
607 yuvImageRenderer.createTextures();
608 }
609 onSurfaceCreatedCalled = true;
610 }
611 GlUtil.checkNoGLES2Error("onSurfaceCreated done");
612 GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
613 GLES20.glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
614
615 // Fire EGL context ready event.
616 synchronized (VideoRendererGui.class) {
617 if (eglContextReady != null) {
618 eglContextReady.run();
619 }
620 }
621 }
622
623 @Override
624 public void onSurfaceChanged(GL10 unused, int width, int height) {
625 Logging.d(TAG, "VideoRendererGui.onSurfaceChanged: " +
626 width + " x " + height + " ");
627 screenWidth = width;
628 screenHeight = height;
629 synchronized (yuvImageRenderers) {
630 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) {
631 yuvImageRenderer.setScreenSize(screenWidth, screenHeight);
632 }
633 }
634 }
635
636 @Override
637 public void onDrawFrame(GL10 unused) {
638 if (drawThread == null) {
639 drawThread = Thread.currentThread();
640 }
641 GLES20.glViewport(0, 0, screenWidth, screenHeight);
642 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
643 synchronized (yuvImageRenderers) {
644 for (YuvImageRenderer yuvImageRenderer : yuvImageRenderers) {
645 yuvImageRenderer.draw();
646 }
647 }
648 }
649
650 }
OLDNEW
« no previous file with comments | « webrtc/api/android/java/src/org/webrtc/VideoRenderer.java ('k') | webrtc/api/android/java/src/org/webrtc/VideoSource.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698