From ee0c6224af554bd076fcc91bc7d7b7d1cf7853d5 Mon Sep 17 00:00:00 2001 From: ibaker Date: Fri, 5 Jun 2020 14:42:47 +0100 Subject: [PATCH] Respect 33-bit wraparound when calculating WebVTT timestamps in HLS Issue: #7462 PiperOrigin-RevId: 314919210 --- RELEASENOTES.md | 2 ++ .../exoplayer2/util/TimestampAdjuster.java | 19 ++++++++++++++++--- .../scte35/SpliceInfoDecoderTest.java | 3 ++- .../source/hls/WebvttExtractor.java | 5 +++-- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index fc0eacab2e..ce8541ed1e 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -157,6 +157,8 @@ * HLS: * Add support for upstream discard including cancelation of ongoing load ([#6322](https://github.com/google/ExoPlayer/issues/6322)). + * Respect 33-bit PTS wrapping when applying `X-TIMESTAMP-MAP` to WebVTT + timestamps ([#7464](https://github.com/google/ExoPlayer/issues/7464)). * Ogg: Allow non-contiguous pages ([#7230](https://github.com/google/ExoPlayer/issues/7230)). * Extractors: 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 439374a086..65f88b1983 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 @@ -113,7 +113,7 @@ public final class TimestampAdjuster { if (lastSampleTimestampUs != 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 = usToPts(lastSampleTimestampUs); + long lastPts = usToNonWrappedPts(lastSampleTimestampUs); 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); @@ -173,14 +173,27 @@ public final class TimestampAdjuster { return (pts * C.MICROS_PER_SECOND) / 90000; } + /** + * Converts a timestamp in microseconds to a 90 kHz clock timestamp, performing wraparound to keep + * the result within 33-bits. + * + * @param us A value in microseconds. + * @return The corresponding value as a 90 kHz clock timestamp, wrapped to 33 bits. + */ + public static long usToWrappedPts(long us) { + return usToNonWrappedPts(us) % MAX_PTS_PLUS_ONE; + } + /** * Converts a timestamp in microseconds to a 90 kHz clock timestamp. * + *

Does not perform any wraparound. To get a 90 kHz timestamp suitable for use with MPEG-TS, + * use {@link #usToWrappedPts(long)}. + * * @param us A value in microseconds. * @return The corresponding value as a 90 kHz clock timestamp. */ - public static long usToPts(long us) { + public static long usToNonWrappedPts(long us) { return (us * 90000) / C.MICROS_PER_SECOND; } - } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java b/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java index 90c2e7d386..dcb1f634c9 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/metadata/scte35/SpliceInfoDecoderTest.java @@ -200,7 +200,8 @@ public final class SpliceInfoDecoderTest { } private static long removePtsConversionPrecisionError(long timeUs, long offsetUs) { - return TimestampAdjuster.ptsToUs(TimestampAdjuster.usToPts(timeUs - offsetUs)) + offsetUs; + return TimestampAdjuster.ptsToUs(TimestampAdjuster.usToNonWrappedPts(timeUs - offsetUs)) + + offsetUs; } } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java index 6a390001d2..832de00cf9 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/WebvttExtractor.java @@ -176,8 +176,9 @@ public final class WebvttExtractor implements Extractor { long firstCueTimeUs = WebvttParserUtil.parseTimestampUs(Assertions.checkNotNull(cueHeaderMatcher.group(1))); - long sampleTimeUs = timestampAdjuster.adjustTsTimestamp( - TimestampAdjuster.usToPts(firstCueTimeUs + tsTimestampUs - vttTimestampUs)); + long sampleTimeUs = + timestampAdjuster.adjustTsTimestamp( + TimestampAdjuster.usToWrappedPts(firstCueTimeUs + tsTimestampUs - vttTimestampUs)); long subsampleOffsetUs = sampleTimeUs - firstCueTimeUs; // Output the track. TrackOutput trackOutput = buildTrackOutput(subsampleOffsetUs);