Remove implementation of DefaultVideoSink.onRendererEnabled

The goal is to get rid of VideoSink.onRendererEnabled so that this
interface becomes renderer-agnostic. Indeed, for multi video sequences,
the DefaultVideoSink won't receive input from a single renderer anymore.

This is a no-op refactoring

PiperOrigin-RevId: 738296515
This commit is contained in:
kimvde 2025-03-19 01:22:06 -07:00 committed by Copybara-Service
parent d0d76f214a
commit 14c06eaf8e
11 changed files with 134 additions and 70 deletions

View File

@ -17,9 +17,6 @@ package androidx.media3.exoplayer.video;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_IMMEDIATELY;
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED;
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_STARTED;
import android.graphics.Bitmap;
import android.view.Surface;
@ -82,11 +79,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
videoFrameMetadataListener = (presentationTimeUs, releaseTimeNs, format, mediaFormat) -> {};
}
/**
* {@inheritDoc}
*
* <p>This method will always throw an {@link UnsupportedOperationException}.
*/
@Override
public void onRendererEnabled(boolean mayRenderStartOfStream) {
int firstFrameReleaseInstruction =
mayRenderStartOfStream ? RELEASE_FIRST_FRAME_IMMEDIATELY : RELEASE_FIRST_FRAME_WHEN_STARTED;
videoFrameRenderControl.onStreamChanged(firstFrameReleaseInstruction, streamStartPositionUs);
throw new UnsupportedOperationException();
}
@Override
@ -197,9 +197,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
videoFrameReleaseControl.setChangeFrameRateStrategy(changeFrameRateStrategy);
}
/**
* {@inheritDoc}
*
* <p>This method will always throw an {@link UnsupportedOperationException}.
*/
@Override
public void enableMayRenderStartOfStream() {
videoFrameReleaseControl.allowReleaseFirstFrameBeforeStarted();
throw new UnsupportedOperationException();
}
/**
@ -209,7 +214,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
*/
@Override
public void onInputStreamChanged(
@InputType int inputType, Format format, long startPositionUs, List<Effect> videoEffects) {
@InputType int inputType,
Format format,
long startPositionUs,
@FirstFrameReleaseInstruction int firstFrameReleaseInstruction,
List<Effect> videoEffects) {
checkState(videoEffects.isEmpty());
if (format.width != inputFormat.width || format.height != inputFormat.height) {
videoFrameRenderControl.onVideoSizeChanged(format.width, format.height);
@ -219,8 +228,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
inputFormat = format;
if (startPositionUs != this.streamStartPositionUs) {
videoFrameRenderControl.onStreamChanged(
RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED, startPositionUs);
videoFrameRenderControl.onStreamChanged(firstFrameReleaseInstruction, startPositionUs);
this.streamStartPositionUs = startPositionUs;
}
}

View File

@ -22,9 +22,9 @@ import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_MAX_INPUT_SIZE_EXCEEDED;
import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_VIDEO_MAX_RESOLUTION_EXCEEDED;
import static androidx.media3.exoplayer.DecoderReuseEvaluation.REUSE_RESULT_NO;
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_IMMEDIATELY;
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED;
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_STARTED;
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 static java.lang.Math.max;
import static java.lang.Math.min;
@ -1650,7 +1650,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
}
/**
* Called when ready to {@linkplain VideoSink#onInputStreamChanged(int, Format, long, List)
* Called when ready to {@linkplain VideoSink#onInputStreamChanged(int, Format, long, int, List)
* change} the input stream.
*
* <p>The default implementation applies this renderer's video effects.
@ -1659,7 +1659,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
VideoSink videoSink, @VideoSink.InputType int inputType, Format format) {
List<Effect> videoEffectsToApply = videoEffects != null ? videoEffects : ImmutableList.of();
videoSink.onInputStreamChanged(
inputType, format, getOutputStreamStartPositionUs(), videoEffectsToApply);
inputType,
format,
getOutputStreamStartPositionUs(),
RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED,
videoEffectsToApply);
}
@Override

View File

@ -22,6 +22,7 @@ import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.common.util.Util.contains;
import static androidx.media3.common.util.Util.getMaxPendingFramesCountForMediaCodecDecoders;
import static androidx.media3.exoplayer.video.VideoSink.INPUT_TYPE_SURFACE;
import static androidx.media3.exoplayer.video.VideoSink.RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.content.Context;
@ -297,6 +298,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
private @MonotonicNonNull HandlerWrapper handler;
private @MonotonicNonNull VideoGraph videoGraph;
private long outputStreamStartPositionUs;
private @VideoSink.FirstFrameReleaseInstruction int nextFirstOutputFrameReleaseInstruction;
@Nullable private Pair<Surface, Size> currentSurfaceAndSize;
private int pendingFlushCount;
private @State int state;
@ -347,6 +349,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
listeners = new CopyOnWriteArraySet<>();
requestOpenGlToneMapping = builder.requestOpenGlToneMapping;
videoGraphOutputFormat = new Format.Builder().build();
outputStreamStartPositionUs = C.TIME_UNSET;
lastOutputBufferPresentationTimeUs = C.TIME_UNSET;
finalBufferPresentationTimeUs = C.TIME_UNSET;
totalVideoInputCount = C.LENGTH_UNSET;
@ -425,13 +428,13 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
// We forward output size changes to the sink even if we are still flushing.
videoGraphOutputFormat =
videoGraphOutputFormat.buildUpon().setWidth(width).setHeight(height).build();
onOutputStreamChanged();
onOutputStreamChanged(nextFirstOutputFrameReleaseInstruction);
}
@Override
public void onOutputFrameRateChanged(float frameRate) {
videoGraphOutputFormat = videoGraphOutputFormat.buildUpon().setFrameRate(frameRate).build();
onOutputStreamChanged();
onOutputStreamChanged(nextFirstOutputFrameReleaseInstruction);
}
@Override
@ -453,7 +456,8 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
if (newOutputStreamStartPositionUs != null
&& newOutputStreamStartPositionUs != outputStreamStartPositionUs) {
outputStreamStartPositionUs = newOutputStreamStartPositionUs;
onOutputStreamChanged();
onOutputStreamChanged(nextFirstOutputFrameReleaseInstruction);
nextFirstOutputFrameReleaseInstruction = RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED;
}
boolean isLastFrame =
finalBufferPresentationTimeUs != C.TIME_UNSET
@ -598,7 +602,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
if (streamStartPositionsUs.size() == 1) {
// Use the latest startPositionUs if none is passed after flushing.
outputStreamStartPositionUs = checkNotNull(streamStartPositionsUs.pollFirst());
onOutputStreamChanged();
onOutputStreamChanged(nextFirstOutputFrameReleaseInstruction);
}
lastOutputBufferPresentationTimeUs = C.TIME_UNSET;
finalBufferPresentationTimeUs = C.TIME_UNSET;
@ -635,11 +639,13 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
return inputColorInfo;
}
private void onOutputStreamChanged() {
private void onOutputStreamChanged(
@VideoSink.FirstFrameReleaseInstruction int firstFrameReleaseInstruction) {
defaultVideoSink.onInputStreamChanged(
INPUT_TYPE_SURFACE,
videoGraphOutputFormat,
outputStreamStartPositionUs,
firstFrameReleaseInstruction,
/* videoEffects= */ ImmutableList.of());
}
@ -680,7 +686,10 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
@Override
public void onRendererEnabled(boolean mayRenderStartOfStream) {
defaultVideoSink.onRendererEnabled(mayRenderStartOfStream);
nextFirstOutputFrameReleaseInstruction =
mayRenderStartOfStream
? RELEASE_FIRST_FRAME_IMMEDIATELY
: RELEASE_FIRST_FRAME_WHEN_STARTED;
}
@Override
@ -765,7 +774,11 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
@Override
public void onInputStreamChanged(
@InputType int inputType, Format format, long startPositionUs, List<Effect> videoEffects) {
@InputType int inputType,
Format format,
long startPositionUs,
@FirstFrameReleaseInstruction int firstFrameReleaseInstruction,
List<Effect> videoEffects) {
checkState(isInitialized());
switch (inputType) {
case INPUT_TYPE_SURFACE:
@ -844,7 +857,9 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
@Override
public void enableMayRenderStartOfStream() {
defaultVideoSink.enableMayRenderStartOfStream();
if (nextFirstOutputFrameReleaseInstruction == RELEASE_FIRST_FRAME_WHEN_STARTED) {
nextFirstOutputFrameReleaseInstruction = RELEASE_FIRST_FRAME_IMMEDIATELY;
}
}
@Override

View File

@ -17,6 +17,9 @@ package androidx.media3.exoplayer.video;
import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Util.msToUs;
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 java.lang.Math.min;
import static java.lang.annotation.ElementType.TYPE_USE;
@ -40,35 +43,6 @@ import java.lang.annotation.Target;
@UnstableApi
public final class VideoFrameReleaseControl {
/**
* The instruction provided to {@link #onStreamChanged(int)} for releasing the first frame.
*
* <p>One of {@link #RELEASE_FIRST_FRAME_IMMEDIATELY}, {@link #RELEASE_FIRST_FRAME_WHEN_STARTED}
* or {@link #RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@UnstableApi
@IntDef({
RELEASE_FIRST_FRAME_IMMEDIATELY,
RELEASE_FIRST_FRAME_WHEN_STARTED,
RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED
})
public @interface FirstFrameReleaseInstruction {}
/** Instructs to release the first frame as soon as possible. */
public static final int RELEASE_FIRST_FRAME_IMMEDIATELY = 0;
/** Instructs to release the first frame when rendering starts. */
public static final int RELEASE_FIRST_FRAME_WHEN_STARTED = 1;
/**
* Instructs to release the first frame when the playback position reaches the stream start
* position.
*/
public static final int RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED = 2;
/**
* The frame release action returned by {@link #getFrameReleaseAction(long, long, long, long,
* boolean, boolean, FrameReleaseInfo)}.
@ -241,7 +215,8 @@ public final class VideoFrameReleaseControl {
*
* <p>Must also be called for the first stream.
*/
public void onStreamChanged(@FirstFrameReleaseInstruction int firstFrameReleaseInstruction) {
public void onStreamChanged(
@VideoSink.FirstFrameReleaseInstruction int firstFrameReleaseInstruction) {
switch (firstFrameReleaseInstruction) {
case RELEASE_FIRST_FRAME_IMMEDIATELY:
firstFrameState = C.FIRST_FRAME_NOT_RENDERED;

View File

@ -17,7 +17,7 @@ package androidx.media3.exoplayer.video;
import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED;
import static androidx.media3.exoplayer.video.VideoSink.RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
@ -179,7 +179,7 @@ import androidx.media3.exoplayer.ExoPlaybackException;
}
public void onStreamChanged(
@VideoFrameReleaseControl.FirstFrameReleaseInstruction int firstFrameReleaseInstruction,
@VideoSink.FirstFrameReleaseInstruction int firstFrameReleaseInstruction,
long streamStartPositionUs) {
if (presentationTimestampsUs.isEmpty()) {
videoFrameReleaseControl.onStreamChanged(firstFrameReleaseInstruction);

View File

@ -125,6 +125,35 @@ public interface VideoSink {
/** Input frames come from a {@link Bitmap}. */
int INPUT_TYPE_BITMAP = 2;
/**
* The instruction provided when the stream changes for releasing the first frame.
*
* <p>One of {@link #RELEASE_FIRST_FRAME_IMMEDIATELY}, {@link #RELEASE_FIRST_FRAME_WHEN_STARTED}
* or {@link #RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED}.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@UnstableApi
@IntDef({
RELEASE_FIRST_FRAME_IMMEDIATELY,
RELEASE_FIRST_FRAME_WHEN_STARTED,
RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED
})
@interface FirstFrameReleaseInstruction {}
/** Instructs to release the first frame as soon as possible. */
int RELEASE_FIRST_FRAME_IMMEDIATELY = 0;
/** Instructs to release the first frame when rendering starts. */
int RELEASE_FIRST_FRAME_WHEN_STARTED = 1;
/**
* Instructs to release the first frame when the playback position reaches the stream start
* position.
*/
int RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED = 2;
/** Called when the {@link Renderer} currently feeding this sink is enabled. */
void onRendererEnabled(boolean mayRenderStartOfStream);
@ -188,7 +217,7 @@ public interface VideoSink {
*
* <p>This method returns {@code true} if the end of the last input stream has been {@linkplain
* #signalEndOfCurrentInputStream() signaled} and all the input frames have been rendered. Note
* that a new input stream can be {@linkplain #onInputStreamChanged(int, Format, long, List)
* that a new input stream can be {@linkplain #onInputStreamChanged(int, Format, long, int, List)
* signaled} even when this method returns true (in which case the sink will not be ended
* anymore).
*/
@ -250,16 +279,22 @@ public interface VideoSink {
* @param format The {@link Format} of the stream.
* @param startPositionUs The start position of the buffer presentation timestamps of the stream,
* in microseconds.
* @param firstFrameReleaseInstruction The {@link FirstFrameReleaseInstruction} indicating when to
* release the stream's first frame.
* @param videoEffects The {@link List<Effect>} to apply to the new stream.
*/
void onInputStreamChanged(
@InputType int inputType, Format format, long startPositionUs, List<Effect> videoEffects);
@InputType int inputType,
Format format,
long startPositionUs,
@FirstFrameReleaseInstruction int firstFrameReleaseInstruction,
List<Effect> videoEffects);
/**
* Handles a video input frame.
*
* <p>Must be called after the corresponding stream is {@linkplain #onInputStreamChanged(int,
* Format, long, List) signaled}.
* Format, long, int, List) signaled}.
*
* @param framePresentationTimeUs The frame's presentation time, in microseconds.
* @param isLastFrame Whether this is the last frame of the video stream. This flag is set on a
@ -276,7 +311,7 @@ public interface VideoSink {
* Handles an input {@link Bitmap}.
*
* <p>Must be called after the corresponding stream is {@linkplain #onInputStreamChanged(int,
* Format, long, List) signaled}.
* Format, long, int, List) signaled}.
*
* @param inputBitmap The {@link Bitmap} to queue to the video sink.
* @param timestampIterator The times within the current stream that the bitmap should be shown

View File

@ -15,6 +15,8 @@
*/
package androidx.media3.exoplayer.video;
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 com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
@ -80,10 +82,24 @@ public final class PlaybackVideoGraphWrapperTest {
sink.initialize(format);
sink.onInputStreamChanged(VideoSink.INPUT_TYPE_SURFACE, format, startPositionUs, firstEffects);
sink.onInputStreamChanged(VideoSink.INPUT_TYPE_SURFACE, format, startPositionUs, secondEffects);
sink.onInputStreamChanged(
VideoSink.INPUT_TYPE_SURFACE, format, startPositionUs, ImmutableList.of());
VideoSink.INPUT_TYPE_SURFACE,
format,
startPositionUs,
RELEASE_FIRST_FRAME_IMMEDIATELY,
firstEffects);
sink.onInputStreamChanged(
VideoSink.INPUT_TYPE_SURFACE,
format,
startPositionUs,
RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED,
secondEffects);
sink.onInputStreamChanged(
VideoSink.INPUT_TYPE_SURFACE,
format,
startPositionUs,
RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED,
ImmutableList.of());
testVideoGraphFactory.verifyRegisteredEffectsMatches(/* invocationTimes= */ 3);
assertThat(testVideoGraphFactory.getCapturedEffects())
.isEqualTo(ImmutableList.of(firstEffects, secondEffects, ImmutableList.of()));

View File

@ -15,8 +15,8 @@
*/
package androidx.media3.exoplayer.video;
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_IMMEDIATELY;
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_STARTED;
import static androidx.media3.exoplayer.video.VideoSink.RELEASE_FIRST_FRAME_IMMEDIATELY;
import static androidx.media3.exoplayer.video.VideoSink.RELEASE_FIRST_FRAME_WHEN_STARTED;
import static com.google.common.truth.Truth.assertThat;
import android.graphics.SurfaceTexture;
@ -587,7 +587,7 @@ public class VideoFrameReleaseControlTest {
/* isDecodeOnlyFrame= */ true,
/* isLastFrame= */ true,
frameReleaseInfo))
.isEqualTo(VideoFrameReleaseControl.RELEASE_FIRST_FRAME_IMMEDIATELY);
.isEqualTo(RELEASE_FIRST_FRAME_IMMEDIATELY);
}
@Test

View File

@ -15,8 +15,8 @@
*/
package androidx.media3.exoplayer.video;
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_IMMEDIATELY;
import static androidx.media3.exoplayer.video.VideoFrameReleaseControl.RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED;
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 com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;

View File

@ -220,10 +220,15 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Override
public void onInputStreamChanged(
@InputType int inputType, Format format, long startPositionUs, List<Effect> videoEffects) {
@InputType int inputType,
Format format,
long startPositionUs,
@FirstFrameReleaseInstruction int firstFrameReleaseInstruction,
List<Effect> videoEffects) {
executeOrDelay(
videoSink ->
videoSink.onInputStreamChanged(inputType, format, startPositionUs, videoEffects));
videoSink.onInputStreamChanged(
inputType, format, startPositionUs, firstFrameReleaseInstruction, videoEffects));
}
/**

View File

@ -24,6 +24,7 @@ import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.common.util.Util.SDK_INT;
import static androidx.media3.exoplayer.DefaultRenderersFactory.DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS;
import static androidx.media3.exoplayer.DefaultRenderersFactory.MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY;
import static androidx.media3.exoplayer.video.VideoSink.RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED;
import android.content.Context;
import android.graphics.Bitmap;
@ -436,7 +437,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
protected void changeVideoSinkInputStream(
VideoSink videoSink, @VideoSink.InputType int inputType, Format format) {
videoSink.onInputStreamChanged(
inputType, format, getOutputStreamStartPositionUs(), pendingEffects);
inputType,
format,
getOutputStreamStartPositionUs(),
RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED,
pendingEffects);
}
private void activateBufferingVideoSink() {
@ -625,6 +630,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
.setFrameRate(/* frameRate= */ DEFAULT_FRAME_RATE)
.build(),
streamStartPositionUs,
RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED,
videoEffects);
inputStreamPending = false;
}