From 361dbc19739dc7910daf07a765bd2edc4a9c06bc Mon Sep 17 00:00:00 2001 From: Magnus Jedvert Date: Tue, 6 Nov 2018 11:32:46 +0100 Subject: [PATCH] Android: Add option to set presentation timestamp in EglRenderer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: b/119004693 Change-Id: I78b676a4417ac313e7fbbea009c8dd586707b1af Reviewed-on: https://webrtc-review.googlesource.com/c/109503 Commit-Queue: Magnus Jedvert Reviewed-by: Sami Kalliomäki Cr-Commit-Position: refs/heads/master@{#25517} --- sdk/android/api/org/webrtc/EglRenderer.java | 24 ++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/sdk/android/api/org/webrtc/EglRenderer.java b/sdk/android/api/org/webrtc/EglRenderer.java index bef34f5a26..319ec7d292 100644 --- a/sdk/android/api/org/webrtc/EglRenderer.java +++ b/sdk/android/api/org/webrtc/EglRenderer.java @@ -125,6 +125,7 @@ public class EglRenderer implements VideoSink { @Nullable private EglBase eglBase; private final VideoFrameDrawer frameDrawer = new VideoFrameDrawer(); @Nullable private RendererCommon.GlDrawer drawer; + private boolean usePresentationTimeStamp; private final Matrix drawMatrix = new Matrix(); // Pending frame to render. Serves as a queue with size 1. Synchronized on |frameLock|. @@ -185,16 +186,19 @@ public class EglRenderer implements VideoSink { * Initialize this class, sharing resources with |sharedContext|. The custom |drawer| will be used * for drawing frames on the EGLSurface. This class is responsible for calling release() on * |drawer|. It is allowed to call init() to reinitialize the renderer after a previous - * init()/release() cycle. + * init()/release() cycle. If usePresentationTimeStamp is true, eglPresentationTimeANDROID will be + * set with the frame timestamps, which specifies desired presentation time and might be useful + * for e.g. syncing audio and video. */ public void init(@Nullable final EglBase.Context sharedContext, final int[] configAttributes, - RendererCommon.GlDrawer drawer) { + RendererCommon.GlDrawer drawer, boolean usePresentationTimeStamp) { synchronized (handlerLock) { if (renderThreadHandler != null) { throw new IllegalStateException(name + "Already initialized"); } logD("Initializing EglRenderer"); this.drawer = drawer; + this.usePresentationTimeStamp = usePresentationTimeStamp; final HandlerThread renderThread = new HandlerThread(name + "EglRenderer"); renderThread.start(); @@ -230,6 +234,16 @@ public class EglRenderer implements VideoSink { } } + /** + * Same as above with usePresentationTimeStamp set to false. + * + * @see #init(EglBase.Context, int[], RendererCommon.GlDrawer, boolean) + */ + public void init(@Nullable final EglBase.Context sharedContext, final int[] configAttributes, + RendererCommon.GlDrawer drawer) { + init(sharedContext, configAttributes, drawer, /* usePresentationTimeStamp= */ false); + } + public void createEglSurface(Surface surface) { createEglSurfaceInternal(surface); } @@ -617,7 +631,11 @@ public class EglRenderer implements VideoSink { eglBase.surfaceWidth(), eglBase.surfaceHeight()); final long swapBuffersStartTimeNs = System.nanoTime(); - eglBase.swapBuffers(); + if (usePresentationTimeStamp) { + eglBase.swapBuffers(frame.getTimestampNs()); + } else { + eglBase.swapBuffers(); + } final long currentTimeNs = System.nanoTime(); synchronized (statisticsLock) {