mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Fix offset passed to VideoFrameReleaseControl
In some cases, the streamOffsetUs was passed to VideoFrameReleaseControl.getFrameReleaseAction() but it should be the streamStartPositionUs. PiperOrigin-RevId: 691040172
This commit is contained in:
parent
7f94aaf49f
commit
14094b5094
8 changed files with 51 additions and 74 deletions
|
|
@ -124,10 +124,7 @@ import java.util.concurrent.Executor;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamTimestampInfo(
|
public void setStreamTimestampInfo(
|
||||||
long streamStartPositionUs,
|
long streamStartPositionUs, long bufferTimestampAdjustmentUs, long lastResetPositionUs) {
|
||||||
long streamOffsetUs,
|
|
||||||
long bufferTimestampAdjustmentUs,
|
|
||||||
long lastResetPositionUs) {
|
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -806,7 +806,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
||||||
videoSink.flush(/* resetPosition= */ true);
|
videoSink.flush(/* resetPosition= */ true);
|
||||||
videoSink.setStreamTimestampInfo(
|
videoSink.setStreamTimestampInfo(
|
||||||
getOutputStreamStartPositionUs(),
|
getOutputStreamStartPositionUs(),
|
||||||
getOutputStreamOffsetUs(),
|
|
||||||
getBufferTimestampAdjustmentUs(),
|
getBufferTimestampAdjustmentUs(),
|
||||||
getLastResetPositionUs());
|
getLastResetPositionUs());
|
||||||
pendingVideoSinkInputStreamChange = true;
|
pendingVideoSinkInputStreamChange = true;
|
||||||
|
|
@ -1608,7 +1607,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
|
||||||
if (videoSink != null) {
|
if (videoSink != null) {
|
||||||
videoSink.setStreamTimestampInfo(
|
videoSink.setStreamTimestampInfo(
|
||||||
getOutputStreamStartPositionUs(),
|
getOutputStreamStartPositionUs(),
|
||||||
getOutputStreamOffsetUs(),
|
|
||||||
getBufferTimestampAdjustmentUs(),
|
getBufferTimestampAdjustmentUs(),
|
||||||
getLastResetPositionUs());
|
getLastResetPositionUs());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -468,10 +468,11 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
||||||
defaultVideoSink.setPlaybackSpeed(speed);
|
defaultVideoSink.setPlaybackSpeed(speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onStreamOffsetChange(
|
private void onStreamTimestampInfoChange(
|
||||||
long bufferTimestampAdjustmentUs, long bufferPresentationTimeUs, long streamOffsetUs) {
|
long bufferTimestampAdjustmentUs, long bufferPresentationTimeUs, long streamStartPositionUs) {
|
||||||
this.bufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs;
|
this.bufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs;
|
||||||
videoFrameRenderControl.onStreamOffsetChange(bufferPresentationTimeUs, streamOffsetUs);
|
videoFrameRenderControl.onStreamStartPositionChange(
|
||||||
|
bufferPresentationTimeUs, streamStartPositionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ColorInfo getAdjustedInputColorInfo(@Nullable ColorInfo inputColorInfo) {
|
private static ColorInfo getAdjustedInputColorInfo(@Nullable ColorInfo inputColorInfo) {
|
||||||
|
|
@ -493,10 +494,9 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
||||||
@Nullable private Format inputFormat;
|
@Nullable private Format inputFormat;
|
||||||
private @InputType int inputType;
|
private @InputType int inputType;
|
||||||
private long inputStreamStartPositionUs;
|
private long inputStreamStartPositionUs;
|
||||||
private long inputStreamOffsetUs;
|
|
||||||
private long inputBufferTimestampAdjustmentUs;
|
private long inputBufferTimestampAdjustmentUs;
|
||||||
private long lastResetPositionUs;
|
private long lastResetPositionUs;
|
||||||
private boolean pendingInputStreamOffsetChange;
|
private boolean pendingInputStreamTimestampInfoChange;
|
||||||
|
|
||||||
/** The buffer presentation time, in microseconds, of the final frame in the stream. */
|
/** The buffer presentation time, in microseconds, of the final frame in the stream. */
|
||||||
private long finalBufferPresentationTimeUs;
|
private long finalBufferPresentationTimeUs;
|
||||||
|
|
@ -575,8 +575,8 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
||||||
lastBufferPresentationTimeUs = C.TIME_UNSET;
|
lastBufferPresentationTimeUs = C.TIME_UNSET;
|
||||||
PlaybackVideoGraphWrapper.this.flush(resetPosition);
|
PlaybackVideoGraphWrapper.this.flush(resetPosition);
|
||||||
pendingInputStreamBufferPresentationTimeUs = C.TIME_UNSET;
|
pendingInputStreamBufferPresentationTimeUs = C.TIME_UNSET;
|
||||||
// Don't change input stream offset or reset the pending input stream offset change so that
|
// Don't change input stream start position or reset the pending input stream timestamp info
|
||||||
// it's announced with the next input frame.
|
// change so that it's announced with the next input frame.
|
||||||
// Don't reset isInputStreamChangePending because it's not guaranteed to receive a new input
|
// Don't reset isInputStreamChangePending because it's not guaranteed to receive a new input
|
||||||
// stream after seeking.
|
// stream after seeking.
|
||||||
}
|
}
|
||||||
|
|
@ -658,16 +658,12 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamTimestampInfo(
|
public void setStreamTimestampInfo(
|
||||||
long streamStartPositionUs,
|
long streamStartPositionUs, long bufferTimestampAdjustmentUs, long lastResetPositionUs) {
|
||||||
long streamOffsetUs,
|
// Ors because this method could be called multiple times on a timestamp info change.
|
||||||
long bufferTimestampAdjustmentUs,
|
pendingInputStreamTimestampInfoChange |=
|
||||||
long lastResetPositionUs) {
|
inputStreamStartPositionUs != streamStartPositionUs
|
||||||
// Ors because this method could be called multiple times on a stream offset change.
|
|
||||||
pendingInputStreamOffsetChange |=
|
|
||||||
inputStreamOffsetUs != streamOffsetUs
|
|
||||||
|| inputBufferTimestampAdjustmentUs != bufferTimestampAdjustmentUs;
|
|| inputBufferTimestampAdjustmentUs != bufferTimestampAdjustmentUs;
|
||||||
inputStreamStartPositionUs = streamStartPositionUs;
|
inputStreamStartPositionUs = streamStartPositionUs;
|
||||||
inputStreamOffsetUs = streamOffsetUs;
|
|
||||||
inputBufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs;
|
inputBufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs;
|
||||||
this.lastResetPositionUs = lastResetPositionUs;
|
this.lastResetPositionUs = lastResetPositionUs;
|
||||||
}
|
}
|
||||||
|
|
@ -765,7 +761,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
maybeSetStreamOffsetChange(bufferPresentationTimeUs);
|
maybeSetStreamTimestampInfo(bufferPresentationTimeUs);
|
||||||
lastBufferPresentationTimeUs = bufferPresentationTimeUs;
|
lastBufferPresentationTimeUs = bufferPresentationTimeUs;
|
||||||
if (isLastFrame) {
|
if (isLastFrame) {
|
||||||
finalBufferPresentationTimeUs = bufferPresentationTimeUs;
|
finalBufferPresentationTimeUs = bufferPresentationTimeUs;
|
||||||
|
|
@ -798,7 +794,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
||||||
long lastBufferPresentationTimeUs =
|
long lastBufferPresentationTimeUs =
|
||||||
copyTimestampIterator.getLastTimestampUs() - inputBufferTimestampAdjustmentUs;
|
copyTimestampIterator.getLastTimestampUs() - inputBufferTimestampAdjustmentUs;
|
||||||
checkState(lastBufferPresentationTimeUs != C.TIME_UNSET);
|
checkState(lastBufferPresentationTimeUs != C.TIME_UNSET);
|
||||||
maybeSetStreamOffsetChange(bufferPresentationTimeUs);
|
maybeSetStreamTimestampInfo(bufferPresentationTimeUs);
|
||||||
this.lastBufferPresentationTimeUs = lastBufferPresentationTimeUs;
|
this.lastBufferPresentationTimeUs = lastBufferPresentationTimeUs;
|
||||||
finalBufferPresentationTimeUs = lastBufferPresentationTimeUs;
|
finalBufferPresentationTimeUs = lastBufferPresentationTimeUs;
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -821,13 +817,11 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
||||||
|
|
||||||
// Other methods
|
// Other methods
|
||||||
|
|
||||||
private void maybeSetStreamOffsetChange(long bufferPresentationTimeUs) {
|
private void maybeSetStreamTimestampInfo(long bufferPresentationTimeUs) {
|
||||||
if (pendingInputStreamOffsetChange) {
|
if (pendingInputStreamTimestampInfoChange) {
|
||||||
PlaybackVideoGraphWrapper.this.onStreamOffsetChange(
|
PlaybackVideoGraphWrapper.this.onStreamTimestampInfoChange(
|
||||||
inputBufferTimestampAdjustmentUs,
|
inputBufferTimestampAdjustmentUs, bufferPresentationTimeUs, inputStreamStartPositionUs);
|
||||||
bufferPresentationTimeUs,
|
pendingInputStreamTimestampInfoChange = false;
|
||||||
/* streamOffsetUs= */ inputStreamOffsetUs);
|
|
||||||
pendingInputStreamOffsetChange = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
private final VideoFrameReleaseControl videoFrameReleaseControl;
|
private final VideoFrameReleaseControl videoFrameReleaseControl;
|
||||||
private final VideoFrameReleaseControl.FrameReleaseInfo videoFrameReleaseInfo;
|
private final VideoFrameReleaseControl.FrameReleaseInfo videoFrameReleaseInfo;
|
||||||
private final TimedValueQueue<VideoSize> videoSizeChanges;
|
private final TimedValueQueue<VideoSize> videoSizeChanges;
|
||||||
private final TimedValueQueue<Long> streamOffsets;
|
private final TimedValueQueue<Long> streamStartPositionsUs;
|
||||||
private final LongArrayQueue presentationTimestampsUs;
|
private final LongArrayQueue presentationTimestampsUs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -76,7 +76,7 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
@Nullable private VideoSize pendingOutputVideoSize;
|
@Nullable private VideoSize pendingOutputVideoSize;
|
||||||
|
|
||||||
private VideoSize reportedVideoSize;
|
private VideoSize reportedVideoSize;
|
||||||
private long outputStreamOffsetUs;
|
private long outputStreamStartPositionUs;
|
||||||
private long lastPresentationTimeUs;
|
private long lastPresentationTimeUs;
|
||||||
|
|
||||||
/** Creates an instance. */
|
/** Creates an instance. */
|
||||||
|
|
@ -86,7 +86,7 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
this.videoFrameReleaseControl = videoFrameReleaseControl;
|
this.videoFrameReleaseControl = videoFrameReleaseControl;
|
||||||
videoFrameReleaseInfo = new VideoFrameReleaseControl.FrameReleaseInfo();
|
videoFrameReleaseInfo = new VideoFrameReleaseControl.FrameReleaseInfo();
|
||||||
videoSizeChanges = new TimedValueQueue<>();
|
videoSizeChanges = new TimedValueQueue<>();
|
||||||
streamOffsets = new TimedValueQueue<>();
|
streamStartPositionsUs = new TimedValueQueue<>();
|
||||||
presentationTimestampsUs = new LongArrayQueue();
|
presentationTimestampsUs = new LongArrayQueue();
|
||||||
reportedVideoSize = VideoSize.UNKNOWN;
|
reportedVideoSize = VideoSize.UNKNOWN;
|
||||||
lastPresentationTimeUs = C.TIME_UNSET;
|
lastPresentationTimeUs = C.TIME_UNSET;
|
||||||
|
|
@ -96,13 +96,13 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
public void flush() {
|
public void flush() {
|
||||||
presentationTimestampsUs.clear();
|
presentationTimestampsUs.clear();
|
||||||
lastPresentationTimeUs = C.TIME_UNSET;
|
lastPresentationTimeUs = C.TIME_UNSET;
|
||||||
if (streamOffsets.size() > 0) {
|
if (streamStartPositionsUs.size() > 0) {
|
||||||
// There is a pending streaming offset change. If seeking within the same stream, keep the
|
// There is a pending streaming start position change. If seeking within the same stream, keep
|
||||||
// pending offset with timestamp zero ensures the offset is applied on the frames after
|
// the pending start position with timestamp zero ensures the start position is applied on the
|
||||||
// flushing. Otherwise if seeking to another stream, a new offset will be set before a new
|
// frames after flushing. Otherwise if seeking to another stream, a new start position will be
|
||||||
// frame arrives so we'll be able to apply the new offset.
|
// set before a new frame arrives so we'll be able to apply the new start position.
|
||||||
long lastStreamOffset = getLastAndClear(streamOffsets);
|
long lastStartPositionUs = getLastAndClear(streamStartPositionsUs);
|
||||||
streamOffsets.add(/* timestamp= */ 0, lastStreamOffset);
|
streamStartPositionsUs.add(/* timestamp= */ 0, lastStartPositionUs);
|
||||||
}
|
}
|
||||||
if (pendingOutputVideoSize == null) {
|
if (pendingOutputVideoSize == null) {
|
||||||
if (videoSizeChanges.size() > 0) {
|
if (videoSizeChanges.size() > 0) {
|
||||||
|
|
@ -139,8 +139,8 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
|
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
|
||||||
while (!presentationTimestampsUs.isEmpty()) {
|
while (!presentationTimestampsUs.isEmpty()) {
|
||||||
long presentationTimeUs = presentationTimestampsUs.element();
|
long presentationTimeUs = presentationTimestampsUs.element();
|
||||||
// Check whether this buffer comes with a new stream offset.
|
// Check whether this buffer comes with a new stream start position.
|
||||||
if (maybeUpdateOutputStreamOffset(presentationTimeUs)) {
|
if (maybeUpdateOutputStreamStartPosition(presentationTimeUs)) {
|
||||||
videoFrameReleaseControl.onProcessedStreamChange();
|
videoFrameReleaseControl.onProcessedStreamChange();
|
||||||
}
|
}
|
||||||
@VideoFrameReleaseControl.FrameReleaseAction
|
@VideoFrameReleaseControl.FrameReleaseAction
|
||||||
|
|
@ -149,7 +149,7 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
presentationTimeUs,
|
presentationTimeUs,
|
||||||
positionUs,
|
positionUs,
|
||||||
elapsedRealtimeUs,
|
elapsedRealtimeUs,
|
||||||
outputStreamOffsetUs,
|
outputStreamStartPositionUs,
|
||||||
/* isLastFrame= */ false,
|
/* isLastFrame= */ false,
|
||||||
videoFrameReleaseInfo);
|
videoFrameReleaseInfo);
|
||||||
switch (frameReleaseAction) {
|
switch (frameReleaseAction) {
|
||||||
|
|
@ -195,8 +195,8 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
// TODO b/257464707 - Support extensively modified media.
|
// TODO b/257464707 - Support extensively modified media.
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onStreamOffsetChange(long presentationTimeUs, long streamOffsetUs) {
|
public void onStreamStartPositionChange(long presentationTimeUs, long streamStartPositionUs) {
|
||||||
streamOffsets.add(presentationTimeUs, streamOffsetUs);
|
streamStartPositionsUs.add(presentationTimeUs, streamStartPositionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dropFrame() {
|
private void dropFrame() {
|
||||||
|
|
@ -219,10 +219,12 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
renderTimeNs, presentationTimeUs, videoFrameReleaseControl.onFrameReleasedIsFirstFrame());
|
renderTimeNs, presentationTimeUs, videoFrameReleaseControl.onFrameReleasedIsFirstFrame());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean maybeUpdateOutputStreamOffset(long presentationTimeUs) {
|
private boolean maybeUpdateOutputStreamStartPosition(long presentationTimeUs) {
|
||||||
@Nullable Long newOutputStreamOffsetUs = streamOffsets.pollFloor(presentationTimeUs);
|
@Nullable
|
||||||
if (newOutputStreamOffsetUs != null && newOutputStreamOffsetUs != outputStreamOffsetUs) {
|
Long newOutputStreamStartPositionUs = streamStartPositionsUs.pollFloor(presentationTimeUs);
|
||||||
outputStreamOffsetUs = newOutputStreamOffsetUs;
|
if (newOutputStreamStartPositionUs != null
|
||||||
|
&& newOutputStreamStartPositionUs != outputStreamStartPositionUs) {
|
||||||
|
outputStreamStartPositionUs = newOutputStreamStartPositionUs;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -207,17 +207,12 @@ public interface VideoSink {
|
||||||
*
|
*
|
||||||
* @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.
|
||||||
* @param streamOffsetUs The offset that is added to the buffer presentation timestamps by the
|
|
||||||
* player, in microseconds.
|
|
||||||
* @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.
|
||||||
* @param lastResetPositionUs The renderer last reset position, in microseconds.
|
* @param lastResetPositionUs The renderer last reset position, in microseconds.
|
||||||
*/
|
*/
|
||||||
void setStreamTimestampInfo(
|
void setStreamTimestampInfo(
|
||||||
long streamStartPositionUs,
|
long streamStartPositionUs, long bufferTimestampAdjustmentUs, long lastResetPositionUs);
|
||||||
long streamOffsetUs,
|
|
||||||
long bufferTimestampAdjustmentUs,
|
|
||||||
long lastResetPositionUs);
|
|
||||||
|
|
||||||
/** Sets the output surface info. */
|
/** Sets the output surface info. */
|
||||||
void setOutputSurfaceInfo(Surface outputSurface, Size outputResolution);
|
void setOutputSurfaceInfo(Surface outputSurface, Size outputResolution);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
import androidx.media3.common.VideoSize;
|
import androidx.media3.common.VideoSize;
|
||||||
import androidx.media3.exoplayer.ExoPlaybackException;
|
|
||||||
import androidx.media3.test.utils.FakeClock;
|
import androidx.media3.test.utils.FakeClock;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
@ -109,7 +108,7 @@ public class VideoFrameRenderControlTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void renderFrames_withStreamOffsetSetChange_firstFrameAgain() throws Exception {
|
public void renderFrames_withStreamStartPositionChange_firstFrameAgain() throws Exception {
|
||||||
VideoFrameRenderControl.FrameRenderer frameRenderer =
|
VideoFrameRenderControl.FrameRenderer frameRenderer =
|
||||||
mock(VideoFrameRenderControl.FrameRenderer.class);
|
mock(VideoFrameRenderControl.FrameRenderer.class);
|
||||||
FakeClock clock = new FakeClock(/* isAutoAdvancing= */ false);
|
FakeClock clock = new FakeClock(/* isAutoAdvancing= */ false);
|
||||||
|
|
@ -122,8 +121,8 @@ public class VideoFrameRenderControlTest {
|
||||||
videoFrameReleaseControl.onStarted();
|
videoFrameReleaseControl.onStarted();
|
||||||
videoFrameRenderControl.onOutputSizeChanged(
|
videoFrameRenderControl.onOutputSizeChanged(
|
||||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||||
videoFrameRenderControl.onStreamOffsetChange(
|
videoFrameRenderControl.onStreamStartPositionChange(
|
||||||
/* presentationTimeUs= */ 0, /* streamOffsetUs= */ 10_000);
|
/* presentationTimeUs= */ 0, /* streamStartPositionUs= */ 10_000);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
||||||
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
||||||
|
|
||||||
|
|
@ -131,18 +130,18 @@ public class VideoFrameRenderControlTest {
|
||||||
inOrder
|
inOrder
|
||||||
.verify(frameRenderer)
|
.verify(frameRenderer)
|
||||||
.onVideoSizeChanged(new VideoSize(/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT));
|
.onVideoSizeChanged(new VideoSize(/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT));
|
||||||
// First frame has the first stream offset.
|
// First frame has the first stream start position.
|
||||||
inOrder.verify(frameRenderer).renderFrame(anyLong(), eq(0L), eq(true));
|
inOrder.verify(frameRenderer).renderFrame(anyLong(), eq(0L), eq(true));
|
||||||
inOrder.verifyNoMoreInteractions();
|
inOrder.verifyNoMoreInteractions();
|
||||||
|
|
||||||
// 10 milliseconds pass
|
// 10 milliseconds pass
|
||||||
clock.advanceTime(/* timeDiffMs= */ 10);
|
clock.advanceTime(/* timeDiffMs= */ 10);
|
||||||
videoFrameRenderControl.onStreamOffsetChange(
|
videoFrameRenderControl.onStreamStartPositionChange(
|
||||||
/* presentationTimeUs= */ 10_000, /* streamOffsetUs= */ 20_000);
|
/* presentationTimeUs= */ 10_000, /* streamStartPositionUs= */ 20_000);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 10_000);
|
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 10_000);
|
||||||
videoFrameRenderControl.render(/* positionUs= */ 10_000, /* elapsedRealtimeUs= */ 0);
|
videoFrameRenderControl.render(/* positionUs= */ 10_000, /* elapsedRealtimeUs= */ 0);
|
||||||
|
|
||||||
// Second frame has the second stream offset and it is also a first frame.
|
// Second frame has the second stream start position and it is also a first frame.
|
||||||
inOrder
|
inOrder
|
||||||
.verify(frameRenderer)
|
.verify(frameRenderer)
|
||||||
.renderFrame(
|
.renderFrame(
|
||||||
|
|
@ -344,8 +343,7 @@ public class VideoFrameRenderControlTest {
|
||||||
long positionUs,
|
long positionUs,
|
||||||
long elapsedRealtimeUs,
|
long elapsedRealtimeUs,
|
||||||
boolean isLastFrame,
|
boolean isLastFrame,
|
||||||
boolean treatDroppedBuffersAsSkipped)
|
boolean treatDroppedBuffersAsSkipped) {
|
||||||
throws ExoPlaybackException {
|
|
||||||
return shouldIgnoreFrames;
|
return shouldIgnoreFrames;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -172,17 +172,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStreamTimestampInfo(
|
public void setStreamTimestampInfo(
|
||||||
long streamStartPositionUs,
|
long streamStartPositionUs, long bufferTimestampAdjustmentUs, long lastResetPositionUs) {
|
||||||
long streamOffsetUs,
|
|
||||||
long bufferTimestampAdjustmentUs,
|
|
||||||
long lastResetPositionUs) {
|
|
||||||
executeOrDelay(
|
executeOrDelay(
|
||||||
videoSink ->
|
videoSink ->
|
||||||
videoSink.setStreamTimestampInfo(
|
videoSink.setStreamTimestampInfo(
|
||||||
streamStartPositionUs,
|
streamStartPositionUs, bufferTimestampAdjustmentUs, lastResetPositionUs));
|
||||||
streamOffsetUs,
|
|
||||||
bufferTimestampAdjustmentUs,
|
|
||||||
lastResetPositionUs));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -460,7 +460,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
videoSink.setPendingVideoEffects(videoEffects);
|
videoSink.setPendingVideoEffects(videoEffects);
|
||||||
videoSink.setStreamTimestampInfo(
|
videoSink.setStreamTimestampInfo(
|
||||||
streamStartPositionUs,
|
streamStartPositionUs,
|
||||||
getStreamOffsetUs(),
|
|
||||||
/* bufferTimestampAdjustmentUs= */ offsetToCompositionTimeUs,
|
/* bufferTimestampAdjustmentUs= */ offsetToCompositionTimeUs,
|
||||||
getLastResetPositionUs());
|
getLastResetPositionUs());
|
||||||
videoSink.onInputStreamChanged(
|
videoSink.onInputStreamChanged(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue