From 7ef1a7ab8b860ca8f9a55698cd6e2149ca1fb78c Mon Sep 17 00:00:00 2001 From: claincly Date: Mon, 25 Nov 2024 05:12:38 -0800 Subject: [PATCH] Support renderer joining in CompositionPlayer Renderers join when they can start processing but not produce output. In CompositionPlayer before this change, the VideoSink will be flushed when position is reset regardless. This is useful for seeking, as seeking triggers position reset. But with pre-warming, a video renderer can be joining - it is enabled (which also triggers position reset) before the previous image renderer is disabled. At this moment, as the image renderer is still producing frames, we should not flush the video sink just now. PiperOrigin-RevId: 699943882 --- .../media3/exoplayer/video/MediaCodecVideoRenderer.java | 8 +++++--- .../media3/transformer/SequenceRenderersFactory.java | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) 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 068a2e5484..87667cc235 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 @@ -805,9 +805,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer @Override protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException { if (videoSink != null) { - // Flush the video sink first to ensure it stops reading textures that will be owned by - // MediaCodec once the codec is flushed. - videoSink.flush(/* resetPosition= */ true); + if (!joining) { + // Flush the video sink first to ensure it stops reading textures that will be owned by + // MediaCodec once the codec is flushed. + videoSink.flush(/* resetPosition= */ true); + } videoSink.setStreamTimestampInfo( getOutputStreamStartPositionUs(), getBufferTimestampAdjustmentUs(), 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 34bc035f79..615e87ff5f 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/SequenceRenderersFactory.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/SequenceRenderersFactory.java @@ -297,11 +297,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; MediaSource.MediaPeriodId mediaPeriodId) throws ExoPlaybackException { checkState(getTimeline().getWindowCount() == 1); - super.onStreamChanged(formats, startPositionUs, offsetUs, mediaPeriodId); // The media item might have been repeated in the sequence. int mediaItemIndex = getTimeline().getIndexOfPeriod(mediaPeriodId.periodUid); offsetToCompositionTimeUs = getOffsetToCompositionTimeUs(sequence, mediaItemIndex, offsetUs); pendingEffect = sequence.editedMediaItems.get(mediaItemIndex).effects.videoEffects; + super.onStreamChanged(formats, startPositionUs, offsetUs, mediaPeriodId); } @Override @@ -400,9 +400,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException { - videoSink.flush(/* resetPosition= */ true); + if (!joining) { + videoSink.flush(/* resetPosition= */ true); + timestampIterator = createTimestampIterator(positionUs); + } super.onPositionReset(positionUs, joining); - timestampIterator = createTimestampIterator(positionUs); } @Override