Allow audio position to jump on first input buffer

Allow the position to jump on receiving the first presentable input buffer,
if and only if the buffer timestamp differs significantly from what was
expected. This prevents a stuck buffering case for streams that are thought
to start at t=0, but actually start at t=large_value.
This commit is contained in:
Oliver Woodman 2018-02-22 10:01:04 +00:00
parent f69cc191ab
commit 2cff596162
2 changed files with 31 additions and 0 deletions

View File

@ -29,6 +29,7 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.PlayerMessage.Target;
import com.google.android.exoplayer2.audio.AudioRendererEventListener.EventDispatcher;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
@ -70,6 +71,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
private int encoderDelay;
private int encoderPadding;
private long currentPositionUs;
private boolean allowFirstBufferPositionDiscontinuity;
private boolean allowPositionDiscontinuity;
/**
@ -366,6 +368,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
super.onPositionReset(positionUs, joining);
audioSink.reset();
currentPositionUs = positionUs;
allowFirstBufferPositionDiscontinuity = true;
allowPositionDiscontinuity = true;
}
@ -424,6 +427,19 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
return audioSink.getPlaybackParameters();
}
@Override
protected void onQueueInputBuffer(DecoderInputBuffer buffer) {
if (allowFirstBufferPositionDiscontinuity && !buffer.isDecodeOnly()) {
// TODO: Remove this hack once we have a proper fix for [Internal: b/71876314].
// Allow the position to jump if the first presentable input buffer has a timestamp that
// differs significantly from what was expected.
if (Math.abs(buffer.timeUs - currentPositionUs) > 500000) {
currentPositionUs = buffer.timeUs;
}
allowFirstBufferPositionDiscontinuity = false;
}
}
@Override
protected boolean processOutputBuffer(long positionUs, long elapsedRealtimeUs, MediaCodec codec,
ByteBuffer buffer, int bufferIndex, int bufferFlags, long bufferPresentationTimeUs,

View File

@ -105,6 +105,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
private boolean audioTrackNeedsConfigure;
private long currentPositionUs;
private boolean allowFirstBufferPositionDiscontinuity;
private boolean allowPositionDiscontinuity;
private boolean inputStreamEnded;
private boolean outputStreamEnded;
@ -416,6 +417,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
return false;
}
inputBuffer.flip();
onQueueInputBuffer(inputBuffer);
decoder.queueInputBuffer(inputBuffer);
decoderReceivedBuffers = true;
decoderCounters.inputBufferCount++;
@ -504,6 +506,7 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
audioSink.reset();
currentPositionUs = positionUs;
allowFirstBufferPositionDiscontinuity = true;
allowPositionDiscontinuity = true;
inputStreamEnded = false;
outputStreamEnded = false;
@ -654,6 +657,18 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
eventDispatcher.inputFormatChanged(newFormat);
}
private void onQueueInputBuffer(DecoderInputBuffer buffer) {
if (allowFirstBufferPositionDiscontinuity && !buffer.isDecodeOnly()) {
// TODO: Remove this hack once we have a proper fix for [Internal: b/71876314].
// Allow the position to jump if the first presentable input buffer has a timestamp that
// differs significantly from what was expected.
if (Math.abs(buffer.timeUs - currentPositionUs) > 500000) {
currentPositionUs = buffer.timeUs;
}
allowFirstBufferPositionDiscontinuity = false;
}
}
private void updateCurrentPosition() {
long newCurrentPositionUs = audioSink.getCurrentPositionUs(isEnded());
if (newCurrentPositionUs != AudioSink.CURRENT_POSITION_NOT_SET) {