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

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

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