Split VideoSink.setStreamTimestampInfo

This is a step towards merging setStreamStartPositionUs with
onInputStreamChanged, which makes sense as the start position can only
change on stream change.

PiperOrigin-RevId: 735309009
This commit is contained in:
kimvde 2025-03-10 03:22:06 -07:00 committed by Copybara-Service
parent a4442a6cc5
commit 15fa27cd9a
6 changed files with 34 additions and 19 deletions

View File

@ -178,12 +178,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
@Override @Override
public void setStreamTimestampInfo(long streamStartPositionUs, long bufferTimestampAdjustmentUs) { public void setStreamStartPositionUs(long streamStartPositionUs) {
if (streamStartPositionUs != this.streamStartPositionUs) { if (streamStartPositionUs != this.streamStartPositionUs) {
videoFrameRenderControl.onStreamChanged( videoFrameRenderControl.onStreamChanged(
RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED, streamStartPositionUs); RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED, streamStartPositionUs);
this.streamStartPositionUs = streamStartPositionUs; this.streamStartPositionUs = streamStartPositionUs;
} }
}
@Override
public void setBufferTimestampAdjustmentUs(long bufferTimestampAdjustmentUs) {
this.bufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs; this.bufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs;
} }

View File

@ -965,8 +965,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
if (this.startPositionUs == C.TIME_UNSET) { if (this.startPositionUs == C.TIME_UNSET) {
this.startPositionUs = startPositionUs; this.startPositionUs = startPositionUs;
if (videoSink != null) { if (videoSink != null) {
videoSink.setStreamTimestampInfo( videoSink.setStreamStartPositionUs(getOutputStreamStartPositionUs());
getOutputStreamStartPositionUs(), getBufferTimestampAdjustmentUs()); videoSink.setBufferTimestampAdjustmentUs(getBufferTimestampAdjustmentUs());
} }
} }
updatePeriodDurationUs(mediaPeriodId); updatePeriodDurationUs(mediaPeriodId);
@ -1868,8 +1868,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
if (videoSink != null) { if (videoSink != null) {
// Signaling end of the previous stream. // Signaling end of the previous stream.
videoSink.signalEndOfCurrentInputStream(); videoSink.signalEndOfCurrentInputStream();
videoSink.setStreamTimestampInfo( videoSink.setStreamStartPositionUs(getOutputStreamStartPositionUs());
getOutputStreamStartPositionUs(), getBufferTimestampAdjustmentUs()); videoSink.setBufferTimestampAdjustmentUs(getBufferTimestampAdjustmentUs());
} else { } else {
videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED); videoFrameReleaseControl.onStreamChanged(RELEASE_FIRST_FRAME_WHEN_PREVIOUS_STREAM_PROCESSED);
} }

View File

