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

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

Issue 2456873002: Android EglRenderer: Add Bitmap frame listener functionality (Closed)
Patch Set: Add spaces. Created 4 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 | « webrtc/api/BUILD.gn ('k') | webrtc/api/android/jni/eglrenderer_jni.cc » ('j') | 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 * Copyright 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2016 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 package org.webrtc; 11 package org.webrtc;
12 12
13 import android.graphics.Bitmap;
13 import android.graphics.SurfaceTexture; 14 import android.graphics.SurfaceTexture;
14 import android.opengl.GLES20; 15 import android.opengl.GLES20;
15 import android.os.Handler; 16 import android.os.Handler;
16 import android.os.HandlerThread; 17 import android.os.HandlerThread;
17 import android.os.Looper; 18 import android.os.Looper;
18 import android.view.Surface; 19 import android.view.Surface;
20 import java.nio.IntBuffer;
21 import java.util.ArrayList;
22 import java.util.Iterator;
19 import java.util.concurrent.CountDownLatch; 23 import java.util.concurrent.CountDownLatch;
20 import java.util.concurrent.TimeUnit; 24 import java.util.concurrent.TimeUnit;
21 25
22 /** 26 /**
23 * Implements org.webrtc.VideoRenderer.Callbacks by displaying the video stream on an EGL Surface. 27 * Implements org.webrtc.VideoRenderer.Callbacks by displaying the video stream on an EGL Surface.
24 * This class is intended to be used as a helper class for rendering on SurfaceV iews and 28 * This class is intended to be used as a helper class for rendering on SurfaceV iews and
25 * TextureViews. 29 * TextureViews.
26 */ 30 */
27 public class EglRenderer implements VideoRenderer.Callbacks { 31 public class EglRenderer implements VideoRenderer.Callbacks {
28 private static final String TAG = "EglRenderer"; 32 private static final String TAG = "EglRenderer";
29 private static final long LOG_INTERVAL_SEC = 4; 33 private static final long LOG_INTERVAL_SEC = 4;
30 private static final int MAX_SURFACE_CLEAR_COUNT = 3; 34 private static final int MAX_SURFACE_CLEAR_COUNT = 3;
31 35
36 public interface FrameListener { void onFrame(Bitmap frame); }
37
38 private static class ScaleAndFrameListener {
39 public final float scale;
40 public final FrameListener listener;
41
42 public ScaleAndFrameListener(float scale, FrameListener listener) {
43 this.scale = scale;
44 this.listener = listener;
45 }
46 }
47
32 private class EglSurfaceCreation implements Runnable { 48 private class EglSurfaceCreation implements Runnable {
33 private Object surface; 49 private Object surface;
34 50
35 public synchronized void setSurface(Object surface) { 51 public synchronized void setSurface(Object surface) {
36 this.surface = surface; 52 this.surface = surface;
37 } 53 }
38 54
39 @Override 55 @Override
40 public synchronized void run() { 56 public synchronized void run() {
41 if (surface != null && eglBase != null && !eglBase.hasSurface()) { 57 if (surface != null && eglBase != null && !eglBase.hasSurface()) {
(...skipping 11 matching lines...) Expand all
53 } 69 }
54 } 70 }
55 71
56 private final String name; 72 private final String name;
57 73
58 // |renderThreadHandler| is a handler for communicating with |renderThread|, a nd is synchronized 74 // |renderThreadHandler| is a handler for communicating with |renderThread|, a nd is synchronized
59 // on |handlerLock|. 75 // on |handlerLock|.
60 private final Object handlerLock = new Object(); 76 private final Object handlerLock = new Object();
61 private Handler renderThreadHandler; 77 private Handler renderThreadHandler;
62 78
79 private final Object frameListenerLock = new Object();
80 private final ArrayList<ScaleAndFrameListener> frameListeners = new ArrayList< >();
81
63 // Variables for fps reduction. 82 // Variables for fps reduction.
64 private final Object fpsReductionLock = new Object(); 83 private final Object fpsReductionLock = new Object();
65 // Time for when next frame should be rendered. 84 // Time for when next frame should be rendered.
66 private long nextFrameTimeNs; 85 private long nextFrameTimeNs;
67 // Minimum duration between frames when fps reduction is active, or -1 if vide o is completely 86 // Minimum duration between frames when fps reduction is active, or -1 if vide o is completely
68 // paused. 87 // paused.
69 private long minRenderPeriodNs; 88 private long minRenderPeriodNs;
70 89
71 // EGL and GL resources for drawing YUV/OES textures. After initilization, the se are only accessed 90 // EGL and GL resources for drawing YUV/OES textures. After initilization, the se are only accessed
72 // from the render thread. 91 // from the render thread.
73 private EglBase eglBase; 92 private EglBase eglBase;
74 private final RendererCommon.YuvUploader yuvUploader = new RendererCommon.YuvU ploader(); 93 private final RendererCommon.YuvUploader yuvUploader = new RendererCommon.YuvU ploader();
94 private YuvConverter yuvConverter;
magjed_webrtc 2016/11/01 18:06:46 Remove this now since you didn't end up using it.
sakal 2016/11/02 08:34:29 Done.
75 private RendererCommon.GlDrawer drawer; 95 private RendererCommon.GlDrawer drawer;
76 // Texture ids for YUV frames. Allocated on first arrival of a YUV frame. 96 // Texture ids for YUV frames. Allocated on first arrival of a YUV frame.
77 private int[] yuvTextures = null; 97 private int[] yuvTextures = null;
78 98
79 // Pending frame to render. Serves as a queue with size 1. Synchronized on |fr ameLock|. 99 // Pending frame to render. Serves as a queue with size 1. Synchronized on |fr ameLock|.
80 private final Object frameLock = new Object(); 100 private final Object frameLock = new Object();
81 private VideoRenderer.I420Frame pendingFrame; 101 private VideoRenderer.I420Frame pendingFrame;
82 102
83 // These variables are synchronized on |layoutLock|. 103 // These variables are synchronized on |layoutLock|.
84 private final Object layoutLock = new Object(); 104 private final Object layoutLock = new Object();
(...skipping 12 matching lines...) Expand all
97 private int framesDropped; 117 private int framesDropped;
98 // Number of rendered video frames. 118 // Number of rendered video frames.
99 private int framesRendered; 119 private int framesRendered;
100 // Start time for counting these statistics, or 0 if we haven't started measur ing yet. 120 // Start time for counting these statistics, or 0 if we haven't started measur ing yet.
101 private long statisticsStartTimeNs; 121 private long statisticsStartTimeNs;
102 // Time in ns spent in renderFrameOnRenderThread() function. 122 // Time in ns spent in renderFrameOnRenderThread() function.
103 private long renderTimeNs; 123 private long renderTimeNs;
104 // Time in ns spent by the render thread in the swapBuffers() function. 124 // Time in ns spent by the render thread in the swapBuffers() function.
105 private long renderSwapBufferTimeNs; 125 private long renderSwapBufferTimeNs;
106 126
127 // Used for bitmap capturing.
128 private final int[] bitmapTexture = new int[1];
magjed_webrtc 2016/11/01 18:06:46 Keep this as an int instead of int[1]. Same for bi
sakal 2016/11/02 08:34:29 Done.
129 private final int[] bitmapFramebuffer = new int[1];
130 private int bitmapTextureWidth;
131 private int bitmapTextureHeight;
132
107 // Runnable for posting frames to render thread. 133 // Runnable for posting frames to render thread.
108 private final Runnable renderFrameRunnable = new Runnable() { 134 private final Runnable renderFrameRunnable = new Runnable() {
109 @Override 135 @Override
110 public void run() { 136 public void run() {
111 renderFrameOnRenderThread(); 137 renderFrameOnRenderThread();
112 } 138 }
113 }; 139 };
114 140
115 private final Runnable logStatisticsRunnable = new Runnable() { 141 private final Runnable logStatisticsRunnable = new Runnable() {
116 @Override 142 @Override
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 } 235 }
210 renderThreadHandler.removeCallbacks(logStatisticsRunnable); 236 renderThreadHandler.removeCallbacks(logStatisticsRunnable);
211 // Release EGL and GL resources on render thread. 237 // Release EGL and GL resources on render thread.
212 renderThreadHandler.postAtFrontOfQueue(new Runnable() { 238 renderThreadHandler.postAtFrontOfQueue(new Runnable() {
213 @Override 239 @Override
214 public void run() { 240 public void run() {
215 if (drawer != null) { 241 if (drawer != null) {
216 drawer.release(); 242 drawer.release();
217 drawer = null; 243 drawer = null;
218 } 244 }
245 if (yuvConverter != null) {
246 yuvConverter.release();
247 yuvConverter = null;
248 }
219 if (yuvTextures != null) { 249 if (yuvTextures != null) {
220 GLES20.glDeleteTextures(3, yuvTextures, 0); 250 GLES20.glDeleteTextures(3, yuvTextures, 0);
221 yuvTextures = null; 251 yuvTextures = null;
222 } 252 }
253 GLES20.glDeleteFramebuffers(1, bitmapFramebuffer, 0);
magjed_webrtc 2016/11/01 18:06:46 Add 'if (bitmapFramebuffer[0] != 0)' check here. S
sakal 2016/11/02 08:34:29 "glDeleteFramebuffers silently ignores 0's and nam
254 bitmapFramebuffer[0] = 0;
255 GLES20.glDeleteTextures(1, bitmapTexture, 0);
256 bitmapTexture[0] = 0;
223 if (eglBase != null) { 257 if (eglBase != null) {
224 logD("eglBase detach and release."); 258 logD("eglBase detach and release.");
225 eglBase.detachCurrent(); 259 eglBase.detachCurrent();
226 eglBase.release(); 260 eglBase.release();
227 eglBase = null; 261 eglBase = null;
228 } 262 }
229 eglCleanupBarrier.countDown(); 263 eglCleanupBarrier.countDown();
230 } 264 }
231 }); 265 });
232 final Looper renderLooper = renderThreadHandler.getLooper(); 266 final Looper renderLooper = renderThreadHandler.getLooper();
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 } 360 }
327 361
328 public void disableFpsReduction() { 362 public void disableFpsReduction() {
329 setFpsReduction(Float.POSITIVE_INFINITY /* fps */); 363 setFpsReduction(Float.POSITIVE_INFINITY /* fps */);
330 } 364 }
331 365
332 public void pauseVideo() { 366 public void pauseVideo() {
333 setFpsReduction(0 /* fps */); 367 setFpsReduction(0 /* fps */);
334 } 368 }
335 369
370 /**
371 * Register a callback to be invoked when a new video frame has been received.
372 *
373 * @param listener The callback to be invoked.
374 * @param scale The scale of the Bitmap passed to the callback, or 0 if no Bitmap is
375 * required.
376 */
377 public void addFrameListener(FrameListener listener, float scale) {
378 synchronized (frameListenerLock) {
379 frameListeners.add(new ScaleAndFrameListener(scale, listener));
380 }
381 }
382
383 /**
384 * Remove any pending callback that was added with addFrameListener. If the ca llback is not in
385 * the queue, nothing happens.
386 *
387 * @param runnable The callback to remove.
388 */
389 public void removeFrameListener(FrameListener listener) {
390 synchronized (frameListenerLock) {
391 final Iterator<ScaleAndFrameListener> iter = frameListeners.iterator();
392 while (iter.hasNext()) {
393 if (iter.next().listener == listener) {
394 iter.remove();
395 }
396 }
397 }
398 }
399
336 // VideoRenderer.Callbacks interface. 400 // VideoRenderer.Callbacks interface.
337 @Override 401 @Override
338 public void renderFrame(VideoRenderer.I420Frame frame) { 402 public void renderFrame(VideoRenderer.I420Frame frame) {
339 synchronized (statisticsLock) { 403 synchronized (statisticsLock) {
340 ++framesReceived; 404 ++framesReceived;
341 } 405 }
342 final boolean dropOldFrame; 406 final boolean dropOldFrame;
343 synchronized (handlerLock) { 407 synchronized (handlerLock) {
344 if (renderThreadHandler == null) { 408 if (renderThreadHandler == null) {
345 logD("Dropping frame - Not initialized or already released."); 409 logD("Dropping frame - Not initialized or already released.");
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 frame = pendingFrame; 529 frame = pendingFrame;
466 pendingFrame = null; 530 pendingFrame = null;
467 } 531 }
468 if (eglBase == null || !eglBase.hasSurface()) { 532 if (eglBase == null || !eglBase.hasSurface()) {
469 logD("Dropping frame - No surface"); 533 logD("Dropping frame - No surface");
470 VideoRenderer.renderFrameDone(frame); 534 VideoRenderer.renderFrameDone(frame);
471 return; 535 return;
472 } 536 }
473 537
474 final long startTimeNs = System.nanoTime(); 538 final long startTimeNs = System.nanoTime();
475 float[] texMatrix = 539 final float[] texMatrix =
476 RendererCommon.rotateTextureMatrix(frame.samplingMatrix, frame.rotationD egree); 540 RendererCommon.rotateTextureMatrix(frame.samplingMatrix, frame.rotationD egree);
541 final float[] drawMatrix;
477 542
478 // After a surface size change, the EGLSurface might still have a buffer of the old size in the 543 // After a surface size change, the EGLSurface might still have a buffer of the old size in the
479 // pipeline. Querying the EGLSurface will show if the underlying buffer dime nsions haven't yet 544 // pipeline. Querying the EGLSurface will show if the underlying buffer dime nsions haven't yet
480 // changed. Such a buffer will be rendered incorrectly, so flush it with a b lack frame. 545 // changed. Such a buffer will be rendered incorrectly, so flush it with a b lack frame.
481 synchronized (layoutLock) { 546 synchronized (layoutLock) {
482 int surfaceClearCount = 0; 547 int surfaceClearCount = 0;
483 while (eglBase.surfaceWidth() != surfaceWidth || eglBase.surfaceHeight() ! = surfaceHeight) { 548 while (eglBase.surfaceWidth() != surfaceWidth || eglBase.surfaceHeight() ! = surfaceHeight) {
484 ++surfaceClearCount; 549 ++surfaceClearCount;
485 if (surfaceClearCount > MAX_SURFACE_CLEAR_COUNT) { 550 if (surfaceClearCount > MAX_SURFACE_CLEAR_COUNT) {
486 logD("Failed to get surface of expected size - dropping frame."); 551 logD("Failed to get surface of expected size - dropping frame.");
487 VideoRenderer.renderFrameDone(frame); 552 VideoRenderer.renderFrameDone(frame);
488 return; 553 return;
489 } 554 }
490 logD("Surface size mismatch - clearing surface."); 555 logD("Surface size mismatch - clearing surface. Size: " + eglBase.surfac eWidth() + "x"
556 + eglBase.surfaceHeight() + " Expected: " + surfaceWidth + "x" + sur faceHeight);
491 clearSurfaceOnRenderThread(); 557 clearSurfaceOnRenderThread();
492 } 558 }
493 final float[] layoutMatrix; 559 final float[] layoutMatrix;
494 if (layoutAspectRatio > 0) { 560 if (layoutAspectRatio > 0) {
495 layoutMatrix = RendererCommon.getLayoutMatrix( 561 layoutMatrix = RendererCommon.getLayoutMatrix(
496 mirror, frame.rotatedWidth() / (float) frame.rotatedHeight(), layout AspectRatio); 562 mirror, frame.rotatedWidth() / (float) frame.rotatedHeight(), layout AspectRatio);
497 } else { 563 } else {
498 layoutMatrix = 564 layoutMatrix =
499 mirror ? RendererCommon.horizontalFlipMatrix() : RendererCommon.iden tityMatrix(); 565 mirror ? RendererCommon.horizontalFlipMatrix() : RendererCommon.iden tityMatrix();
500 } 566 }
501 texMatrix = RendererCommon.multiplyMatrices(texMatrix, layoutMatrix); 567 drawMatrix = RendererCommon.multiplyMatrices(texMatrix, layoutMatrix);
502 } 568 }
503 569
504 GLES20.glClearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */) ; 570 GLES20.glClearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */) ;
505 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); 571 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
506 if (frame.yuvFrame) { 572 if (frame.yuvFrame) {
507 // Make sure YUV textures are allocated. 573 // Make sure YUV textures are allocated.
508 if (yuvTextures == null) { 574 if (yuvTextures == null) {
509 yuvTextures = new int[3]; 575 yuvTextures = new int[3];
510 for (int i = 0; i < 3; i++) { 576 for (int i = 0; i < 3; i++) {
511 yuvTextures[i] = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D); 577 yuvTextures[i] = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D);
512 } 578 }
513 } 579 }
514 yuvUploader.uploadYuvData( 580 yuvUploader.uploadYuvData(
515 yuvTextures, frame.width, frame.height, frame.yuvStrides, frame.yuvPla nes); 581 yuvTextures, frame.width, frame.height, frame.yuvStrides, frame.yuvPla nes);
516 drawer.drawYuv(yuvTextures, texMatrix, frame.rotatedWidth(), frame.rotated Height(), 0, 0, 582 drawer.drawYuv(yuvTextures, drawMatrix, frame.rotatedWidth(), frame.rotate dHeight(), 0, 0,
517 surfaceWidth, surfaceHeight); 583 surfaceWidth, surfaceHeight);
518 } else { 584 } else {
519 drawer.drawOes(frame.textureId, texMatrix, frame.rotatedWidth(), frame.rot atedHeight(), 0, 0, 585 drawer.drawOes(frame.textureId, drawMatrix, frame.rotatedWidth(), frame.ro tatedHeight(), 0, 0,
520 surfaceWidth, surfaceHeight); 586 surfaceWidth, surfaceHeight);
521 } 587 }
522 588
589 // Notify callbacks. Make temporary copy of callback list to avoid
magjed_webrtc 2016/11/01 18:06:46 Move this block of code into a helper function. Al
sakal 2016/11/02 08:34:29 Done.
590 // ConcurrentModificationException, in case callbacks call addFramelistener or
591 // removeFrameListener.
592 final ArrayList<ScaleAndFrameListener> tmpList = new ArrayList<>(frameListen ers);
593 frameListeners.clear();
594 for (ScaleAndFrameListener scaleAndListener : tmpList) {
595 final int scaledWidth = (int) (scaleAndListener.scale * frame.rotatedWidth ());
596 final int scaledHeight = (int) (scaleAndListener.scale * frame.rotatedHeig ht());
597 final float[] bitmapMatrix = RendererCommon.multiplyMatrices(
magjed_webrtc 2016/11/01 18:06:46 Move this outside the loop.
sakal 2016/11/02 08:34:29 Done.
598 RendererCommon.multiplyMatrices(texMatrix,
599 mirror ? RendererCommon.horizontalFlipMatrix() : RendererCommon.id entityMatrix()),
600 RendererCommon.verticalFlipMatrix());
601
602 if (scaledWidth == 0 || scaledHeight == 0) {
603 scaleAndListener.listener.onFrame(null);
604 continue;
605 }
606 if (bitmapTexture[0] == 0) {
607 bitmapTexture[0] = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D);
608 bitmapTextureWidth = bitmapTextureHeight = 0;
609 }
610 if (bitmapFramebuffer[0] == 0) {
611 GLES20.glGenFramebuffers(1, bitmapFramebuffer, 0);
612 }
613
614 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, bitmapTexture[0]);
615 if (scaledWidth != bitmapTextureWidth || scaledHeight != bitmapTextureHeig ht) {
magjed_webrtc 2016/11/01 18:06:46 Wait a minute... Maybe you can use the helper clas
sakal 2016/11/02 08:34:29 Done.
616 GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, scaledWidth , scaledHeight, 0,
617 GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
618 bitmapTextureWidth = scaledWidth;
619 bitmapTextureHeight = scaledHeight;
620 }
621 GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, bitmapFramebuffer[0]);
622 GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTAC HMENT0,
623 GLES20.GL_TEXTURE_2D, bitmapTexture[0], 0);
624
625 if (frame.yuvFrame) {
626 drawer.drawYuv(yuvTextures, bitmapMatrix, frame.rotatedWidth(), frame.ro tatedHeight(), 0, 0,
627 scaledWidth, scaledHeight);
628 } else {
629 drawer.drawOes(frame.textureId, bitmapMatrix, frame.rotatedWidth(), fram e.rotatedHeight(),
630 0, 0, scaledWidth, scaledHeight);
631 }
632
633 final IntBuffer bitmapBuffer = IntBuffer.allocate(scaledWidth * scaledHeig ht);
634 GLES20.glViewport(0, 0, scaledWidth, scaledHeight);
635 GLES20.glReadPixels(
636 0, 0, scaledWidth, scaledHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BY TE, bitmapBuffer);
637
638 GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
639 GlUtil.checkNoGLES2Error("EglRenderer.renderFrameOnRenderThread - bitmap c apture");
640
641 // RGBA to ARGB conversion.
642 final int[] bitmapArray = bitmapBuffer.array();
643 nativeABGRToARGB(bitmapArray, scaledWidth, scaledHeight);
644
645 final Bitmap bitmap = Bitmap.createBitmap(
646 bitmapBuffer.array(), scaledWidth, scaledHeight, Bitmap.Config.ARGB_88 88);
647 scaleAndListener.listener.onFrame(bitmap);
648 }
649
523 final long swapBuffersStartTimeNs = System.nanoTime(); 650 final long swapBuffersStartTimeNs = System.nanoTime();
524 eglBase.swapBuffers(); 651 eglBase.swapBuffers();
525 VideoRenderer.renderFrameDone(frame); 652 VideoRenderer.renderFrameDone(frame);
526 653
527 final long currentTimeNs = System.nanoTime(); 654 final long currentTimeNs = System.nanoTime();
528 synchronized (statisticsLock) { 655 synchronized (statisticsLock) {
529 ++framesRendered; 656 ++framesRendered;
530 renderTimeNs += (currentTimeNs - startTimeNs); 657 renderTimeNs += (currentTimeNs - startTimeNs);
531 renderSwapBufferTimeNs += (currentTimeNs - swapBuffersStartTimeNs); 658 renderSwapBufferTimeNs += (currentTimeNs - swapBuffersStartTimeNs);
532 } 659 }
(...skipping 19 matching lines...) Expand all
552 + " Average render time: " + averageTimeAsString(renderTimeNs, framesR endered) + "." 679 + " Average render time: " + averageTimeAsString(renderTimeNs, framesR endered) + "."
553 + " Average swapBuffer time: " 680 + " Average swapBuffer time: "
554 + averageTimeAsString(renderSwapBufferTimeNs, framesRendered) + "."); 681 + averageTimeAsString(renderSwapBufferTimeNs, framesRendered) + ".");
555 resetStatistics(currentTimeNs); 682 resetStatistics(currentTimeNs);
556 } 683 }
557 } 684 }
558 685
559 private void logD(String string) { 686 private void logD(String string) {
560 Logging.d(TAG, name + string); 687 Logging.d(TAG, name + string);
561 } 688 }
689
690 private static native void nativeABGRToARGB(int[] array, int width, int height );
562 } 691 }
OLDNEW
« no previous file with comments | « webrtc/api/BUILD.gn ('k') | webrtc/api/android/jni/eglrenderer_jni.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698