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

Unified Diff: webrtc/sdk/android/api/org/webrtc/EglRenderer.java

Issue 2688843002: EglRenderer: Trigger framelisteners even on dropped frames by default. (Closed)
Patch Set: Changes according to magjed's comments. Created 3 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | webrtc/sdk/android/api/org/webrtc/RendererCommon.java » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/sdk/android/api/org/webrtc/EglRenderer.java
diff --git a/webrtc/sdk/android/api/org/webrtc/EglRenderer.java b/webrtc/sdk/android/api/org/webrtc/EglRenderer.java
index f5c1fe1773ed2465a3fb3c18bb0028b5da0bbeff..0e54145063df2a746a2d2eb97b5553902fb28e75 100644
--- a/webrtc/sdk/android/api/org/webrtc/EglRenderer.java
+++ b/webrtc/sdk/android/api/org/webrtc/EglRenderer.java
@@ -95,8 +95,6 @@ public class EglRenderer implements VideoRenderer.Callbacks {
private EglBase eglBase;
private final RendererCommon.YuvUploader yuvUploader = new RendererCommon.YuvUploader();
private RendererCommon.GlDrawer drawer;
- // Texture ids for YUV frames. Allocated on first arrival of a YUV frame.
- private int[] yuvTextures = null;
// Pending frame to render. Serves as a queue with size 1. Synchronized on |frameLock|.
private final Object frameLock = new Object();
@@ -239,10 +237,7 @@ public class EglRenderer implements VideoRenderer.Callbacks {
drawer.release();
drawer = null;
}
- if (yuvTextures != null) {
- GLES20.glDeleteTextures(3, yuvTextures, 0);
- yuvTextures = null;
- }
+ yuvUploader.release();
if (bitmapTextureFramebuffer != null) {
bitmapTextureFramebuffer.release();
bitmapTextureFramebuffer = null;
@@ -364,33 +359,31 @@ public class EglRenderer implements VideoRenderer.Callbacks {
* Register a callback to be invoked when a new video frame has been received. This version uses
* the drawer of the EglRenderer that was passed in init.
*
- * @param listener The callback to be invoked.
+ * @param listener The callback to be invoked. The callback will be invoked on the render thread.
+ * It should be lightweight and must not call removeFrameListener.
* @param scale The scale of the Bitmap passed to the callback, or 0 if no Bitmap is
* required.
*/
public void addFrameListener(final FrameListener listener, final float scale) {
- postToRenderThread(new Runnable() {
- @Override
- public void run() {
- frameListeners.add(new FrameListenerAndParams(listener, scale, drawer));
- }
- });
+ addFrameListener(listener, scale, null);
}
/**
* Register a callback to be invoked when a new video frame has been received.
*
- * @param listener The callback to be invoked.
+ * @param listener The callback to be invoked. The callback will be invoked on the render thread.
+ * It should be lightweight and must not call removeFrameListener.
* @param scale The scale of the Bitmap passed to the callback, or 0 if no Bitmap is
* required.
- * @param drawer Custom drawer to use for this frame listener.
+ * @param drawer Custom drawer to use for this frame listener or null to use the default one.
*/
public void addFrameListener(
- final FrameListener listener, final float scale, final RendererCommon.GlDrawer drawer) {
+ final FrameListener listener, final float scale, final RendererCommon.GlDrawer drawerParam) {
postToRenderThread(new Runnable() {
@Override
public void run() {
- frameListeners.add(new FrameListenerAndParams(listener, scale, drawer));
+ final RendererCommon.GlDrawer listenerDrawer = drawerParam == null ? drawer : drawerParam;
+ frameListeners.add(new FrameListenerAndParams(listener, scale, listenerDrawer));
}
});
}
@@ -403,6 +396,9 @@ public class EglRenderer implements VideoRenderer.Callbacks {
* @param runnable The callback to remove.
*/
public void removeFrameListener(final FrameListener listener) {
+ if (Thread.currentThread() == renderThreadHandler.getLooper().getThread()) {
+ throw new RuntimeException("removeFrameListener must not be called on the render thread.");
+ }
final CountDownLatch latch = new CountDownLatch(1);
postToRenderThread(new Runnable() {
@Override
@@ -432,20 +428,6 @@ public class EglRenderer implements VideoRenderer.Callbacks {
VideoRenderer.renderFrameDone(frame);
return;
}
- // Check if fps reduction is active.
- synchronized (fpsReductionLock) {
- if (minRenderPeriodNs > 0) {
- final long currentTimeNs = System.nanoTime();
- if (currentTimeNs < nextFrameTimeNs) {
- logD("Dropping frame - fps reduction is active.");
- VideoRenderer.renderFrameDone(frame);
- return;
- }
- nextFrameTimeNs += minRenderPeriodNs;
- // The time for the next frame should always be in the future.
- nextFrameTimeNs = Math.max(nextFrameTimeNs, currentTimeNs);
- }
- }
synchronized (frameLock) {
dropOldFrame = (pendingFrame != null);
if (dropOldFrame) {
@@ -543,6 +525,28 @@ public class EglRenderer implements VideoRenderer.Callbacks {
VideoRenderer.renderFrameDone(frame);
return;
}
+ // Check if fps reduction is active.
+ final boolean shouldRenderFrame;
+ synchronized (fpsReductionLock) {
+ if (minRenderPeriodNs == Long.MAX_VALUE) {
+ // Rendering is paused.
+ shouldRenderFrame = false;
+ } else if (minRenderPeriodNs <= 0) {
+ // FPS reduction is disabled.
+ shouldRenderFrame = true;
+ } else {
+ final long currentTimeNs = System.nanoTime();
+ if (currentTimeNs < nextFrameTimeNs) {
+ logD("Skipping frame rendering - fps reduction is active.");
+ shouldRenderFrame = false;
+ } else {
+ nextFrameTimeNs += minRenderPeriodNs;
+ // The time for the next frame should always be in the future.
+ nextFrameTimeNs = Math.max(nextFrameTimeNs, currentTimeNs);
+ shouldRenderFrame = true;
+ }
+ }
+ }
final long startTimeNs = System.nanoTime();
final float[] texMatrix =
@@ -575,55 +579,61 @@ public class EglRenderer implements VideoRenderer.Callbacks {
drawMatrix = RendererCommon.multiplyMatrices(texMatrix, layoutMatrix);
}
- GLES20.glClearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
- GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+ boolean shouldUploadYuvTextures = false;
if (frame.yuvFrame) {
- // Make sure YUV textures are allocated.
- if (yuvTextures == null) {
- yuvTextures = new int[3];
- for (int i = 0; i < 3; i++) {
- yuvTextures[i] = GlUtil.generateTexture(GLES20.GL_TEXTURE_2D);
+ shouldUploadYuvTextures = shouldRenderFrame;
+ // Check if there are frame listeners that we want to render a bitmap for regardless of if the
+ // frame was rendered. This is the case when there are frameListeners with scale != 0f.
+ if (!shouldUploadYuvTextures) {
+ for (FrameListenerAndParams listenerAndParams : frameListeners) {
+ if (listenerAndParams.scale != 0f) {
+ shouldUploadYuvTextures = true;
+ break;
+ }
}
}
-
- yuvUploader.uploadYuvData(
- yuvTextures, frame.width, frame.height, frame.yuvStrides, frame.yuvPlanes);
- drawer.drawYuv(yuvTextures, drawMatrix, drawnFrameWidth, drawnFrameHeight, 0, 0,
- eglBase.surfaceWidth(), eglBase.surfaceHeight());
- } else {
- drawer.drawOes(frame.textureId, drawMatrix, drawnFrameWidth, drawnFrameHeight, 0, 0,
- eglBase.surfaceWidth(), eglBase.surfaceHeight());
}
+ final int[] yuvTextures = shouldUploadYuvTextures
+ ? yuvUploader.uploadYuvData(frame.width, frame.height, frame.yuvStrides, frame.yuvPlanes)
+ : null;
- final long swapBuffersStartTimeNs = System.nanoTime();
- eglBase.swapBuffers();
+ if (shouldRenderFrame) {
+ GLES20.glClearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+ if (frame.yuvFrame) {
+ drawer.drawYuv(yuvTextures, drawMatrix, drawnFrameWidth, drawnFrameHeight, 0, 0,
+ eglBase.surfaceWidth(), eglBase.surfaceHeight());
+ } else {
+ drawer.drawOes(frame.textureId, drawMatrix, drawnFrameWidth, drawnFrameHeight, 0, 0,
+ eglBase.surfaceWidth(), eglBase.surfaceHeight());
+ }
- final long currentTimeNs = System.nanoTime();
- synchronized (statisticsLock) {
- ++framesRendered;
- renderTimeNs += (currentTimeNs - startTimeNs);
- renderSwapBufferTimeNs += (currentTimeNs - swapBuffersStartTimeNs);
+ final long swapBuffersStartTimeNs = System.nanoTime();
+ eglBase.swapBuffers();
+
+ final long currentTimeNs = System.nanoTime();
+ synchronized (statisticsLock) {
+ ++framesRendered;
+ renderTimeNs += (currentTimeNs - startTimeNs);
+ renderSwapBufferTimeNs += (currentTimeNs - swapBuffersStartTimeNs);
+ }
}
- notifyCallbacks(frame, texMatrix);
+ notifyCallbacks(frame, yuvTextures, texMatrix);
VideoRenderer.renderFrameDone(frame);
}
- private void notifyCallbacks(VideoRenderer.I420Frame frame, float[] texMatrix) {
- // Make temporary copy of callback list to avoid ConcurrentModificationException, in case
- // callbacks call addFramelistener or removeFrameListener.
- final ArrayList<FrameListenerAndParams> tmpList;
+ private void notifyCallbacks(
+ VideoRenderer.I420Frame frame, int[] yuvTextures, float[] texMatrix) {
if (frameListeners.isEmpty())
return;
- tmpList = new ArrayList<>(frameListeners);
- frameListeners.clear();
final float[] bitmapMatrix = RendererCommon.multiplyMatrices(
RendererCommon.multiplyMatrices(texMatrix,
mirror ? RendererCommon.horizontalFlipMatrix() : RendererCommon.identityMatrix()),
RendererCommon.verticalFlipMatrix());
- for (FrameListenerAndParams listenerAndParams : tmpList) {
+ for (FrameListenerAndParams listenerAndParams : frameListeners) {
final int scaledWidth = (int) (listenerAndParams.scale * frame.rotatedWidth());
final int scaledHeight = (int) (listenerAndParams.scale * frame.rotatedHeight());
@@ -663,6 +673,7 @@ public class EglRenderer implements VideoRenderer.Callbacks {
bitmap.copyPixelsFromBuffer(bitmapBuffer);
listenerAndParams.listener.onFrame(bitmap);
}
+ frameListeners.clear();
}
private String averageTimeAsString(long sumTimeNs, int count) {
« no previous file with comments | « no previous file | webrtc/sdk/android/api/org/webrtc/RendererCommon.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698