From 427daef3504dd344d7dbea42c324c8a28e48e96d Mon Sep 17 00:00:00 2001 From: kimvde Date: Mon, 31 Mar 2025 02:25:10 -0700 Subject: [PATCH] Remove VideoSink.setWakeUpListener This is the last Renderer reference in VideoSink PiperOrigin-RevId: 742189332 --- .../mediacodec/MediaCodecRenderer.java | 12 ------- .../exoplayer/video/DefaultVideoSink.java | 13 +------ .../video/MediaCodecVideoRenderer.java | 20 +++++------ .../video/PlaybackVideoGraphWrapper.java | 35 ++++++++++--------- .../media3/exoplayer/video/VideoSink.java | 8 ++--- .../transformer/BufferingVideoSink.java | 6 ---- .../transformer/SequenceRenderersFactory.java | 18 +++++++--- 7 files changed, 47 insertions(+), 65 deletions(-) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java index 4de67f4944..890888ca6e 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecRenderer.java @@ -839,7 +839,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { throws ExoPlaybackException { if (messageType == MSG_SET_WAKEUP_LISTENER) { wakeupListener = checkNotNull((WakeupListener) message); - onWakeupListenerSet(wakeupListener); } else { super.handleMessage(messageType, message); } @@ -1546,17 +1545,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { // Do nothing. } - /** - * Called when a {@link WakeupListener} is set. - * - *

The default implementation is a no-op. - * - * @param wakeupListener The {@link WakeupListener}. - */ - protected void onWakeupListenerSet(WakeupListener wakeupListener) { - // Do nothing. - } - /** * Called when a new {@link Format} is read from the upstream {@link MediaPeriod}. * diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/DefaultVideoSink.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/DefaultVideoSink.java index b696c4070c..f5596b42f0 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/DefaultVideoSink.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/DefaultVideoSink.java @@ -30,7 +30,6 @@ import androidx.media3.common.util.Clock; import androidx.media3.common.util.Size; import androidx.media3.common.util.TimestampIterator; import androidx.media3.exoplayer.ExoPlaybackException; -import androidx.media3.exoplayer.Renderer; import java.util.ArrayDeque; import java.util.List; import java.util.Queue; @@ -46,7 +45,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; *

* *

The {@linkplain #getInputSurface() input} and {@linkplain #setOutputSurfaceInfo(Surface, Size) @@ -224,6 +222,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; videoFrameHandlers.add(videoFrameHandler); long bufferPresentationTimeUs = framePresentationTimeUs - bufferTimestampAdjustmentUs; videoFrameRenderControl.onFrameAvailableForRendering(bufferPresentationTimeUs); + listenerExecutor.execute(() -> listener.onFrameAvailableForRendering()); return true; } @@ -246,16 +245,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } } - /** - * {@inheritDoc} - * - *

This method will always throw an {@link UnsupportedOperationException}. - */ - @Override - public void setWakeupListener(Renderer.WakeupListener wakeupListener) { - throw new UnsupportedOperationException(); - } - @Override public void join(boolean renderNextFrameImmediately) { videoFrameReleaseControl.join(renderNextFrameImmediately); 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 860d2a7255..cbcc07ba1d 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 @@ -883,6 +883,15 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer // have been set on the renderer before creating the VideoSink. videoSink.setListener( new VideoSink.Listener() { + + @Override + public void onFrameAvailableForRendering() { + @Nullable WakeupListener wakeupListener = getWakeupListener(); + if (wakeupListener != null) { + wakeupListener.onWakeup(); + } + } + @Override public void onFirstFrameRendered() { if (displaySurface != null) { @@ -932,10 +941,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer mayRenderStartOfStream ? RELEASE_FIRST_FRAME_IMMEDIATELY : RELEASE_FIRST_FRAME_WHEN_STARTED; - @Nullable WakeupListener wakeupListener = getWakeupListener(); - if (wakeupListener != null) { - videoSink.setWakeupListener(wakeupListener); - } experimentalEnableProcessedStreamChangedAtStart(); } else { videoFrameReleaseControl.setClock(getClock()); @@ -1464,13 +1469,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer eventDispatcher.videoCodecError(codecError); } - @Override - protected void onWakeupListenerSet(WakeupListener wakeupListener) { - if (videoSink != null) { - videoSink.setWakeupListener(wakeupListener); - } - } - @Override @Nullable protected DecoderReuseEvaluation onInputFormatChanged(FormatHolder formatHolder) diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/PlaybackVideoGraphWrapper.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/PlaybackVideoGraphWrapper.java index d91d9ff674..b4f375b7fc 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/PlaybackVideoGraphWrapper.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/PlaybackVideoGraphWrapper.java @@ -55,7 +55,6 @@ import androidx.media3.common.util.TimedValueQueue; import androidx.media3.common.util.TimestampIterator; import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.Util; -import androidx.media3.exoplayer.Renderer; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; @@ -80,11 +79,15 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video /** Listener for {@link PlaybackVideoGraphWrapper} events. */ public interface Listener { - /** Called when the video frame processor renders the first frame. */ - void onFirstFrameRendered(); - /** Called when the video frame processor dropped a frame. */ - void onFrameDropped(); + /** Called when an output frame is available for rendering. */ + default void onFrameAvailableForRendering() {} + + /** Called when the first output frame is rendered. */ + default void onFirstFrameRendered() {} + + /** Called when an output frame is dropped. */ + default void onFrameDropped() {} /** * Called before a frame is rendered for the first time since setting the surface, and each time @@ -92,14 +95,14 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video * * @param videoSize The video size. */ - void onVideoSizeChanged(VideoSize videoSize); + default void onVideoSizeChanged(VideoSize videoSize) {} /** - * Called when the video frame processor encountered an error. + * Called when an error occurs. * * @param videoFrameProcessingException The error. */ - void onError(VideoFrameProcessingException videoFrameProcessingException); + default void onError(VideoFrameProcessingException videoFrameProcessingException) {} } /** A builder for {@link PlaybackVideoGraphWrapper} instances. */ @@ -288,7 +291,6 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video @Nullable private Pair currentSurfaceAndSize; private int pendingFlushCount; private @State int state; - @Nullable private Renderer.WakeupListener wakeupListener; /** * The buffer presentation time of the frame most recently output by the video graph, in @@ -430,9 +432,9 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video // Ignore available frames while flushing return; } - if (wakeupListener != null) { + for (PlaybackVideoGraphWrapper.Listener listener : listeners) { // Wake up the player when not playing to render the frame more promptly. - wakeupListener.onWakeup(); + listener.onFrameAvailableForRendering(); } long bufferPresentationTimeUs = framePresentationTimeUs - bufferTimestampAdjustmentUs; @@ -949,11 +951,6 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video PlaybackVideoGraphWrapper.this.render(positionUs, elapsedRealtimeUs); } - @Override - public void setWakeupListener(Renderer.WakeupListener wakeupListener) { - PlaybackVideoGraphWrapper.this.wakeupListener = wakeupListener; - } - @Override public void join(boolean renderNextFrameImmediately) { defaultVideoSink.join(renderNextFrameImmediately); @@ -966,6 +963,12 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video // PlaybackVideoGraphWrapper.Listener implementation + @Override + public void onFrameAvailableForRendering() { + VideoSink.Listener currentListener = listener; + listenerExecutor.execute(currentListener::onFrameAvailableForRendering); + } + @Override public void onFirstFrameRendered() { VideoSink.Listener currentListener = listener; 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 b01ed1e58c..8c3bff6f1d 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 @@ -28,7 +28,6 @@ import androidx.media3.common.VideoSize; import androidx.media3.common.util.Size; import androidx.media3.common.util.TimestampIterator; import androidx.media3.common.util.UnstableApi; -import androidx.media3.exoplayer.Renderer; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -56,6 +55,10 @@ public interface VideoSink { /** Listener for {@link VideoSink} events. */ interface Listener { + + /** Called when an output frame is available for rendering. */ + default void onFrameAvailableForRendering() {} + /** Called when the sink renders the first frame on the output surface. */ default void onFirstFrameRendered() {} @@ -305,9 +308,6 @@ public interface VideoSink { */ void render(long positionUs, long elapsedRealtimeUs) throws VideoSinkException; - /** Sets a {@link Renderer.WakeupListener} on the {@code VideoSink}. */ - void setWakeupListener(Renderer.WakeupListener wakeupListener); - /** * Joins the video sink to a new stream. * diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/BufferingVideoSink.java b/libraries/transformer/src/main/java/androidx/media3/transformer/BufferingVideoSink.java index 20f88ba29e..a0882624ae 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/BufferingVideoSink.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/BufferingVideoSink.java @@ -23,7 +23,6 @@ import androidx.media3.common.Effect; import androidx.media3.common.Format; import androidx.media3.common.util.Size; import androidx.media3.common.util.TimestampIterator; -import androidx.media3.exoplayer.Renderer; import androidx.media3.exoplayer.video.PlaceholderSurface; import androidx.media3.exoplayer.video.VideoFrameMetadataListener; import androidx.media3.exoplayer.video.VideoSink; @@ -263,11 +262,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } } - @Override - public void setWakeupListener(Renderer.WakeupListener wakeupListener) { - executeOrDelay(videoSink -> videoSink.setWakeupListener(wakeupListener)); - } - @Override public void join(boolean renderNextFrameImmediately) { executeOrDelay(videoSink -> videoSink.join(renderNextFrameImmediately)); diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/SequenceRenderersFactory.java b/libraries/transformer/src/main/java/androidx/media3/transformer/SequenceRenderersFactory.java index 5a07f6f840..84926b5e52 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/SequenceRenderersFactory.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/SequenceRenderersFactory.java @@ -27,6 +27,7 @@ import static androidx.media3.exoplayer.DefaultRenderersFactory.MAX_DROPPED_VIDE import static androidx.media3.exoplayer.video.VideoSink.RELEASE_FIRST_FRAME_IMMEDIATELY; import static androidx.media3.exoplayer.video.VideoSink.RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED; import static androidx.media3.exoplayer.video.VideoSink.RELEASE_FIRST_FRAME_WHEN_STARTED; +import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import android.content.Context; import android.graphics.Bitmap; @@ -500,6 +501,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; private boolean mayRenderStartOfStream; private @VideoSink.FirstFrameReleaseInstruction int nextFirstFrameReleaseInstruction; private long offsetToCompositionTimeUs; + private @MonotonicNonNull WakeupListener wakeupListener; public SequenceImageRenderer( EditedMediaItemSequence sequence, @@ -523,9 +525,17 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; mayRenderStartOfStream ? RELEASE_FIRST_FRAME_IMMEDIATELY : RELEASE_FIRST_FRAME_WHEN_STARTED; - // TODO: b/328444280 - Do not set a listener on VideoSink, but MediaCodecVideoRenderer must - // unregister itself as a listener too. - videoSink.setListener(VideoSink.Listener.NO_OP, /* executor= */ (runnable) -> {}); + // TODO: b/328444280 - Unregister as a listener when the renderer is not used anymore + videoSink.setListener( + new VideoSink.Listener() { + @Override + public void onFrameAvailableForRendering() { + if (wakeupListener != null) { + wakeupListener.onWakeup(); + } + } + }, + directExecutor()); } @Override @@ -658,7 +668,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; public void handleMessage(@MessageType int messageType, @Nullable Object message) throws ExoPlaybackException { if (messageType == MSG_SET_WAKEUP_LISTENER) { - videoSink.setWakeupListener((WakeupListener) checkNotNull(message)); + this.wakeupListener = (WakeupListener) checkNotNull(message); } else { super.handleMessage(messageType, message); }