Propagate end of stream received from OnFrameRenderedListener

Previously the renderer EOS (aka last frame rendered), was reported as soon
as the last encoded frame was queued in the codec renderer.
This leaded to EOS reported too early.

PiperOrigin-RevId: 280456277
This commit is contained in:
krocard 2019-11-14 18:18:02 +00:00 committed by Oliver Woodman
parent c8e7ecd367
commit 5579cc89c6
3 changed files with 32 additions and 4 deletions

View file

@ -2,6 +2,9 @@
### dev-v2 (not yet released) ###
* Video tunneling: Fix renderer end-of-stream with `OnFrameRenderedListener`
from API 23, tunneled renderer must send a special timestamp on EOS.
Previously the EOS was reported when the input stream reached EOS.
* Require an end time or duration for SubRip (SRT) and SubStation Alpha
(SSA/ASS) subtitles. This applies to both sidecar files & subtitles
[embedded in Matroska streams](https://matroska.org/technical/specs/subtitles/index.html).

View file

@ -373,6 +373,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private boolean waitingForFirstSyncSample;
private boolean waitingForFirstSampleInFormat;
private boolean skipMediaCodecStopOnRelease;
private boolean pendingOutputEndOfStream;
protected DecoderCounters decoderCounters;
@ -603,6 +604,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
inputStreamEnded = false;
outputStreamEnded = false;
pendingOutputEndOfStream = false;
flushOrReinitializeCodec();
formatQueue.clear();
}
@ -686,6 +688,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
@Override
public void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
if (pendingOutputEndOfStream) {
pendingOutputEndOfStream = false;
processEndOfStream();
}
try {
if (outputStreamEnded) {
renderToEndOfStream();
@ -1693,6 +1699,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
}
}
/**
* Notifies the renderer that output end of stream is pending and should be handled on the next
* render.
*/
protected final void setPendingOutputEndOfStream() {
pendingOutputEndOfStream = true;
}
private void reinitializeCodec() throws ExoPlaybackException {
releaseCodec();
maybeInitCodec();

View file

@ -93,6 +93,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
*/
private static final float INITIAL_FORMAT_MAX_INPUT_SIZE_SCALE_FACTOR = 1.5f;
/** Magic frame render timestamp that indicates the EOS in tunneling mode. */
private static final long TUNNELING_EOS_PRESENTATION_TIME_US = Long.MAX_VALUE;
/** A {@link DecoderException} with additional surface information. */
public static final class VideoDecoderException extends DecoderException {
@ -604,8 +607,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@Override
protected boolean getCodecNeedsEosPropagation() {
// In tunneling mode we can't dequeue an end-of-stream buffer, so propagate it in the renderer.
return tunneling;
// Since API 23, onFrameRenderedListener allows for detection of the renderer EOS.
return tunneling && Util.SDK_INT < 23;
}
@Override
@ -946,6 +949,11 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
onProcessedOutputBuffer(presentationTimeUs);
}
/** Called when a output EOS was received in tunneling mode. */
private void onProcessedTunneledEndOfStream() {
setPendingOutputEndOfStream();
}
/**
* Called when an output buffer is successfully processed.
*
@ -1754,9 +1762,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// Stale event.
return;
}
onProcessedTunneledBuffer(presentationTimeUs);
if (presentationTimeUs == TUNNELING_EOS_PRESENTATION_TIME_US) {
onProcessedTunneledEndOfStream();
} else {
onProcessedTunneledBuffer(presentationTimeUs);
}
}
}
}