Commit 0a68d1f0 by tonihei Committed by Oliver Woodman

Fix pending stream offset activation in video renderer.

Currently, pending stream offset changes are kept until an output buffer
timestamp surpasses the next pending stream offset. However, this is
problematic if the next stream offset overlaps with the current output
buffer sample times (e.g. because the next stream starts at a non-zero start
time).

To correctly time the switch to the next stream offset, this change keeps
the timestamp of the last queued input sample as switch point. And we only
switch to the new offset after an output sample timestamp reached this switch
point.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=192736637
parent 9a4e083b
...@@ -91,6 +91,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -91,6 +91,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
private final int maxDroppedFramesToNotify; private final int maxDroppedFramesToNotify;
private final boolean deviceNeedsAutoFrcWorkaround; private final boolean deviceNeedsAutoFrcWorkaround;
private final long[] pendingOutputStreamOffsetsUs; private final long[] pendingOutputStreamOffsetsUs;
private final long[] pendingOutputStreamSwitchTimesUs;
private CodecMaxValues codecMaxValues; private CodecMaxValues codecMaxValues;
private boolean codecNeedsSetOutputSurfaceWorkaround; private boolean codecNeedsSetOutputSurfaceWorkaround;
...@@ -123,6 +124,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -123,6 +124,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
private int tunnelingAudioSessionId; private int tunnelingAudioSessionId;
/* package */ OnFrameRenderedListenerV23 tunnelingOnFrameRenderedListener; /* package */ OnFrameRenderedListenerV23 tunnelingOnFrameRenderedListener;
private long lastInputTimeUs;
private long outputStreamOffsetUs; private long outputStreamOffsetUs;
private int pendingOutputStreamOffsetCount; private int pendingOutputStreamOffsetCount;
...@@ -194,7 +196,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -194,7 +196,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
eventDispatcher = new EventDispatcher(eventHandler, eventListener); eventDispatcher = new EventDispatcher(eventHandler, eventListener);
deviceNeedsAutoFrcWorkaround = deviceNeedsAutoFrcWorkaround(); deviceNeedsAutoFrcWorkaround = deviceNeedsAutoFrcWorkaround();
pendingOutputStreamOffsetsUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT]; pendingOutputStreamOffsetsUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT];
pendingOutputStreamSwitchTimesUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT];
outputStreamOffsetUs = C.TIME_UNSET; outputStreamOffsetUs = C.TIME_UNSET;
lastInputTimeUs = C.TIME_UNSET;
joiningDeadlineMs = C.TIME_UNSET; joiningDeadlineMs = C.TIME_UNSET;
currentWidth = Format.NO_VALUE; currentWidth = Format.NO_VALUE;
currentHeight = Format.NO_VALUE; currentHeight = Format.NO_VALUE;
...@@ -269,6 +273,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -269,6 +273,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
pendingOutputStreamOffsetCount++; pendingOutputStreamOffsetCount++;
} }
pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1] = offsetUs; pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1] = offsetUs;
pendingOutputStreamSwitchTimesUs[pendingOutputStreamOffsetCount - 1] = lastInputTimeUs;
} }
super.onStreamChanged(formats, offsetUs); super.onStreamChanged(formats, offsetUs);
} }
...@@ -279,6 +284,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -279,6 +284,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
clearRenderedFirstFrame(); clearRenderedFirstFrame();
initialPositionUs = C.TIME_UNSET; initialPositionUs = C.TIME_UNSET;
consecutiveDroppedFrameCount = 0; consecutiveDroppedFrameCount = 0;
lastInputTimeUs = C.TIME_UNSET;
if (pendingOutputStreamOffsetCount != 0) { if (pendingOutputStreamOffsetCount != 0) {
outputStreamOffsetUs = pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1]; outputStreamOffsetUs = pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1];
pendingOutputStreamOffsetCount = 0; pendingOutputStreamOffsetCount = 0;
...@@ -332,6 +338,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -332,6 +338,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
currentPixelWidthHeightRatio = Format.NO_VALUE; currentPixelWidthHeightRatio = Format.NO_VALUE;
pendingPixelWidthHeightRatio = Format.NO_VALUE; pendingPixelWidthHeightRatio = Format.NO_VALUE;
outputStreamOffsetUs = C.TIME_UNSET; outputStreamOffsetUs = C.TIME_UNSET;
lastInputTimeUs = C.TIME_UNSET;
pendingOutputStreamOffsetCount = 0; pendingOutputStreamOffsetCount = 0;
clearReportedVideoSize(); clearReportedVideoSize();
clearRenderedFirstFrame(); clearRenderedFirstFrame();
...@@ -495,6 +502,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -495,6 +502,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@Override @Override
protected void onQueueInputBuffer(DecoderInputBuffer buffer) { protected void onQueueInputBuffer(DecoderInputBuffer buffer) {
buffersInCodecCount++; buffersInCodecCount++;
lastInputTimeUs = Math.max(buffer.timeUs, lastInputTimeUs);
if (Util.SDK_INT < 23 && tunneling) { if (Util.SDK_INT < 23 && tunneling) {
maybeNotifyRenderedFirstFrame(); maybeNotifyRenderedFirstFrame();
} }
...@@ -538,13 +546,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -538,13 +546,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
initialPositionUs = positionUs; initialPositionUs = positionUs;
} }
while (pendingOutputStreamOffsetCount != 0
&& bufferPresentationTimeUs >= pendingOutputStreamOffsetsUs[0]) {
outputStreamOffsetUs = pendingOutputStreamOffsetsUs[0];
pendingOutputStreamOffsetCount--;
System.arraycopy(pendingOutputStreamOffsetsUs, 1, pendingOutputStreamOffsetsUs, 0,
pendingOutputStreamOffsetCount);
}
long presentationTimeUs = bufferPresentationTimeUs - outputStreamOffsetUs; long presentationTimeUs = bufferPresentationTimeUs - outputStreamOffsetUs;
if (shouldSkip) { if (shouldSkip) {
...@@ -639,6 +640,23 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -639,6 +640,23 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@Override @Override
protected void onProcessedOutputBuffer(long presentationTimeUs) { protected void onProcessedOutputBuffer(long presentationTimeUs) {
buffersInCodecCount--; buffersInCodecCount--;
while (pendingOutputStreamOffsetCount != 0
&& presentationTimeUs >= pendingOutputStreamSwitchTimesUs[0]) {
outputStreamOffsetUs = pendingOutputStreamOffsetsUs[0];
pendingOutputStreamOffsetCount--;
System.arraycopy(
pendingOutputStreamOffsetsUs,
/* srcPos= */ 1,
pendingOutputStreamOffsetsUs,
/* destPos= */ 0,
pendingOutputStreamOffsetCount);
System.arraycopy(
pendingOutputStreamSwitchTimesUs,
/* srcPos= */ 1,
pendingOutputStreamSwitchTimesUs,
/* destPos= */ 0,
pendingOutputStreamOffsetCount);
}
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment