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 95e0558ae6..65081b0dfd 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 @@ -426,8 +426,9 @@ public final class CompositingVideoSinkProvider implements VideoSinkProvider, Vi } } - private boolean isReady() { - return pendingFlushCount == 0 && videoFrameRenderControl.isReady(); + private boolean isReady(boolean rendererOtherwiseReady) { + return videoFrameRenderControl.isReady( + /* rendererOtherwiseReady= */ rendererOtherwiseReady && pendingFlushCount == 0); } private boolean hasReleasedFrame(long presentationTimeUs) { @@ -585,8 +586,9 @@ public final class CompositingVideoSinkProvider implements VideoSinkProvider, Vi } @Override - public boolean isReady() { - return isInitialized() && CompositingVideoSinkProvider.this.isReady(); + public boolean isReady(boolean rendererOtherwiseReady) { + return CompositingVideoSinkProvider.this.isReady( + /* rendererOtherwiseReady= */ rendererOtherwiseReady && isInitialized()); } @Override 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 8a90f05e2f..af5a7002da 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 @@ -748,15 +748,18 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer @Override public boolean isReady() { - boolean readyToReleaseFrames = super.isReady() && (videoSink == null || videoSink.isReady()); - if (readyToReleaseFrames + boolean rendererOtherwiseReady = super.isReady(); + if (videoSink != null) { + return videoSink.isReady(rendererOtherwiseReady); + } + if (rendererOtherwiseReady && ((placeholderSurface != null && displaySurface == placeholderSurface) || getCodec() == null || tunneling)) { // Not releasing frames. return true; } - return videoFrameReleaseControl.isReady(readyToReleaseFrames); + return videoFrameReleaseControl.isReady(rendererOtherwiseReady); } @Override 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 565322d994..1ffa491e4e 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 @@ -277,12 +277,14 @@ public final class VideoFrameReleaseControl { /** * Whether the release control is ready to start playback. * - * @see Renderer#isReady() - * @param rendererReady Whether the renderer is ready. + *
The renderer should be {@linkplain Renderer#isReady() ready} if and only if the release + * control is ready. + * + * @param rendererOtherwiseReady Whether the renderer is ready except for the release control. * @return Whether the release control is ready. */ - public boolean isReady(boolean rendererReady) { - if (rendererReady && firstFrameState == C.FIRST_FRAME_RENDERED) { + public boolean isReady(boolean rendererOtherwiseReady) { + if (rendererOtherwiseReady && firstFrameState == C.FIRST_FRAME_RENDERED) { // Ready. If we were joining then we've now joined, so clear the joining deadline. joiningDeadlineMs = C.TIME_UNSET; return true; diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoFrameRenderControl.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoFrameRenderControl.java index 624c977c81..ed8e089daf 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoFrameRenderControl.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/video/VideoFrameRenderControl.java @@ -123,8 +123,8 @@ import androidx.media3.exoplayer.ExoPlaybackException; } /** Returns whether the renderer is ready. */ - public boolean isReady() { - return videoFrameReleaseControl.isReady(/* rendererReady= */ true); + public boolean isReady(boolean rendererOtherwiseReady) { + return videoFrameReleaseControl.isReady(rendererOtherwiseReady); } /** 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 a360f5de67..091281fe94 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,6 +28,7 @@ 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; @@ -148,8 +149,13 @@ public interface VideoSink { /** * Returns whether the video sink is able to immediately render media from the current position. + * + *
The renderer should be {@linkplain Renderer#isReady() ready} if and only if the video sink
+ * is ready.
+ *
+ * @param rendererOtherwiseReady Whether the renderer is ready except for the video sink.
*/
- boolean isReady();
+ boolean isReady(boolean rendererOtherwiseReady);
/**
* Returns whether all queued video frames have been rendered, including the frame marked as last
diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/VideoFrameReleaseControlTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/VideoFrameReleaseControlTest.java
index 109efcf04a..6e6f8cfc86 100644
--- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/VideoFrameReleaseControlTest.java
+++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/VideoFrameReleaseControlTest.java
@@ -31,8 +31,8 @@ public class VideoFrameReleaseControlTest {
public void isReady_onNewInstance_returnsFalse() {
VideoFrameReleaseControl videoFrameReleaseControl = createVideoFrameReleaseControl();
- assertThat(videoFrameReleaseControl.isReady(/* rendererReady= */ true)).isFalse();
- assertThat(videoFrameReleaseControl.isReady(/* rendererReady= */ false)).isFalse();
+ assertThat(videoFrameReleaseControl.isReady(/* rendererOtherwiseReady= */ true)).isFalse();
+ assertThat(videoFrameReleaseControl.isReady(/* rendererOtherwiseReady= */ false)).isFalse();
}
@Test
@@ -40,7 +40,7 @@ public class VideoFrameReleaseControlTest {
VideoFrameReleaseControl videoFrameReleaseControl = createVideoFrameReleaseControl();
assertThat(videoFrameReleaseControl.onFrameReleasedIsFirstFrame()).isTrue();
- assertThat(videoFrameReleaseControl.isReady(/* rendererReady= */ true)).isTrue();
+ assertThat(videoFrameReleaseControl.isReady(/* rendererOtherwiseReady= */ true)).isTrue();
}
@Test
@@ -52,7 +52,7 @@ public class VideoFrameReleaseControlTest {
videoFrameReleaseControl.join(/* renderNextFrameImmediately= */ true);
- assertThat(videoFrameReleaseControl.isReady(/* rendererReady= */ false)).isTrue();
+ assertThat(videoFrameReleaseControl.isReady(/* rendererOtherwiseReady= */ false)).isTrue();
}
@Test
@@ -64,7 +64,7 @@ public class VideoFrameReleaseControlTest {
videoFrameReleaseControl.join(/* renderNextFrameImmediately= */ false);
- assertThat(videoFrameReleaseControl.isReady(/* rendererReady= */ false)).isTrue();
+ assertThat(videoFrameReleaseControl.isReady(/* rendererOtherwiseReady= */ false)).isTrue();
}
@Test
@@ -75,11 +75,11 @@ public class VideoFrameReleaseControlTest {
videoFrameReleaseControl.setClock(clock);
videoFrameReleaseControl.join(/* renderNextFrameImmediately= */ true);
- assertThat(videoFrameReleaseControl.isReady(/* rendererReady= */ false)).isTrue();
+ assertThat(videoFrameReleaseControl.isReady(/* rendererOtherwiseReady= */ false)).isTrue();
clock.advanceTime(/* timeDiffMs= */ 101);
- assertThat(videoFrameReleaseControl.isReady(/* rendererReady= */ false)).isFalse();
+ assertThat(videoFrameReleaseControl.isReady(/* rendererOtherwiseReady= */ false)).isFalse();
}
@Test
@@ -90,11 +90,11 @@ public class VideoFrameReleaseControlTest {
videoFrameReleaseControl.setClock(clock);
videoFrameReleaseControl.join(/* renderNextFrameImmediately= */ false);
- assertThat(videoFrameReleaseControl.isReady(/* rendererReady= */ false)).isTrue();
+ assertThat(videoFrameReleaseControl.isReady(/* rendererOtherwiseReady= */ false)).isTrue();
clock.advanceTime(/* timeDiffMs= */ 101);
- assertThat(videoFrameReleaseControl.isReady(/* rendererReady= */ false)).isFalse();
+ assertThat(videoFrameReleaseControl.isReady(/* rendererOtherwiseReady= */ false)).isFalse();
}
@Test
@@ -132,10 +132,10 @@ public class VideoFrameReleaseControlTest {
VideoFrameReleaseControl videoFrameReleaseControl = createVideoFrameReleaseControl();
videoFrameReleaseControl.onFrameReleasedIsFirstFrame();
- assertThat(videoFrameReleaseControl.isReady(/* rendererReady= */ true)).isTrue();
+ assertThat(videoFrameReleaseControl.isReady(/* rendererOtherwiseReady= */ true)).isTrue();
videoFrameReleaseControl.reset();
- assertThat(videoFrameReleaseControl.isReady(/* rendererReady= */ true)).isFalse();
+ assertThat(videoFrameReleaseControl.isReady(/* rendererOtherwiseReady= */ true)).isFalse();
}
@Test
diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/VideoFrameRenderControlTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/VideoFrameRenderControlTest.java
index 92dda8db51..727f4dd57c 100644
--- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/VideoFrameRenderControlTest.java
+++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/video/VideoFrameRenderControlTest.java
@@ -43,7 +43,7 @@ public class VideoFrameRenderControlTest {
new VideoFrameRenderControl(
mock(VideoFrameRenderControl.FrameRenderer.class), createVideoFrameReleaseControl());
- assertThat(videoFrameRenderControl.isReady()).isFalse();
+ assertThat(videoFrameRenderControl.isReady(/* rendererOtherwiseReady= */ true)).isFalse();
}
@Test
@@ -60,7 +60,7 @@ public class VideoFrameRenderControlTest {
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 0);
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
- assertThat(videoFrameRenderControl.isReady()).isTrue();
+ assertThat(videoFrameRenderControl.isReady(/* rendererOtherwiseReady= */ true)).isTrue();
InOrder inOrder = Mockito.inOrder(frameRenderer);
inOrder
.verify(frameRenderer)
@@ -92,7 +92,7 @@ public class VideoFrameRenderControlTest {
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 10_000);
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
- assertThat(videoFrameRenderControl.isReady()).isTrue();
+ assertThat(videoFrameRenderControl.isReady(/* rendererOtherwiseReady= */ true)).isTrue();
InOrder inOrder = Mockito.inOrder(frameRenderer);
inOrder
.verify(frameRenderer)
@@ -141,7 +141,7 @@ public class VideoFrameRenderControlTest {
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 0);
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
- assertThat(videoFrameRenderControl.isReady()).isTrue();
+ assertThat(videoFrameRenderControl.isReady(/* rendererOtherwiseReady= */ true)).isTrue();
InOrder inOrder = Mockito.inOrder(frameRenderer);
inOrder
.verify(frameRenderer)
diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/SequencePlayerRenderersWrapper.java b/libraries/transformer/src/main/java/androidx/media3/transformer/SequencePlayerRenderersWrapper.java
index 862766a747..bc2f65a28a 100644
--- a/libraries/transformer/src/main/java/androidx/media3/transformer/SequencePlayerRenderersWrapper.java
+++ b/libraries/transformer/src/main/java/androidx/media3/transformer/SequencePlayerRenderersWrapper.java
@@ -48,7 +48,6 @@ import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.text.TextOutput;
import androidx.media3.exoplayer.video.CompositingVideoSinkProvider;
import androidx.media3.exoplayer.video.MediaCodecVideoRenderer;
-import androidx.media3.exoplayer.video.VideoFrameReleaseControl;
import androidx.media3.exoplayer.video.VideoRendererEventListener;
import androidx.media3.exoplayer.video.VideoSink;
import com.google.common.collect.ImmutableList;
@@ -296,7 +295,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final SequencePlayerRenderersWrapper sequencePlayerRenderersWrapper;
private final CompositingVideoSinkProvider compositingVideoSinkProvider;
private final VideoSink videoSink;
- private final VideoFrameReleaseControl videoFrameReleaseControl;
private ImmutableList