From 3032252fdee9fdcda03aaec62005c09cbd442b20 Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 13 Apr 2021 16:06:04 +0100 Subject: [PATCH] Use a single message for setting video renderer outputs Previously, we had separate MSG_SET_SURFACE and MSG_SET_VIDEO_DECODER_OUTPUT_BUFFER_RENDERER messages for setting different types of supported output. Use of these constants to switch between outputs during use of a player was confusing because not all video renderers support both message types. To switch from VideoDecoderOutputBufferRenderer to a Surface, it was sufficient just to send MSG_SET_SURFACE, since all video renderers support this and clear any other output that might be set. Conversely, to switch in the opposite direction, just sending a MSG_SET_VIDEO_DECODER_OUTPUT_BUFFER_RENDERER was not sufficient, because not all video renderers handle this message to clear any previous output. Hence it was necessary to explicitly clear a previously set surface using a separate MSG_SET_SURFACE message. Passing two messages to switch the output may prevent renderers from implementing the output switch efficiently. This change passes all outputs using a single message type, and requires that all renderers treat unsupported outputs as though null were passed (i.e., they clear any existing output). There are some other miscellaneous improvements: 1. Non-surface outputs are now passed to onRenderedFirstFrame. This fixes a bug in SimpleExoPlayer's onRenderedFirstFrame, where previously it could not correctly equality check the output corresponding to the event to its current output in the VideoDecoderOutputBufferRenderer case. 2. Fix SimpleExoPlayer to report surface size changes for the VideoDecoderOutputBufferRenderer case. Even though the surface is rendered to indirectly in this case, we can still query (and listen to changes to) the surface's size. PiperOrigin-RevId: 368215850 --- .../java/com/google/android/exoplayer2/C.java | 5 +- .../android/exoplayer2/BaseRenderer.java | 2 +- .../google/android/exoplayer2/Renderer.java | 21 +-- .../android/exoplayer2/SimpleExoPlayer.java | 143 +++++++++--------- .../analytics/AnalyticsCollector.java | 9 +- .../analytics/AnalyticsListener.java | 12 +- .../android/exoplayer2/util/EventLogger.java | 5 +- .../video/DecoderVideoRenderer.java | 92 +++++------ .../video/MediaCodecVideoRenderer.java | 15 +- .../video/VideoRendererEventListener.java | 22 +-- .../android/exoplayer2/ExoPlayerTest.java | 2 +- .../analytics/AnalyticsCollectorTest.java | 3 +- .../video/DecoderVideoRendererTest.java | 19 ++- .../video/MediaCodecVideoRendererTest.java | 2 +- .../testutil/FakeVideoRenderer.java | 14 +- 15 files changed, 157 insertions(+), 209 deletions(-) diff --git a/library/common/src/main/java/com/google/android/exoplayer2/C.java b/library/common/src/main/java/com/google/android/exoplayer2/C.java index 916b52b8bd..de31cade4a 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/C.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/C.java @@ -782,7 +782,7 @@ public final class C { */ public static final UUID PLAYREADY_UUID = new UUID(0x9A04F07998404286L, 0xAB92E65BE0885F95L); - /** @deprecated Use {@code Renderer.MSG_SET_SURFACE}. */ + /** @deprecated Use {@code Renderer.MSG_SET_VIDEO_OUTPUT}. */ @Deprecated public static final int MSG_SET_SURFACE = 1; /** @deprecated Use {@code Renderer.MSG_SET_VOLUME}. */ @@ -803,9 +803,6 @@ public final class C { /** @deprecated Use {@code Renderer.MSG_SET_CAMERA_MOTION_LISTENER}. */ @Deprecated public static final int MSG_SET_CAMERA_MOTION_LISTENER = 7; - /** @deprecated Use {@code Renderer.MSG_SET_VIDEO_DECODER_OUTPUT_BUFFER_RENDERER}. */ - @Deprecated public static final int MSG_SET_VIDEO_DECODER_OUTPUT_BUFFER_RENDERER = 8; - /** @deprecated Use {@code Renderer.MSG_CUSTOM_BASE}. */ @Deprecated public static final int MSG_CUSTOM_BASE = 10000; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java index 37db0c5544..cb76107df5 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/BaseRenderer.java @@ -196,7 +196,7 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { // PlayerMessage.Target implementation. @Override - public void handleMessage(int what, @Nullable Object object) throws ExoPlaybackException { + public void handleMessage(int messageType, @Nullable Object payload) throws ExoPlaybackException { // Do nothing. } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/Renderer.java b/library/core/src/main/java/com/google/android/exoplayer2/Renderer.java index 0aba970a25..f84fef5004 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/Renderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/Renderer.java @@ -24,7 +24,6 @@ import com.google.android.exoplayer2.audio.AuxEffectInfo; import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.util.MediaClock; import com.google.android.exoplayer2.util.Util; -import com.google.android.exoplayer2.video.DecoderVideoRenderer; import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer; import com.google.android.exoplayer2.video.VideoFrameMetadataListener; import com.google.android.exoplayer2.video.spherical.CameraMotionListener; @@ -76,11 +75,14 @@ public interface Renderer extends PlayerMessage.Target { /** * The type of a message that can be passed to a video renderer via {@link - * ExoPlayer#createMessage(Target)}. The message payload should be the target {@link Surface}, or - * null. + * ExoPlayer#createMessage(Target)}. The message payload is normally a {@link Surface}, however + * some video renderers may accept other outputs (e.g., {@link VideoDecoderOutputBufferRenderer}). + * + *

If the receiving renderer does not support the payload type as an output, then it will clear + * any existing output that it has. */ @SuppressWarnings("deprecation") - int MSG_SET_SURFACE = C.MSG_SET_SURFACE; + int MSG_SET_VIDEO_OUTPUT = C.MSG_SET_SURFACE; /** * A type of a message that can be passed to an audio renderer via {@link * ExoPlayer#createMessage(Target)}. The message payload should be a {@link Float} with 0 being @@ -142,17 +144,6 @@ public interface Renderer extends PlayerMessage.Target { */ @SuppressWarnings("deprecation") int MSG_SET_CAMERA_MOTION_LISTENER = C.MSG_SET_CAMERA_MOTION_LISTENER; - /** - * The type of a message that can be passed to a {@link DecoderVideoRenderer} via {@link - * ExoPlayer#createMessage(Target)}. The message payload should be the target {@link - * VideoDecoderOutputBufferRenderer}, or null. - * - *

This message is intended only for use with extension renderers that expect a {@link - * VideoDecoderOutputBufferRenderer}. For other use cases, an output surface should be passed via - * {@link #MSG_SET_SURFACE} instead. - */ - @SuppressWarnings("deprecation") - int MSG_SET_VIDEO_DECODER_OUTPUT_BUFFER_RENDERER = C.MSG_SET_VIDEO_DECODER_OUTPUT_BUFFER_RENDERER; /** * The type of a message that can be passed to an audio renderer via {@link * ExoPlayer#createMessage(Target)}. The message payload should be a {@link Boolean} instance diff --git a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index e2dae18b4e..f7e53ba2e7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -61,7 +61,6 @@ import com.google.android.exoplayer2.util.ConditionVariable; import com.google.android.exoplayer2.util.Log; import com.google.android.exoplayer2.util.PriorityTaskManager; import com.google.android.exoplayer2.util.Util; -import com.google.android.exoplayer2.video.VideoDecoderGLSurfaceView; import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer; import com.google.android.exoplayer2.video.VideoFrameMetadataListener; import com.google.android.exoplayer2.video.VideoListener; @@ -587,11 +586,12 @@ public class SimpleExoPlayer extends BasePlayer @Nullable private Format videoFormat; @Nullable private Format audioFormat; @Nullable private AudioTrack keepSessionIdAudioTrack; - @Nullable private Surface surface; - private boolean ownsSurface; - @C.VideoScalingMode private int videoScalingMode; + @Nullable private Object videoOutput; + @Nullable private Surface ownedSurface; @Nullable private SurfaceHolder surfaceHolder; + private boolean surfaceHolderSurfaceIsVideoOutput; @Nullable private TextureView textureView; + @C.VideoScalingMode private int videoScalingMode; private int surfaceWidth; private int surfaceHeight; @Nullable private DecoderCounters videoDecoderCounters; @@ -797,14 +797,14 @@ public class SimpleExoPlayer extends BasePlayer public void clearVideoSurface() { verifyApplicationThread(); removeSurfaceCallbacks(); - setVideoSurfaceInternal(/* surface= */ null, /* ownsSurface= */ false); + setVideoOutputInternal(/* videoOutput= */ null); maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); } @Override public void clearVideoSurface(@Nullable Surface surface) { verifyApplicationThread(); - if (surface != null && surface == this.surface) { + if (surface != null && surface == videoOutput) { clearVideoSurface(); } } @@ -813,10 +813,7 @@ public class SimpleExoPlayer extends BasePlayer public void setVideoSurface(@Nullable Surface surface) { verifyApplicationThread(); removeSurfaceCallbacks(); - if (surface != null) { - setVideoDecoderOutputBufferRenderer(/* videoDecoderOutputBufferRenderer= */ null); - } - setVideoSurfaceInternal(surface, /* ownsSurface= */ false); + setVideoOutputInternal(surface); int newSurfaceSize = surface == null ? 0 : C.LENGTH_UNSET; maybeNotifySurfaceSizeChanged(/* width= */ newSurfaceSize, /* height= */ newSurfaceSize); } @@ -824,23 +821,20 @@ public class SimpleExoPlayer extends BasePlayer @Override public void setVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) { verifyApplicationThread(); - removeSurfaceCallbacks(); - if (surfaceHolder != null) { - setVideoDecoderOutputBufferRenderer(/* videoDecoderOutputBufferRenderer= */ null); - } - this.surfaceHolder = surfaceHolder; if (surfaceHolder == null) { - setVideoSurfaceInternal(null, /* ownsSurface= */ false); - maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); + clearVideoSurface(); } else { + removeSurfaceCallbacks(); + this.surfaceHolderSurfaceIsVideoOutput = true; + this.surfaceHolder = surfaceHolder; surfaceHolder.addCallback(componentListener); Surface surface = surfaceHolder.getSurface(); if (surface != null && surface.isValid()) { - setVideoSurfaceInternal(surface, /* ownsSurface= */ false); + setVideoOutputInternal(surface); Rect surfaceSize = surfaceHolder.getSurfaceFrame(); maybeNotifySurfaceSizeChanged(surfaceSize.width(), surfaceSize.height()); } else { - setVideoSurfaceInternal(/* surface= */ null, /* ownsSurface= */ false); + setVideoOutputInternal(/* videoOutput= */ null); maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); } } @@ -850,7 +844,7 @@ public class SimpleExoPlayer extends BasePlayer public void clearVideoSurfaceHolder(@Nullable SurfaceHolder surfaceHolder) { verifyApplicationThread(); if (surfaceHolder != null && surfaceHolder == this.surfaceHolder) { - setVideoSurfaceHolder(null); + clearVideoSurface(); } } @@ -858,11 +852,21 @@ public class SimpleExoPlayer extends BasePlayer public void setVideoSurfaceView(@Nullable SurfaceView surfaceView) { verifyApplicationThread(); if (surfaceView instanceof VideoDecoderOutputBufferRenderer) { - VideoDecoderOutputBufferRenderer videoDecoderOutputBufferRenderer = - (VideoDecoderOutputBufferRenderer) surfaceView; - clearVideoSurface(); + removeSurfaceCallbacks(); + setVideoOutputInternal(surfaceView); + // Although we won't use the surface directly as the video output, still use the holder to + // query the surface size, to be informed in changes to the size via componentListener, and + // for equality checking in clearVideoSurfaceHolder. + surfaceHolderSurfaceIsVideoOutput = false; surfaceHolder = surfaceView.getHolder(); - setVideoDecoderOutputBufferRenderer(videoDecoderOutputBufferRenderer); + surfaceHolder.addCallback(componentListener); + Surface surface = surfaceHolder.getSurface(); + if (surface != null && surface.isValid()) { + Rect surfaceSize = surfaceHolder.getSurfaceFrame(); + maybeNotifySurfaceSizeChanged(surfaceSize.width(), surfaceSize.height()); + } else { + maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); + } } else { setVideoSurfaceHolder(surfaceView == null ? null : surfaceView.getHolder()); } @@ -871,39 +875,29 @@ public class SimpleExoPlayer extends BasePlayer @Override public void clearVideoSurfaceView(@Nullable SurfaceView surfaceView) { verifyApplicationThread(); - if (surfaceView instanceof VideoDecoderGLSurfaceView) { - if (surfaceView.getHolder() == surfaceHolder) { - setVideoDecoderOutputBufferRenderer(null); - surfaceHolder = null; - } - } else { - clearVideoSurfaceHolder(surfaceView == null ? null : surfaceView.getHolder()); - } + clearVideoSurfaceHolder(surfaceView == null ? null : surfaceView.getHolder()); } @Override public void setVideoTextureView(@Nullable TextureView textureView) { verifyApplicationThread(); - removeSurfaceCallbacks(); - if (textureView != null) { - setVideoDecoderOutputBufferRenderer(/* videoDecoderOutputBufferRenderer= */ null); - } - this.textureView = textureView; if (textureView == null) { - setVideoSurfaceInternal(/* surface= */ null, /* ownsSurface= */ true); - maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); + clearVideoSurface(); } else { + removeSurfaceCallbacks(); + this.textureView = textureView; if (textureView.getSurfaceTextureListener() != null) { Log.w(TAG, "Replacing existing SurfaceTextureListener."); } textureView.setSurfaceTextureListener(componentListener); + @Nullable SurfaceTexture surfaceTexture = textureView.isAvailable() ? textureView.getSurfaceTexture() : null; if (surfaceTexture == null) { - setVideoSurfaceInternal(/* surface= */ null, /* ownsSurface= */ true); + setVideoOutputInternal(/* videoOutput= */ null); maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); } else { - setVideoSurfaceInternal(new Surface(surfaceTexture), /* ownsSurface= */ true); + setSurfaceTextureInternal(surfaceTexture); maybeNotifySurfaceSizeChanged(textureView.getWidth(), textureView.getHeight()); } } @@ -913,7 +907,7 @@ public class SimpleExoPlayer extends BasePlayer public void clearVideoTextureView(@Nullable TextureView textureView) { verifyApplicationThread(); if (textureView != null && textureView == this.textureView) { - setVideoTextureView(null); + clearVideoSurface(); } } @@ -1563,11 +1557,9 @@ public class SimpleExoPlayer extends BasePlayer player.release(); analyticsCollector.release(); removeSurfaceCallbacks(); - if (surface != null) { - if (ownsSurface) { - surface.release(); - } - surface = null; + if (ownedSurface != null) { + ownedSurface.release(); + ownedSurface = null; } if (isPriorityTaskManagerRegistered) { Assertions.checkNotNull(priorityTaskManager).remove(C.PRIORITY_PLAYBACK); @@ -1834,22 +1826,29 @@ public class SimpleExoPlayer extends BasePlayer } } - private void setVideoSurfaceInternal(@Nullable Surface surface, boolean ownsSurface) { - // Note: We don't turn this method into a no-op if the surface is being replaced with itself - // so as to ensure onRenderedFirstFrame callbacks are still called in this case. + private void setSurfaceTextureInternal(SurfaceTexture surfaceTexture) { + Surface surface = new Surface(surfaceTexture); + setVideoOutputInternal(surface); + ownedSurface = surface; + } + + private void setVideoOutputInternal(@Nullable Object videoOutput) { + // Note: We don't turn this method into a no-op if the output is being replaced with itself so + // as to ensure onRenderedFirstFrame callbacks are still called in this case. List messages = new ArrayList<>(); for (Renderer renderer : renderers) { if (renderer.getTrackType() == C.TRACK_TYPE_VIDEO) { messages.add( player .createMessage(renderer) - .setType(Renderer.MSG_SET_SURFACE) - .setPayload(surface) + .setType(Renderer.MSG_SET_VIDEO_OUTPUT) + .setPayload(videoOutput) .send()); } } - if (this.surface != null && this.surface != surface) { - // We're replacing a surface. Block to ensure that it's not accessed after the method returns. + if (this.videoOutput != null && this.videoOutput != videoOutput) { + // We're replacing an output. Block to ensure that this output will not be accessed by the + // renderers after this method returns. try { for (PlayerMessage message : messages) { message.blockUntilDelivered(detachSurfaceTimeoutMs); @@ -1863,21 +1862,13 @@ public class SimpleExoPlayer extends BasePlayer ExoPlaybackException.createForRenderer( new ExoTimeoutException(ExoTimeoutException.TIMEOUT_OPERATION_DETACH_SURFACE))); } - // If we created the previous surface, we are responsible for releasing it. - if (this.ownsSurface) { - this.surface.release(); + if (this.videoOutput == ownedSurface) { + // We're replacing a surface that we are responsible for releasing. + ownedSurface.release(); + ownedSurface = null; } } - this.surface = surface; - this.ownsSurface = ownsSurface; - } - - private void setVideoDecoderOutputBufferRenderer( - @Nullable VideoDecoderOutputBufferRenderer videoDecoderOutputBufferRenderer) { - sendRendererMessage( - C.TRACK_TYPE_VIDEO, - Renderer.MSG_SET_VIDEO_DECODER_OUTPUT_BUFFER_RENDERER, - videoDecoderOutputBufferRenderer); + this.videoOutput = videoOutput; } private void maybeNotifySurfaceSizeChanged(int width, int height) { @@ -2060,9 +2051,9 @@ public class SimpleExoPlayer extends BasePlayer } @Override - public void onRenderedFirstFrame(@Nullable Surface surface, long renderTimeMs) { - analyticsCollector.onRenderedFirstFrame(surface, renderTimeMs); - if (SimpleExoPlayer.this.surface == surface) { + public void onRenderedFirstFrame(Object output, long renderTimeMs) { + analyticsCollector.onRenderedFirstFrame(output, renderTimeMs); + if (videoOutput == output) { for (VideoListener videoListener : videoListeners) { videoListener.onRenderedFirstFrame(); } @@ -2178,7 +2169,9 @@ public class SimpleExoPlayer extends BasePlayer @Override public void surfaceCreated(SurfaceHolder holder) { - setVideoSurfaceInternal(holder.getSurface(), false); + if (surfaceHolderSurfaceIsVideoOutput) { + setVideoOutputInternal(holder.getSurface()); + } } @Override @@ -2188,7 +2181,9 @@ public class SimpleExoPlayer extends BasePlayer @Override public void surfaceDestroyed(SurfaceHolder holder) { - setVideoSurfaceInternal(/* surface= */ null, /* ownsSurface= */ false); + if (surfaceHolderSurfaceIsVideoOutput) { + setVideoOutputInternal(/* videoOutput= */ null); + } maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); } @@ -2196,7 +2191,7 @@ public class SimpleExoPlayer extends BasePlayer @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { - setVideoSurfaceInternal(new Surface(surfaceTexture), /* ownsSurface= */ true); + setSurfaceTextureInternal(surfaceTexture); maybeNotifySurfaceSizeChanged(width, height); } @@ -2207,7 +2202,7 @@ public class SimpleExoPlayer extends BasePlayer @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { - setVideoSurfaceInternal(/* surface= */ null, /* ownsSurface= */ true); + setVideoOutputInternal(/* videoOutput= */ null); maybeNotifySurfaceSizeChanged(/* width= */ 0, /* height= */ 0); return true; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java index 6a0c56caf7..51c89217f4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsCollector.java @@ -19,7 +19,6 @@ import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import android.os.Looper; import android.util.SparseArray; -import android.view.Surface; import androidx.annotation.CallSuper; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; @@ -442,17 +441,13 @@ public class AnalyticsCollector eventTime, width, height, unappliedRotationDegrees, pixelWidthHeightRatio)); } - @SuppressWarnings("deprecation") // Calling deprecated listener method. @Override - public final void onRenderedFirstFrame(@Nullable Surface surface, long renderTimeMs) { + public final void onRenderedFirstFrame(Object output, long renderTimeMs) { EventTime eventTime = generateReadingMediaPeriodEventTime(); sendEvent( eventTime, AnalyticsListener.EVENT_RENDERED_FIRST_FRAME, - listener -> { - listener.onRenderedFirstFrame(eventTime, surface); - listener.onRenderedFirstFrame(eventTime, surface, renderTimeMs); - }); + listener -> listener.onRenderedFirstFrame(eventTime, output, renderTimeMs)); } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java index 643ce08b84..7c4e9750a0 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/analytics/AnalyticsListener.java @@ -48,6 +48,7 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.util.ExoFlags; +import com.google.android.exoplayer2.video.VideoDecoderOutputBufferRenderer; import com.google.common.base.Objects; import java.io.IOException; import java.lang.annotation.Documented; @@ -1020,16 +1021,11 @@ public interface AnalyticsListener { * renderer was reset, or since the stream being rendered was changed. * * @param eventTime The event time. - * @param surface The {@link Surface} to which a frame has been rendered, or {@code null} if the - * renderer renders to something that isn't a {@link Surface}. + * @param output The output to which a frame has been rendered. Normally a {@link Surface}, + * however may also be other output types (e.g., a {@link VideoDecoderOutputBufferRenderer}). * @param renderTimeMs {@link SystemClock#elapsedRealtime()} when the first frame was rendered. */ - default void onRenderedFirstFrame( - EventTime eventTime, @Nullable Surface surface, long renderTimeMs) {} - - /** @deprecated Use {@link #onRenderedFirstFrame(EventTime, Surface, long)} instead. */ - @Deprecated - default void onRenderedFirstFrame(EventTime eventTime, @Nullable Surface surface) {} + default void onRenderedFirstFrame(EventTime eventTime, Object output, long renderTimeMs) {} /** * Called before a frame is rendered for the first time since setting the surface, and each time diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java b/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java index 513621a6fa..ceec6e82cd 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java @@ -19,7 +19,6 @@ import static java.lang.Math.min; import android.os.SystemClock; import android.text.TextUtils; -import android.view.Surface; import androidx.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlaybackException; @@ -453,8 +452,8 @@ public class EventLogger implements AnalyticsListener { } @Override - public void onRenderedFirstFrame(EventTime eventTime, @Nullable Surface surface) { - logd(eventTime, "renderedFirstFrame", String.valueOf(surface)); + public void onRenderedFirstFrame(EventTime eventTime, Object output, long renderTimeMs) { + logd(eventTime, "renderedFirstFrame", String.valueOf(output)); } @Override diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java index 436fa00530..b86e4ff4d8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/DecoderVideoRenderer.java @@ -29,6 +29,7 @@ import androidx.annotation.IntDef; import androidx.annotation.Nullable; import com.google.android.exoplayer2.BaseRenderer; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.C.VideoOutputMode; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.Format; @@ -59,11 +60,9 @@ import java.lang.annotation.RetentionPolicy; * on the playback thread: * *