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 new file mode 100644 index 0000000000..ba176111b1 --- /dev/null +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/DefaultVideoSink.java @@ -0,0 +1,181 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package androidx.media3.exoplayer.video; + +import android.graphics.Bitmap; +import android.view.Surface; +import androidx.media3.common.Effect; +import androidx.media3.common.Format; +import androidx.media3.common.util.Size; +import androidx.media3.common.util.TimestampIterator; +import java.util.List; +import java.util.concurrent.Executor; + +/** + * The default {@link VideoSink} implementation. This implementation renders video frames to an + * output surface. Applying {@linkplain Effect video effects} is unsupported. + */ +/* package */ final class DefaultVideoSink implements VideoSink { + + private final VideoFrameReleaseControl videoFrameReleaseControl; + private final VideoFrameRenderControl videoFrameRenderControl; + + public DefaultVideoSink( + VideoFrameReleaseControl videoFrameReleaseControl, + VideoFrameRenderControl videoFrameRenderControl) { + this.videoFrameReleaseControl = videoFrameReleaseControl; + this.videoFrameRenderControl = videoFrameRenderControl; + } + + @Override + public void onRendererEnabled(boolean mayRenderStartOfStream) { + videoFrameReleaseControl.onEnabled(mayRenderStartOfStream); + } + + @Override + public void onRendererDisabled() { + videoFrameReleaseControl.onDisabled(); + } + + @Override + public void onRendererStarted() { + videoFrameReleaseControl.onStarted(); + } + + @Override + public void onRendererStopped() { + videoFrameReleaseControl.onStopped(); + } + + @Override + public void setListener(Listener listener, Executor executor) { + throw new UnsupportedOperationException(); + } + + @Override + public void initialize(Format sourceFormat) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isInitialized() { + throw new UnsupportedOperationException(); + } + + @Override + public void flush(boolean resetPosition) { + if (resetPosition) { + videoFrameReleaseControl.reset(); + } + } + + @Override + public boolean isReady(boolean rendererOtherwiseReady) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isEnded() { + throw new UnsupportedOperationException(); + } + + @Override + public Surface getInputSurface() { + throw new UnsupportedOperationException(); + } + + @Override + public void setVideoFrameMetadataListener(VideoFrameMetadataListener videoFrameMetadataListener) { + throw new UnsupportedOperationException(); + } + + @Override + public void setPlaybackSpeed(float speed) { + videoFrameRenderControl.setPlaybackSpeed(speed); + } + + @Override + public void setVideoEffects(List videoEffects) { + throw new UnsupportedOperationException(); + } + + @Override + public void setPendingVideoEffects(List videoEffects) { + throw new UnsupportedOperationException(); + } + + @Override + public void setStreamTimestampInfo( + long streamStartPositionUs, + long streamOffsetUs, + long bufferTimestampAdjustmentUs, + long lastResetPositionUs) { + throw new UnsupportedOperationException(); + } + + @Override + public void setOutputSurfaceInfo(Surface outputSurface, Size outputResolution) { + throw new UnsupportedOperationException(); + } + + @Override + public void clearOutputSurfaceInfo() { + throw new UnsupportedOperationException(); + } + + @Override + public void setChangeFrameRateStrategy(int changeFrameRateStrategy) { + videoFrameReleaseControl.setChangeFrameRateStrategy(changeFrameRateStrategy); + } + + @Override + public void enableMayRenderStartOfStream() { + videoFrameReleaseControl.allowReleaseFirstFrameBeforeStarted(); + } + + @Override + public void onInputStreamChanged(@InputType int inputType, Format format) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean handleInputFrame( + long framePresentationTimeUs, + boolean isLastFrame, + long positionUs, + long elapsedRealtimeUs, + VideoFrameHandler videoFrameHandler) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean handleInputBitmap(Bitmap inputBitmap, TimestampIterator timestampIterator) { + throw new UnsupportedOperationException(); + } + + @Override + public void render(long positionUs, long elapsedRealtimeUs) { + throw new UnsupportedOperationException(); + } + + @Override + public void join(boolean renderNextFrameImmediately) { + videoFrameReleaseControl.join(renderNextFrameImmediately); + } + + @Override + public void release() {} +} 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 17eb925648..7648b96956 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 @@ -231,8 +231,8 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video private final VideoFrameReleaseControl videoFrameReleaseControl; private final VideoFrameRenderControl videoFrameRenderControl; private final PreviewingVideoGraph.Factory previewingVideoGraphFactory; - private final List compositionEffects; + private final VideoSink defaultVideoSink; private final Clock clock; private final CopyOnWriteArraySet listeners; @@ -261,6 +261,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video new VideoFrameRenderControl(new FrameRendererImpl(), videoFrameReleaseControl); previewingVideoGraphFactory = checkStateNotNull(builder.previewingVideoGraphFactory); compositionEffects = builder.compositionEffects; + defaultVideoSink = new DefaultVideoSink(videoFrameReleaseControl, videoFrameRenderControl); listeners = new CopyOnWriteArraySet<>(); state = STATE_CREATED; addListener(inputVideoSink); @@ -465,7 +466,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video } private void setPlaybackSpeed(float speed) { - videoFrameRenderControl.setPlaybackSpeed(speed); + defaultVideoSink.setPlaybackSpeed(speed); } private void onStreamOffsetChange( @@ -529,22 +530,22 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video @Override public void onRendererEnabled(boolean mayRenderStartOfStream) { - videoFrameReleaseControl.onEnabled(mayRenderStartOfStream); + defaultVideoSink.onRendererEnabled(mayRenderStartOfStream); } @Override public void onRendererDisabled() { - videoFrameReleaseControl.onDisabled(); + defaultVideoSink.onRendererDisabled(); } @Override public void onRendererStarted() { - videoFrameReleaseControl.onStarted(); + defaultVideoSink.onRendererStarted(); } @Override public void onRendererStopped() { - videoFrameReleaseControl.onStopped(); + defaultVideoSink.onRendererStopped(); } @Override @@ -574,9 +575,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video finalBufferPresentationTimeUs = C.TIME_UNSET; lastBufferPresentationTimeUs = C.TIME_UNSET; PlaybackVideoGraphWrapper.this.flush(); - if (resetPosition) { - videoFrameReleaseControl.reset(); - } + defaultVideoSink.flush(resetPosition); pendingInputStreamBufferPresentationTimeUs = C.TIME_UNSET; // Don't change input stream offset or reset the pending input stream offset change so that // it's announced with the next input frame. @@ -689,12 +688,12 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video @Override public void setChangeFrameRateStrategy( @C.VideoChangeFrameRateStrategy int changeFrameRateStrategy) { - videoFrameReleaseControl.setChangeFrameRateStrategy(changeFrameRateStrategy); + defaultVideoSink.setChangeFrameRateStrategy(changeFrameRateStrategy); } @Override public void enableMayRenderStartOfStream() { - videoFrameReleaseControl.allowReleaseFirstFrameBeforeStarted(); + defaultVideoSink.enableMayRenderStartOfStream(); } @Override @@ -820,7 +819,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video @Override public void join(boolean renderNextFrameImmediately) { - videoFrameReleaseControl.join(renderNextFrameImmediately); + defaultVideoSink.join(renderNextFrameImmediately); } @Override