@ -441,8 +441,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
streamStartPositionsUs.pollFloor(bufferPresentationTimeUs); streamStartPositionsUs.pollFloor(bufferPresentationTimeUs);
if (newOutputStreamStartPositionUs != null if (newOutputStreamStartPositionUs != null
&& newOutputStreamStartPositionUs != outputStreamStartPositionUs) { && newOutputStreamStartPositionUs != outputStreamStartPositionUs) {
defaultVideoSink.setStreamTimestampInfo( defaultVideoSink.setStreamStartPositionUs(newOutputStreamStartPositionUs);
newOutputStreamStartPositionUs, bufferTimestampAdjustmentUs);
outputStreamStartPositionUs = newOutputStreamStartPositionUs; outputStreamStartPositionUs = newOutputStreamStartPositionUs;
} }
boolean isLastFrame = boolean isLastFrame =
@ -589,7 +588,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
if (streamStartPositionsUs.size() == 1) { if (streamStartPositionsUs.size() == 1) {
long lastStartPositionUs = checkNotNull(streamStartPositionsUs.pollFirst()); long lastStartPositionUs = checkNotNull(streamStartPositionsUs.pollFirst());
// defaultVideoSink should use the latest startPositionUs if none is passed after flushing. // defaultVideoSink should use the latest startPositionUs if none is passed after flushing.
defaultVideoSink.setStreamTimestampInfo(lastStartPositionUs, bufferTimestampAdjustmentUs); defaultVideoSink.setStreamStartPositionUs(lastStartPositionUs);
} }
lastOutputBufferPresentationTimeUs = C.TIME_UNSET; lastOutputBufferPresentationTimeUs = C.TIME_UNSET;
finalBufferPresentationTimeUs = C.TIME_UNSET; finalBufferPresentationTimeUs = C.TIME_UNSET;
@ -610,8 +609,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
private void setBufferTimestampAdjustment(long bufferTimestampAdjustmentUs) { private void setBufferTimestampAdjustment(long bufferTimestampAdjustmentUs) {
this.bufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs; this.bufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs;
defaultVideoSink.setStreamTimestampInfo( defaultVideoSink.setBufferTimestampAdjustmentUs(bufferTimestampAdjustmentUs);
outputStreamStartPositionUs, bufferTimestampAdjustmentUs);
} }
private boolean shouldRenderToInputVideoSink() { private boolean shouldRenderToInputVideoSink() {
@ -795,14 +793,17 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
} }
@Override @Override
public void setStreamTimestampInfo( public void setStreamStartPositionUs(long streamStartPositionUs) {
long streamStartPositionUs, long bufferTimestampAdjustmentUs) {
// Input timestamps should always be positive because they are offset by ExoPlayer. Adding a // Input timestamps should always be positive because they are offset by ExoPlayer. Adding a
// position to the queue with timestamp 0 should therefore always apply it as long as it is // position to the queue with timestamp 0 should therefore always apply it as long as it is
// the only position in the queue. // the only position in the queue.
streamStartPositionsUs.add( streamStartPositionsUs.add(
lastBufferPresentationTimeUs == C.TIME_UNSET ? 0 : lastBufferPresentationTimeUs + 1, lastBufferPresentationTimeUs == C.TIME_UNSET ? 0 : lastBufferPresentationTimeUs + 1,
streamStartPositionUs); streamStartPositionUs);
}
@Override
public void setBufferTimestampAdjustmentUs(long bufferTimestampAdjustmentUs) {
inputBufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs; inputBufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs;
// The buffer timestamp adjustment is only allowed to change after a flush to make sure that // The buffer timestamp adjustment is only allowed to change after a flush to make sure that
// the buffer timestamps are increasing. We can update the buffer timestamp adjustment // the buffer timestamps are increasing. We can update the buffer timestamp adjustment

View File

@ -211,14 +211,20 @@ public interface VideoSink {
void setVideoEffects(List<Effect> videoEffects); void setVideoEffects(List<Effect> videoEffects);
/** /**
* Sets information about the timestamps of the current input stream. * Sets the current stream start position.
* *
* @param streamStartPositionUs The start position of the buffer presentation timestamps of the * @param streamStartPositionUs The start position of the buffer presentation timestamps of the
* current stream, in microseconds. * current stream, in microseconds.
*/
void setStreamStartPositionUs(long streamStartPositionUs);
/**
* Sets the buffer timestamp adjustment.
*
* @param bufferTimestampAdjustmentUs The timestamp adjustment to add to the buffer presentation * @param bufferTimestampAdjustmentUs The timestamp adjustment to add to the buffer presentation
* timestamps to convert them to frame presentation timestamps, in microseconds. * timestamps to convert them to frame presentation timestamps, in microseconds.
*/ */
void setStreamTimestampInfo(long streamStartPositionUs, long bufferTimestampAdjustmentUs); void setBufferTimestampAdjustmentUs(long bufferTimestampAdjustmentUs);
/** Sets the output surface info. */ /** Sets the output surface info. */
void setOutputSurfaceInfo(Surface outputSurface, Size outputResolution); void setOutputSurfaceInfo(Surface outputSurface, Size outputResolution);

View File

@ -193,10 +193,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
} }
@Override @Override
public void setStreamTimestampInfo(long streamStartPositionUs, long bufferTimestampAdjustmentUs) { public void setStreamStartPositionUs(long streamStartPositionUs) {
executeOrDelay(videoSink -> videoSink.setStreamStartPositionUs(streamStartPositionUs));
}
@Override
public void setBufferTimestampAdjustmentUs(long bufferTimestampAdjustmentUs) {
executeOrDelay( executeOrDelay(
videoSink -> videoSink -> videoSink.setBufferTimestampAdjustmentUs(bufferTimestampAdjustmentUs));
videoSink.setStreamTimestampInfo(streamStartPositionUs, bufferTimestampAdjustmentUs));
} }
@Override @Override

View File

@ -587,6 +587,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
int mediaItemIndex = getTimeline().getIndexOfPeriod(mediaPeriodId.periodUid); int mediaItemIndex = getTimeline().getIndexOfPeriod(mediaPeriodId.periodUid);
currentEditedMediaItem = sequence.editedMediaItems.get(mediaItemIndex); currentEditedMediaItem = sequence.editedMediaItems.get(mediaItemIndex);
offsetToCompositionTimeUs = getOffsetToCompositionTimeUs(sequence, mediaItemIndex, offsetUs); offsetToCompositionTimeUs = getOffsetToCompositionTimeUs(sequence, mediaItemIndex, offsetUs);
videoSink.setBufferTimestampAdjustmentUs(offsetToCompositionTimeUs);
timestampIterator = createTimestampIterator(/* positionUs= */ startPositionUs); timestampIterator = createTimestampIterator(/* positionUs= */ startPositionUs);
videoEffects = currentEditedMediaItem.effects.videoEffects; videoEffects = currentEditedMediaItem.effects.videoEffects;
inputStreamPending = true; inputStreamPending = true;
@ -614,8 +615,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
long positionUs, long elapsedRealtimeUs, Bitmap outputImage, long timeUs) { long positionUs, long elapsedRealtimeUs, Bitmap outputImage, long timeUs) {
if (inputStreamPending) { if (inputStreamPending) {
checkState(streamStartPositionUs != C.TIME_UNSET); checkState(streamStartPositionUs != C.TIME_UNSET);
videoSink.setStreamTimestampInfo( videoSink.setStreamStartPositionUs(streamStartPositionUs);
streamStartPositionUs, /* bufferTimestampAdjustmentUs= */ offsetToCompositionTimeUs);
videoSink.onInputStreamChanged( videoSink.onInputStreamChanged(
VideoSink.INPUT_TYPE_BITMAP, VideoSink.INPUT_TYPE_BITMAP,
new Format.Builder() new Format.Builder()