diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/CompositingVideoSinkProvider.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/CompositingVideoSinkProvider.java index 7c9ce3273d..95e0558ae6 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/CompositingVideoSinkProvider.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/CompositingVideoSinkProvider.java @@ -788,6 +788,11 @@ public final class CompositingVideoSinkProvider implements VideoSinkProvider, Vi } } + @Override + public void join(boolean renderNextFrameImmediately) { + videoFrameReleaseControl.join(renderNextFrameImmediately); + } + @Override public void release() { CompositingVideoSinkProvider.this.release(); diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java index 212f1b991e..8a90f05e2f 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/MediaCodecVideoRenderer.java @@ -731,7 +731,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer // Don't render next frame immediately to let the codec catch up with the playback position // first. This prevents a stuttering effect caused by showing the first frame and then // dropping many of the subsequent frames during the catch up phase. - videoFrameReleaseControl.join(/* renderNextFrameImmediately= */ false); + if (videoSink != null) { + videoSink.join(/* renderNextFrameImmediately= */ false); + } else { + videoFrameReleaseControl.join(/* renderNextFrameImmediately= */ false); + } } maybeSetupTunnelingForFirstFrame(); consecutiveDroppedFrameCount = 0; @@ -924,7 +928,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer // before we rendered the new first frame. Since there is no reason to believe the next // frame is delayed and the renderer needs to catch up, we still request to render the // next frame as soon as possible. - videoFrameReleaseControl.join(/* renderNextFrameImmediately= */ true); + if (videoSink != null) { + videoSink.join(/* renderNextFrameImmediately= */ true); + } else { + videoFrameReleaseControl.join(/* renderNextFrameImmediately= */ true); + } } } else { // The display surface has been removed. diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoFrameReleaseControl.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoFrameReleaseControl.java index 380d63a968..565322d994 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoFrameReleaseControl.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoFrameReleaseControl.java @@ -302,7 +302,7 @@ public final class VideoFrameReleaseControl { /** * Joins the release control to a new stream. * - *

The release control will pretend to be {@linkplain #isReady ready} for short time even if + *

The release control will pretend to be {@linkplain #isReady ready} for a short time even if * the first frame hasn't been rendered yet to avoid interrupting an ongoing playback. * * @param renderNextFrameImmediately Whether the next frame should be released as soon as possible diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoSink.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoSink.java index c2eab5cc56..a360f5de67 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoSink.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoSink.java @@ -265,6 +265,17 @@ public interface VideoSink { */ void render(long positionUs, long elapsedRealtimeUs) throws VideoSinkException; + /** + * Joins the video sink to a new stream. + * + *

The sink will pretend to be {@linkplain #isReady ready} for a short time even if the first + * frame hasn't been rendered yet to avoid interrupting an ongoing playback. + * + * @param renderNextFrameImmediately Whether the next frame should be rendered as soon as possible + * or only at its preferred scheduled release time. + */ + void join(boolean renderNextFrameImmediately); + /** Releases the sink. */ void release(); }