From e95c42ef98f953282575d210bf5e739efddbb1bd Mon Sep 17 00:00:00 2001 From: olly Date: Mon, 2 Aug 2021 16:36:52 +0100 Subject: [PATCH] Simplify TimestampAdjuster logic - Use timestampOffsetUs == C.TIME_UNSET directly as the way of determining whether the adjuster has determined the offset, rather than relying on lastSampleTimestampUs checks for this. - Remove comment referring to lastSampleTimestampUs as holding the "adjusted PTS". Its value may not have originated from a PTS timestamp. It's also confusing to refer to it as "adjusted" given timestampOffsetUs has not been applied to it. - Fix PassthroughSectionPayloadReader to make sure it'll never output a sample with an unset timestamp. #minor-release PiperOrigin-RevId: 388226180 --- .../exoplayer2/util/TimestampAdjuster.java | 47 +++++++------------ .../ts/PassthroughSectionPayloadReader.java | 12 ++--- .../source/hls/TimestampAdjusterProvider.java | 5 +- 3 files changed, 24 insertions(+), 40 deletions(-) diff --git a/library/common/src/main/java/com/google/android/exoplayer2/util/TimestampAdjuster.java b/library/common/src/main/java/com/google/android/exoplayer2/util/TimestampAdjuster.java index a19bc9fd74..cb7edd527b 100644 --- a/library/common/src/main/java/com/google/android/exoplayer2/util/TimestampAdjuster.java +++ b/library/common/src/main/java/com/google/android/exoplayer2/util/TimestampAdjuster.java @@ -46,7 +46,7 @@ public final class TimestampAdjuster { private long timestampOffsetUs; @GuardedBy("this") - private long lastSampleTimestampUs; + private long lastUnadjustedTimestampUs; /** * @param firstSampleTimestampUs The desired value of the first adjusted sample timestamp in @@ -91,7 +91,7 @@ public final class TimestampAdjuster { sharedInitializationStarted = true; } if (!canInitialize || this.firstSampleTimestampUs != firstSampleTimestampUs) { - while (lastSampleTimestampUs == C.TIME_UNSET) { + while (timestampOffsetUs == C.TIME_UNSET) { wait(); } } @@ -108,28 +108,21 @@ public final class TimestampAdjuster { /** * Returns the last value obtained from {@link #adjustSampleTimestamp}. If {@link * #adjustSampleTimestamp} has not been called, returns the result of calling {@link - * #getFirstSampleTimestampUs()}. If this value is {@link #DO_NOT_OFFSET}, returns {@link - * C#TIME_UNSET}. + * #getFirstSampleTimestampUs()} unless that value is {@link #DO_NOT_OFFSET}, in which case {@link + * C#TIME_UNSET} is returned. */ public synchronized long getLastAdjustedTimestampUs() { - return lastSampleTimestampUs != C.TIME_UNSET - ? (lastSampleTimestampUs + timestampOffsetUs) + return lastUnadjustedTimestampUs != C.TIME_UNSET + ? lastUnadjustedTimestampUs + timestampOffsetUs : firstSampleTimestampUs != DO_NOT_OFFSET ? firstSampleTimestampUs : C.TIME_UNSET; } /** - * Returns the offset between the input of {@link #adjustSampleTimestamp(long)} and its output. If - * {@link #DO_NOT_OFFSET} was provided to the constructor, 0 is returned. If the timestamp - * adjuster is yet not initialized, {@link C#TIME_UNSET} is returned. - * - * @return The offset between {@link #adjustSampleTimestamp(long)}'s input and output. {@link - * C#TIME_UNSET} if the adjuster is not yet initialized and 0 if timestamps should not be - * offset. + * Returns the offset between the input of {@link #adjustSampleTimestamp(long)} and its output, or + * {@link C#TIME_UNSET} if the offset has not yet been determined. */ public synchronized long getTimestampOffsetUs() { - return firstSampleTimestampUs == DO_NOT_OFFSET - ? 0 - : lastSampleTimestampUs == C.TIME_UNSET ? C.TIME_UNSET : timestampOffsetUs; + return timestampOffsetUs; } /** @@ -140,8 +133,8 @@ public final class TimestampAdjuster { */ public synchronized void reset(long firstSampleTimestampUs) { this.firstSampleTimestampUs = firstSampleTimestampUs; - lastSampleTimestampUs = C.TIME_UNSET; - timestampOffsetUs = 0; + timestampOffsetUs = firstSampleTimestampUs == DO_NOT_OFFSET ? 0 : C.TIME_UNSET; + lastUnadjustedTimestampUs = C.TIME_UNSET; sharedInitializationStarted = false; } @@ -155,10 +148,10 @@ public final class TimestampAdjuster { if (pts90Khz == C.TIME_UNSET) { return C.TIME_UNSET; } - if (lastSampleTimestampUs != C.TIME_UNSET) { + if (lastUnadjustedTimestampUs != C.TIME_UNSET) { // The wrap count for the current PTS may be closestWrapCount or (closestWrapCount - 1), // and we need to snap to the one closest to lastSampleTimestampUs. - long lastPts = usToNonWrappedPts(lastSampleTimestampUs); + long lastPts = usToNonWrappedPts(lastUnadjustedTimestampUs); long closestWrapCount = (lastPts + (MAX_PTS_PLUS_ONE / 2)) / MAX_PTS_PLUS_ONE; long ptsWrapBelow = pts90Khz + (MAX_PTS_PLUS_ONE * (closestWrapCount - 1)); long ptsWrapAbove = pts90Khz + (MAX_PTS_PLUS_ONE * closestWrapCount); @@ -180,18 +173,12 @@ public final class TimestampAdjuster { if (timeUs == C.TIME_UNSET) { return C.TIME_UNSET; } - // Record the adjusted PTS to adjust for wraparound next time. - if (lastSampleTimestampUs != C.TIME_UNSET) { - lastSampleTimestampUs = timeUs; - } else { - if (firstSampleTimestampUs != DO_NOT_OFFSET) { - // Calculate the timestamp offset. - timestampOffsetUs = firstSampleTimestampUs - timeUs; - } - lastSampleTimestampUs = timeUs; - // Notify threads waiting for this adjuster to be initialized. + if (timestampOffsetUs == C.TIME_UNSET) { + timestampOffsetUs = firstSampleTimestampUs - timeUs; + // Notify threads waiting for the timestamp offset to be determined. notifyAll(); } + lastUnadjustedTimestampUs = timeUs; return timeUs + timestampOffsetUs; } diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PassthroughSectionPayloadReader.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PassthroughSectionPayloadReader.java index 72667e2a3f..111cfd8750 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PassthroughSectionPayloadReader.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/ts/PassthroughSectionPayloadReader.java @@ -62,9 +62,10 @@ public final class PassthroughSectionPayloadReader implements SectionPayloadRead @Override public void consume(ParsableByteArray sectionData) { assertInitialized(); + long sampleTimestampUs = timestampAdjuster.getLastAdjustedTimestampUs(); long subsampleOffsetUs = timestampAdjuster.getTimestampOffsetUs(); - if (subsampleOffsetUs == C.TIME_UNSET) { - // Don't output samples without a known subsample offset. + if (sampleTimestampUs == C.TIME_UNSET || subsampleOffsetUs == C.TIME_UNSET) { + // Don't output samples without a known sample timestamp and subsample offset. return; } if (subsampleOffsetUs != format.subsampleOffsetUs) { @@ -73,12 +74,7 @@ public final class PassthroughSectionPayloadReader implements SectionPayloadRead } int sampleSize = sectionData.bytesLeft(); output.sampleData(sectionData, sampleSize); - output.sampleMetadata( - timestampAdjuster.getLastAdjustedTimestampUs(), - C.BUFFER_FLAG_KEY_FRAME, - sampleSize, - 0, - null); + output.sampleMetadata(sampleTimestampUs, C.BUFFER_FLAG_KEY_FRAME, sampleSize, 0, null); } @EnsuresNonNull({"timestampAdjuster", "output"}) diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/TimestampAdjusterProvider.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/TimestampAdjusterProvider.java index 9249bec7a5..0509376f72 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/TimestampAdjusterProvider.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/TimestampAdjusterProvider.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.source.hls; import android.util.SparseArray; +import androidx.annotation.Nullable; import com.google.android.exoplayer2.util.TimestampAdjuster; /** Provides {@link TimestampAdjuster} instances for use during HLS playbacks. */ @@ -37,9 +38,9 @@ public final class TimestampAdjusterProvider { * @return A {@link TimestampAdjuster}. */ public TimestampAdjuster getAdjuster(int discontinuitySequence) { - TimestampAdjuster adjuster = timestampAdjusters.get(discontinuitySequence); + @Nullable TimestampAdjuster adjuster = timestampAdjusters.get(discontinuitySequence); if (adjuster == null) { - adjuster = new TimestampAdjuster(TimestampAdjuster.DO_NOT_OFFSET); + adjuster = new TimestampAdjuster(/* firstSampleTimestampUs= */ 0); timestampAdjusters.put(discontinuitySequence, adjuster); } return adjuster;