diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index ff61ce7afe..2ceeeea103 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.mediacodec; +import static com.google.android.exoplayer2.util.Assertions.checkState; import static java.lang.Math.max; import android.annotation.TargetApi; @@ -352,6 +353,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { private final TimedValueQueue formatQueue; private final ArrayList decodeOnlyPresentationTimestamps; private final MediaCodec.BufferInfo outputBufferInfo; + private final long[] pendingOutputStreamStartPositionsUs; private final long[] pendingOutputStreamOffsetsUs; private final long[] pendingOutputStreamSwitchTimesUs; @@ -409,6 +411,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { @MediaCodecOperationMode private int mediaCodecOperationMode; @Nullable private ExoPlaybackException pendingPlaybackException; protected DecoderCounters decoderCounters; + private long outputStreamStartPositionUs; private long outputStreamOffsetUs; private int pendingOutputStreamOffsetCount; @@ -439,8 +442,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer { outputBufferInfo = new MediaCodec.BufferInfo(); operatingRate = 1f; mediaCodecOperationMode = OPERATION_MODE_SYNCHRONOUS; + pendingOutputStreamStartPositionsUs = 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]; + outputStreamStartPositionUs = C.TIME_UNSET; outputStreamOffsetUs = C.TIME_UNSET; bypassBatchBuffer = new BatchBuffer(); resetCodecStateForRelease(); @@ -685,8 +690,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer { @Override protected void onStreamChanged(Format[] formats, long startPositionUs, long offsetUs) throws ExoPlaybackException { - if (outputStreamOffsetUs == C.TIME_UNSET) { - outputStreamOffsetUs = offsetUs; + if (this.outputStreamOffsetUs == C.TIME_UNSET) { + checkState(this.outputStreamStartPositionUs == C.TIME_UNSET); + this.outputStreamStartPositionUs = startPositionUs; + this.outputStreamOffsetUs = offsetUs; } else { if (pendingOutputStreamOffsetCount == pendingOutputStreamOffsetsUs.length) { Log.w( @@ -696,6 +703,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } else { pendingOutputStreamOffsetCount++; } + pendingOutputStreamStartPositionsUs[pendingOutputStreamOffsetCount - 1] = startPositionUs; pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1] = offsetUs; pendingOutputStreamSwitchTimesUs[pendingOutputStreamOffsetCount - 1] = largestQueuedPresentationTimeUs; @@ -721,6 +729,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer { formatQueue.clear(); if (pendingOutputStreamOffsetCount != 0) { outputStreamOffsetUs = pendingOutputStreamOffsetsUs[pendingOutputStreamOffsetCount - 1]; + outputStreamStartPositionUs = + pendingOutputStreamStartPositionsUs[pendingOutputStreamOffsetCount - 1]; pendingOutputStreamOffsetCount = 0; } } @@ -738,6 +748,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { @Override protected void onDisabled() { inputFormat = null; + outputStreamStartPositionUs = C.TIME_UNSET; outputStreamOffsetUs = C.TIME_UNSET; pendingOutputStreamOffsetCount = 0; if (sourceDrmSession != null || codecDrmSession != null) { @@ -1545,8 +1556,15 @@ public abstract class MediaCodecRenderer extends BaseRenderer { protected void onProcessedOutputBuffer(long presentationTimeUs) { while (pendingOutputStreamOffsetCount != 0 && presentationTimeUs >= pendingOutputStreamSwitchTimesUs[0]) { + outputStreamStartPositionUs = pendingOutputStreamStartPositionsUs[0]; outputStreamOffsetUs = pendingOutputStreamOffsetsUs[0]; pendingOutputStreamOffsetCount--; + System.arraycopy( + pendingOutputStreamStartPositionsUs, + /* srcPos= */ 1, + pendingOutputStreamStartPositionsUs, + /* destPos= */ 0, + pendingOutputStreamOffsetCount); System.arraycopy( pendingOutputStreamOffsetsUs, /* srcPos= */ 1, @@ -1945,6 +1963,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer { return largestQueuedPresentationTimeUs; } + /** + * Returns the start position of the output {@link SampleStream}, in renderer time microseconds. + */ + protected final long getOutputStreamStartPositionUs() { + return outputStreamStartPositionUs; + } + /** * Returns the offset that should be subtracted from {@code bufferPresentationTimeUs} in {@link * #processOutputBuffer(long, long, MediaCodec, ByteBuffer, int, int, int, long, boolean, boolean, @@ -2080,7 +2105,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { BatchBuffer batchBuffer = bypassBatchBuffer; // Let's process the pending buffer if any. - Assertions.checkState(!outputStreamEnded); + checkState(!outputStreamEnded); if (!batchBuffer.isEmpty()) { // Optimisation: Do not process buffer if empty. if (processOutputBuffer( positionUs, @@ -2119,7 +2144,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } // Now refill the empty buffer for the next iteration. - Assertions.checkState(!inputStreamEnded); + checkState(!inputStreamEnded); FormatHolder formatHolder = getFormatHolder(); boolean formatChange = readBatchFromSource(formatHolder, batchBuffer);