mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Various refactorings in VideoFrameRenderControl
- Rename a few methods/variable to improve readability. - Refactor how video size changes are tracked. This will simplify the upcoming logic to refactor the timestamp logic in VideoFrameRenderControl because we will use the same logic for outputVideoSize and for outputStreamStartPositionUs. PiperOrigin-RevId: 696026515
This commit is contained in:
parent
838c621d00
commit
64e92cb8e1
4 changed files with 74 additions and 78 deletions
|
|
@ -151,7 +151,7 @@ import java.util.concurrent.Executor;
|
||||||
@Override
|
@Override
|
||||||
public void onInputStreamChanged(@InputType int inputType, Format format) {
|
public void onInputStreamChanged(@InputType int inputType, Format format) {
|
||||||
if (format.width != inputFormat.width || format.height != inputFormat.height) {
|
if (format.width != inputFormat.width || format.height != inputFormat.height) {
|
||||||
videoFrameRenderControl.onOutputSizeChanged(format.width, format.height);
|
videoFrameRenderControl.onVideoSizeChanged(format.width, format.height);
|
||||||
}
|
}
|
||||||
if (format.frameRate != inputFormat.frameRate) {
|
if (format.frameRate != inputFormat.frameRate) {
|
||||||
videoFrameReleaseControl.setFrameRate(format.frameRate);
|
videoFrameReleaseControl.setFrameRate(format.frameRate);
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
||||||
}
|
}
|
||||||
// The frame presentation time is relative to the start of the Composition and without the
|
// The frame presentation time is relative to the start of the Composition and without the
|
||||||
// renderer offset
|
// renderer offset
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(
|
videoFrameRenderControl.onFrameAvailableForRendering(
|
||||||
framePresentationTimeUs - bufferTimestampAdjustmentUs);
|
framePresentationTimeUs - bufferTimestampAdjustmentUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,7 +471,7 @@ public final class PlaybackVideoGraphWrapper implements VideoSinkProvider, Video
|
||||||
private void onStreamTimestampInfoChange(
|
private void onStreamTimestampInfoChange(
|
||||||
long bufferTimestampAdjustmentUs, long bufferPresentationTimeUs, long streamStartPositionUs) {
|
long bufferTimestampAdjustmentUs, long bufferPresentationTimeUs, long streamStartPositionUs) {
|
||||||
this.bufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs;
|
this.bufferTimestampAdjustmentUs = bufferTimestampAdjustmentUs;
|
||||||
videoFrameRenderControl.onStreamStartPositionChange(
|
videoFrameRenderControl.onStreamStartPositionChanged(
|
||||||
bufferPresentationTimeUs, streamStartPositionUs);
|
bufferPresentationTimeUs, streamStartPositionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,23 +40,21 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
void onVideoSizeChanged(VideoSize videoSize);
|
void onVideoSizeChanged(VideoSize videoSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to release the {@linkplain
|
* Called to release the {@linkplain VideoFrameRenderControl#onFrameAvailableForRendering(long)
|
||||||
* VideoFrameRenderControl#onOutputFrameAvailableForRendering(long)} oldest frame that is
|
* oldest frame that is available for rendering}.
|
||||||
* available for rendering}.
|
|
||||||
*
|
*
|
||||||
* @param renderTimeNs The specific time, in nano seconds, that this frame should be rendered or
|
* @param renderTimeNs The specific time, in nano seconds, that this frame should be rendered or
|
||||||
* {@link VideoFrameProcessor#RENDER_OUTPUT_FRAME_IMMEDIATELY} if the frame needs to be
|
* {@link VideoFrameProcessor#RENDER_OUTPUT_FRAME_IMMEDIATELY} if the frame needs to be
|
||||||
* rendered immediately.
|
* rendered immediately.
|
||||||
* @param presentationTimeUs The frame's presentation time, in microseconds, which was announced
|
* @param presentationTimeUs The frame's presentation time, in microseconds, which was announced
|
||||||
* with {@link VideoFrameRenderControl#onOutputFrameAvailableForRendering(long)}.
|
* with {@link VideoFrameRenderControl#onFrameAvailableForRendering(long)}.
|
||||||
* @param isFirstFrame Whether this is the first frame of the stream.
|
* @param isFirstFrame Whether this is the first frame of the stream.
|
||||||
*/
|
*/
|
||||||
void renderFrame(long renderTimeNs, long presentationTimeUs, boolean isFirstFrame);
|
void renderFrame(long renderTimeNs, long presentationTimeUs, boolean isFirstFrame);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to drop the {@linkplain
|
* Called to drop the {@linkplain VideoFrameRenderControl#onFrameAvailableForRendering(long)
|
||||||
* VideoFrameRenderControl#onOutputFrameAvailableForRendering(long)} oldest frame that is
|
* oldest frame that is available for rendering}.
|
||||||
* available for rendering}.
|
|
||||||
*/
|
*/
|
||||||
void dropFrame();
|
void dropFrame();
|
||||||
}
|
}
|
||||||
|
|
@ -64,20 +62,20 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
private final FrameRenderer frameRenderer;
|
private final FrameRenderer frameRenderer;
|
||||||
private final VideoFrameReleaseControl videoFrameReleaseControl;
|
private final VideoFrameReleaseControl videoFrameReleaseControl;
|
||||||
private final VideoFrameReleaseControl.FrameReleaseInfo videoFrameReleaseInfo;
|
private final VideoFrameReleaseControl.FrameReleaseInfo videoFrameReleaseInfo;
|
||||||
private final TimedValueQueue<VideoSize> videoSizeChanges;
|
|
||||||
|
/**
|
||||||
|
* A queue of unprocessed input frame sizes. Each size is associated with the timestamp from which
|
||||||
|
* it should be applied.
|
||||||
|
*/
|
||||||
|
private final TimedValueQueue<VideoSize> videoSizes;
|
||||||
|
|
||||||
private final TimedValueQueue<Long> streamStartPositionsUs;
|
private final TimedValueQueue<Long> streamStartPositionsUs;
|
||||||
private final LongArrayQueue presentationTimestampsUs;
|
private final LongArrayQueue presentationTimestampsUs;
|
||||||
|
|
||||||
/**
|
private long lastInputPresentationTimeUs;
|
||||||
* Stores a video size that is announced with {@link #onOutputSizeChanged(int, int)} until an
|
private long lastOutputPresentationTimeUs;
|
||||||
* output frame is made available. Once the next frame arrives, we associate the frame's timestamp
|
private VideoSize outputVideoSize;
|
||||||
* with the video size change in {@link #videoSizeChanges} and clear this field.
|
|
||||||
*/
|
|
||||||
@Nullable private VideoSize pendingOutputVideoSize;
|
|
||||||
|
|
||||||
private VideoSize reportedVideoSize;
|
|
||||||
private long outputStreamStartPositionUs;
|
private long outputStreamStartPositionUs;
|
||||||
private long lastPresentationTimeUs;
|
|
||||||
|
|
||||||
/** Creates an instance. */
|
/** Creates an instance. */
|
||||||
public VideoFrameRenderControl(
|
public VideoFrameRenderControl(
|
||||||
|
|
@ -85,36 +83,35 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
this.frameRenderer = frameRenderer;
|
this.frameRenderer = frameRenderer;
|
||||||
this.videoFrameReleaseControl = videoFrameReleaseControl;
|
this.videoFrameReleaseControl = videoFrameReleaseControl;
|
||||||
videoFrameReleaseInfo = new VideoFrameReleaseControl.FrameReleaseInfo();
|
videoFrameReleaseInfo = new VideoFrameReleaseControl.FrameReleaseInfo();
|
||||||
videoSizeChanges = new TimedValueQueue<>();
|
videoSizes = new TimedValueQueue<>();
|
||||||
streamStartPositionsUs = new TimedValueQueue<>();
|
streamStartPositionsUs = new TimedValueQueue<>();
|
||||||
presentationTimestampsUs = new LongArrayQueue();
|
presentationTimestampsUs = new LongArrayQueue();
|
||||||
reportedVideoSize = VideoSize.UNKNOWN;
|
lastInputPresentationTimeUs = C.TIME_UNSET;
|
||||||
lastPresentationTimeUs = C.TIME_UNSET;
|
outputVideoSize = VideoSize.UNKNOWN;
|
||||||
|
lastOutputPresentationTimeUs = C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Flushes the renderer. */
|
/** Flushes the renderer. */
|
||||||
public void flush() {
|
public void flush() {
|
||||||
presentationTimestampsUs.clear();
|
presentationTimestampsUs.clear();
|
||||||
lastPresentationTimeUs = C.TIME_UNSET;
|
lastInputPresentationTimeUs = C.TIME_UNSET;
|
||||||
|
lastOutputPresentationTimeUs = C.TIME_UNSET;
|
||||||
if (streamStartPositionsUs.size() > 0) {
|
if (streamStartPositionsUs.size() > 0) {
|
||||||
// There is a pending streaming start position change. If seeking within the same stream, keep
|
// There is a pending streaming start position change. If seeking within the same stream, keep
|
||||||
// the pending start position with timestamp zero ensures the start position is applied on the
|
// the pending start position with min timestamp to ensure the start position is applied on
|
||||||
// frames after flushing. Otherwise if seeking to another stream, a new start position will be
|
// the frames after flushing. Otherwise if seeking to another stream, a new start position
|
||||||
// set before a new frame arrives so we'll be able to apply the new start position.
|
// will be set before a new frame arrives so we'll be able to apply the new start position.
|
||||||
long lastStartPositionUs = getLastAndClear(streamStartPositionsUs);
|
long lastStartPositionUs = getLastAndClear(streamStartPositionsUs);
|
||||||
|
// 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
|
||||||
|
// the only position in the queue.
|
||||||
streamStartPositionsUs.add(/* timestamp= */ 0, lastStartPositionUs);
|
streamStartPositionsUs.add(/* timestamp= */ 0, lastStartPositionUs);
|
||||||
}
|
}
|
||||||
if (pendingOutputVideoSize == null) {
|
if (videoSizes.size() > 0) {
|
||||||
if (videoSizeChanges.size() > 0) {
|
|
||||||
// Do not clear the last pending video size, we still want to report the size change after a
|
// Do not clear the last pending video size, we still want to report the size change after a
|
||||||
// flush. If after the flush, a new video size is announced, it will overwrite
|
// flush. If after the flush, a new video size is announced, it will be used instead.
|
||||||
// pendingOutputVideoSize. When the next frame is available for rendering, we will announce
|
VideoSize lastVideoSize = getLastAndClear(videoSizes);
|
||||||
// pendingOutputVideoSize.
|
videoSizes.add(/* timestamp= */ 0, lastVideoSize);
|
||||||
pendingOutputVideoSize = getLastAndClear(videoSizeChanges);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we keep the latest value of pendingOutputVideoSize
|
|
||||||
videoSizeChanges.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,7 +123,8 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
* {@code presentationTimeUs}.
|
* {@code presentationTimeUs}.
|
||||||
*/
|
*/
|
||||||
public boolean hasReleasedFrame(long presentationTimeUs) {
|
public boolean hasReleasedFrame(long presentationTimeUs) {
|
||||||
return lastPresentationTimeUs != C.TIME_UNSET && lastPresentationTimeUs >= presentationTimeUs;
|
return lastOutputPresentationTimeUs != C.TIME_UNSET
|
||||||
|
&& lastOutputPresentationTimeUs >= presentationTimeUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -160,12 +158,12 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
case VideoFrameReleaseControl.FRAME_RELEASE_IGNORE:
|
case VideoFrameReleaseControl.FRAME_RELEASE_IGNORE:
|
||||||
// TODO b/293873191 - Handle very late buffers and drop to key frame. Need to flush
|
// TODO b/293873191 - Handle very late buffers and drop to key frame. Need to flush
|
||||||
// VideoGraph input frames in this case.
|
// VideoGraph input frames in this case.
|
||||||
lastPresentationTimeUs = presentationTimeUs;
|
lastOutputPresentationTimeUs = presentationTimeUs;
|
||||||
dropFrame();
|
dropFrame();
|
||||||
break;
|
break;
|
||||||
case VideoFrameReleaseControl.FRAME_RELEASE_IMMEDIATELY:
|
case VideoFrameReleaseControl.FRAME_RELEASE_IMMEDIATELY:
|
||||||
case VideoFrameReleaseControl.FRAME_RELEASE_SCHEDULED:
|
case VideoFrameReleaseControl.FRAME_RELEASE_SCHEDULED:
|
||||||
lastPresentationTimeUs = presentationTimeUs;
|
lastOutputPresentationTimeUs = presentationTimeUs;
|
||||||
renderFrame(
|
renderFrame(
|
||||||
/* shouldRenderImmediately= */ frameReleaseAction
|
/* shouldRenderImmediately= */ frameReleaseAction
|
||||||
== VideoFrameReleaseControl.FRAME_RELEASE_IMMEDIATELY);
|
== VideoFrameReleaseControl.FRAME_RELEASE_IMMEDIATELY);
|
||||||
|
|
@ -177,8 +175,10 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called when the size of the available frames has changed. */
|
/** Called when the size of the available frames has changed. */
|
||||||
public void onOutputSizeChanged(int width, int height) {
|
public void onVideoSizeChanged(int width, int height) {
|
||||||
pendingOutputVideoSize = new VideoSize(width, height);
|
videoSizes.add(
|
||||||
|
lastInputPresentationTimeUs == C.TIME_UNSET ? 0 : lastInputPresentationTimeUs + 1,
|
||||||
|
new VideoSize(width, height));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -186,16 +186,13 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
*
|
*
|
||||||
* @param presentationTimeUs The frame's presentation timestamp, in microseconds.
|
* @param presentationTimeUs The frame's presentation timestamp, in microseconds.
|
||||||
*/
|
*/
|
||||||
public void onOutputFrameAvailableForRendering(long presentationTimeUs) {
|
public void onFrameAvailableForRendering(long presentationTimeUs) {
|
||||||
if (pendingOutputVideoSize != null) {
|
|
||||||
videoSizeChanges.add(presentationTimeUs, pendingOutputVideoSize);
|
|
||||||
pendingOutputVideoSize = null;
|
|
||||||
}
|
|
||||||
presentationTimestampsUs.add(presentationTimeUs);
|
presentationTimestampsUs.add(presentationTimeUs);
|
||||||
|
lastInputPresentationTimeUs = presentationTimeUs;
|
||||||
// TODO b/257464707 - Support extensively modified media.
|
// TODO b/257464707 - Support extensively modified media.
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onStreamStartPositionChange(long presentationTimeUs, long streamStartPositionUs) {
|
public void onStreamStartPositionChanged(long presentationTimeUs, long streamStartPositionUs) {
|
||||||
streamStartPositionsUs.add(presentationTimeUs, streamStartPositionUs);
|
streamStartPositionsUs.add(presentationTimeUs, streamStartPositionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -207,9 +204,9 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
private void renderFrame(boolean shouldRenderImmediately) {
|
private void renderFrame(boolean shouldRenderImmediately) {
|
||||||
long presentationTimeUs = checkStateNotNull(presentationTimestampsUs.remove());
|
long presentationTimeUs = checkStateNotNull(presentationTimestampsUs.remove());
|
||||||
|
|
||||||
boolean videoSizeUpdated = maybeUpdateVideoSize(presentationTimeUs);
|
boolean videoSizeUpdated = maybeUpdateOutputVideoSize(presentationTimeUs);
|
||||||
if (videoSizeUpdated) {
|
if (videoSizeUpdated) {
|
||||||
frameRenderer.onVideoSizeChanged(reportedVideoSize);
|
frameRenderer.onVideoSizeChanged(outputVideoSize);
|
||||||
}
|
}
|
||||||
long renderTimeNs =
|
long renderTimeNs =
|
||||||
shouldRenderImmediately
|
shouldRenderImmediately
|
||||||
|
|
@ -230,13 +227,12 @@ import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean maybeUpdateVideoSize(long presentationTimeUs) {
|
private boolean maybeUpdateOutputVideoSize(long presentationTimeUs) {
|
||||||
@Nullable VideoSize videoSize = videoSizeChanges.pollFloor(presentationTimeUs);
|
@Nullable VideoSize newOutputVideoSize = videoSizes.pollFloor(presentationTimeUs);
|
||||||
if (videoSize == null) {
|
if (newOutputVideoSize != null
|
||||||
return false;
|
&& !newOutputVideoSize.equals(VideoSize.UNKNOWN)
|
||||||
}
|
&& !newOutputVideoSize.equals(outputVideoSize)) {
|
||||||
if (!videoSize.equals(VideoSize.UNKNOWN) && !videoSize.equals(reportedVideoSize)) {
|
outputVideoSize = newOutputVideoSize;
|
||||||
reportedVideoSize = videoSize;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,9 @@ public class VideoFrameRenderControlTest {
|
||||||
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
||||||
|
|
||||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||||
videoFrameRenderControl.onOutputSizeChanged(
|
videoFrameRenderControl.onVideoSizeChanged(
|
||||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
||||||
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
||||||
|
|
||||||
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
||||||
|
|
@ -74,10 +74,10 @@ public class VideoFrameRenderControlTest {
|
||||||
|
|
||||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||||
videoFrameReleaseControl.onStarted();
|
videoFrameReleaseControl.onStarted();
|
||||||
videoFrameRenderControl.onOutputSizeChanged(
|
videoFrameRenderControl.onVideoSizeChanged(
|
||||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 10_000);
|
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 10_000);
|
||||||
|
|
||||||
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
||||||
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
||||||
|
|
@ -119,11 +119,11 @@ public class VideoFrameRenderControlTest {
|
||||||
|
|
||||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||||
videoFrameReleaseControl.onStarted();
|
videoFrameReleaseControl.onStarted();
|
||||||
videoFrameRenderControl.onOutputSizeChanged(
|
videoFrameRenderControl.onVideoSizeChanged(
|
||||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||||
videoFrameRenderControl.onStreamStartPositionChange(
|
videoFrameRenderControl.onStreamStartPositionChanged(
|
||||||
/* presentationTimeUs= */ 0, /* streamStartPositionUs= */ 10_000);
|
/* presentationTimeUs= */ 0, /* streamStartPositionUs= */ 10_000);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
||||||
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
||||||
|
|
||||||
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
||||||
|
|
@ -136,9 +136,9 @@ public class VideoFrameRenderControlTest {
|
||||||
|
|
||||||
// 10 milliseconds pass
|
// 10 milliseconds pass
|
||||||
clock.advanceTime(/* timeDiffMs= */ 10);
|
clock.advanceTime(/* timeDiffMs= */ 10);
|
||||||
videoFrameRenderControl.onStreamStartPositionChange(
|
videoFrameRenderControl.onStreamStartPositionChanged(
|
||||||
/* presentationTimeUs= */ 10_000, /* streamStartPositionUs= */ 20_000);
|
/* presentationTimeUs= */ 10_000, /* streamStartPositionUs= */ 20_000);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 10_000);
|
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 10_000);
|
||||||
videoFrameRenderControl.render(/* positionUs= */ 10_000, /* elapsedRealtimeUs= */ 0);
|
videoFrameRenderControl.render(/* positionUs= */ 10_000, /* elapsedRealtimeUs= */ 0);
|
||||||
|
|
||||||
// Second frame has the second stream start position and it is also a first frame.
|
// Second frame has the second stream start position and it is also a first frame.
|
||||||
|
|
@ -168,10 +168,10 @@ public class VideoFrameRenderControlTest {
|
||||||
|
|
||||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||||
videoFrameReleaseControl.onStarted();
|
videoFrameReleaseControl.onStarted();
|
||||||
videoFrameRenderControl.onOutputSizeChanged(
|
videoFrameRenderControl.onVideoSizeChanged(
|
||||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 10_000);
|
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 10_000);
|
||||||
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
||||||
|
|
||||||
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
||||||
|
|
@ -206,16 +206,16 @@ public class VideoFrameRenderControlTest {
|
||||||
|
|
||||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||||
videoFrameReleaseControl.onStarted();
|
videoFrameReleaseControl.onStarted();
|
||||||
videoFrameRenderControl.onOutputSizeChanged(
|
videoFrameRenderControl.onVideoSizeChanged(
|
||||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
||||||
videoFrameRenderControl.flush();
|
videoFrameRenderControl.flush();
|
||||||
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
||||||
|
|
||||||
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
||||||
inOrder.verifyNoMoreInteractions();
|
inOrder.verifyNoMoreInteractions();
|
||||||
|
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 10_000);
|
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 10_000);
|
||||||
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
||||||
|
|
||||||
// First frame was rendered with pending video size change.
|
// First frame was rendered with pending video size change.
|
||||||
|
|
@ -250,9 +250,9 @@ public class VideoFrameRenderControlTest {
|
||||||
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
||||||
|
|
||||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||||
videoFrameRenderControl.onOutputSizeChanged(
|
videoFrameRenderControl.onVideoSizeChanged(
|
||||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
||||||
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
||||||
|
|
||||||
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
||||||
|
|
@ -277,9 +277,9 @@ public class VideoFrameRenderControlTest {
|
||||||
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
new VideoFrameRenderControl(frameRenderer, videoFrameReleaseControl);
|
||||||
|
|
||||||
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
videoFrameReleaseControl.onEnabled(/* releaseFirstFrameBeforeStarted= */ true);
|
||||||
videoFrameRenderControl.onOutputSizeChanged(
|
videoFrameRenderControl.onVideoSizeChanged(
|
||||||
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
/* width= */ VIDEO_WIDTH, /* height= */ VIDEO_HEIGHT);
|
||||||
videoFrameRenderControl.onOutputFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
videoFrameRenderControl.onFrameAvailableForRendering(/* presentationTimeUs= */ 0);
|
||||||
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
videoFrameRenderControl.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0);
|
||||||
|
|
||||||
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
InOrder inOrder = Mockito.inOrder(frameRenderer);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue