Add a render callback to EGLRenderer
Change-Id: I72f68ebf5f2e032403701ec6fb1fc3c5580ddf4c Bug: webrtc:340303238 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/350520 Reviewed-by: Linus Nilsson <lnilsson@webrtc.org> Commit-Queue: Ranveer Aggarwal <ranvr@webrtc.org> Reviewed-by: Zoé Lepaul <xalep@webrtc.org> Cr-Commit-Position: refs/heads/main@{#42358}
This commit is contained in:
parent
af0c18c594
commit
17b06515df
@ -34,6 +34,14 @@ public class EglRenderer implements VideoSink {
|
||||
|
||||
public interface FrameListener { void onFrame(Bitmap frame); }
|
||||
|
||||
/**
|
||||
* Can be implemented by the clients who want to know exactly when a render happens.
|
||||
*/
|
||||
public interface RenderListener {
|
||||
/** Fired when swapBuffers happens. */
|
||||
void onRender(long timestampNs);
|
||||
}
|
||||
|
||||
/** Callback for clients to be notified about errors encountered during rendering. */
|
||||
public static interface ErrorCallback {
|
||||
/** Called if GLES20.GL_OUT_OF_MEMORY is encountered during rendering. */
|
||||
@ -100,6 +108,8 @@ public class EglRenderer implements VideoSink {
|
||||
|
||||
private final ArrayList<FrameListenerAndParams> frameListeners = new ArrayList<>();
|
||||
|
||||
private final ArrayList<RenderListener> renderListeners = new ArrayList<>();
|
||||
|
||||
private volatile ErrorCallback errorCallback;
|
||||
|
||||
// Variables for fps reduction.
|
||||
@ -279,6 +289,7 @@ public class EglRenderer implements VideoSink {
|
||||
eglBase = null;
|
||||
}
|
||||
|
||||
renderListeners.clear();
|
||||
frameListeners.clear();
|
||||
eglCleanupBarrier.countDown();
|
||||
});
|
||||
@ -405,7 +416,7 @@ public class EglRenderer implements VideoSink {
|
||||
* 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 or null to use the default one.
|
||||
* @param drawerParam Custom drawer to use for this frame listener or null to use the default.
|
||||
*/
|
||||
public void addFrameListener(
|
||||
final FrameListener listener, final float scale, final RendererCommon.GlDrawer drawerParam) {
|
||||
@ -419,7 +430,7 @@ public class EglRenderer implements VideoSink {
|
||||
* 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 or null to use the default one.
|
||||
* @param drawerParam Custom drawer to use for this frame listener or null to use the default.
|
||||
* @param applyFpsReduction This callback will not be called for frames that have been dropped by
|
||||
* FPS reduction.
|
||||
*/
|
||||
@ -432,12 +443,22 @@ public class EglRenderer implements VideoSink {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback to be invoked when a new video frame has been rendered.
|
||||
*
|
||||
* @param listener The callback to be invoked. The callback will be invoked on the render thread.
|
||||
* It should be lightweight and must not call removeRenderListener.
|
||||
*/
|
||||
public void addRenderListener(final RenderListener listener) {
|
||||
renderListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any pending callback that was added with addFrameListener. If the callback is not in
|
||||
* the queue, nothing happens. It is ensured that callback won't be called after this method
|
||||
* returns.
|
||||
*
|
||||
* @param runnable The callback to remove.
|
||||
* @param listener The callback to remove.
|
||||
*/
|
||||
public void removeFrameListener(final FrameListener listener) {
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
@ -461,6 +482,36 @@ public class EglRenderer implements VideoSink {
|
||||
ThreadUtils.awaitUninterruptibly(latch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any pending callback that was added with addRenderListener. If the callback is not in
|
||||
* the queue, nothing happens. It is ensured that callback won't be called after this method
|
||||
* returns.
|
||||
*
|
||||
* @param listener The callback to remove.
|
||||
*/
|
||||
public void removeRenderListener(final RenderListener listener) {
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
synchronized (threadLock) {
|
||||
if (eglThread == null) {
|
||||
return;
|
||||
}
|
||||
if (Thread.currentThread() == eglThread.getHandler().getLooper().getThread()) {
|
||||
throw new RuntimeException("removeRenderListener must not be called on the render thread.");
|
||||
}
|
||||
postToRenderThread(
|
||||
() -> {
|
||||
latch.countDown();
|
||||
final Iterator<RenderListener> iter = renderListeners.iterator();
|
||||
while (iter.hasNext()) {
|
||||
if (iter.next() == listener) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
ThreadUtils.awaitUninterruptibly(latch);
|
||||
}
|
||||
|
||||
/** Can be set in order to be notified about errors encountered during rendering. */
|
||||
public void setErrorCallback(ErrorCallback errorCallback) {
|
||||
this.errorCallback = errorCallback;
|
||||
@ -576,6 +627,10 @@ public class EglRenderer implements VideoSink {
|
||||
eglBase.swapBuffers();
|
||||
}
|
||||
|
||||
for (var listener : renderListeners) {
|
||||
listener.onRender(System.nanoTime());
|
||||
}
|
||||
|
||||
synchronized (statisticsLock) {
|
||||
renderSwapBufferTimeNs += (System.nanoTime() - swapBuffersStartTimeNs);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user