From b6d0540059d3393a9e179eb5975f94a2ec58f804 Mon Sep 17 00:00:00 2001 From: ibaker Date: Wed, 9 Oct 2024 07:24:19 -0700 Subject: [PATCH] Use `scaleLargeTimestamp` in `TimestampAdjuster` This helps avoid overflows in intermediate calculations. Verified the value in the test using `BigInteger`: ``` jshell> BigInteger.valueOf(1L << 52).multiply(BigInteger.valueOf(90000)).divide(BigInteger.valueOf(1000000)) $3 ==> 405323966463344 ``` Issue: androidx/media#1763 #cherrypick PiperOrigin-RevId: 684028178 --- RELEASENOTES.md | 4 ++++ .../java/androidx/media3/common/util/TimestampAdjuster.java | 4 ++-- .../androidx/media3/common/util/TimestampAdjusterTest.java | 6 ++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9996b0c4f9..62a7ac7ebb 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -74,6 +74,10 @@ * Add workaround for codecs that get stuck after the last sample without returning an end-of-stream signal. * Text: + * Ensure WebVTT in HLS with very large subtitle timestamps (which overflow + a 64-bit `long` when represented as microseconds and multiplied by the + `90,000` MPEG timebase) are displayed + ([#1763](https://github.com/androidx/media/issues/1763)). * Metadata: * Assign the `C.TRACK_TYPE_METADATA` type to tracks containing icy or vnd.dvb.ait content. diff --git a/libraries/common/src/main/java/androidx/media3/common/util/TimestampAdjuster.java b/libraries/common/src/main/java/androidx/media3/common/util/TimestampAdjuster.java index 5dd6afbdf0..f471724f43 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/TimestampAdjuster.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/TimestampAdjuster.java @@ -271,7 +271,7 @@ public final class TimestampAdjuster { * @return The corresponding value in microseconds. */ public static long ptsToUs(long pts) { - return (pts * C.MICROS_PER_SECOND) / 90000; + return Util.scaleLargeTimestamp(pts, C.MICROS_PER_SECOND, 90000); } /** @@ -295,6 +295,6 @@ public final class TimestampAdjuster { * @return The corresponding value as a 90 kHz clock timestamp. */ public static long usToNonWrappedPts(long us) { - return (us * 90000) / C.MICROS_PER_SECOND; + return Util.scaleLargeTimestamp(us, 90000, C.MICROS_PER_SECOND); } } diff --git a/libraries/common/src/test/java/androidx/media3/common/util/TimestampAdjusterTest.java b/libraries/common/src/test/java/androidx/media3/common/util/TimestampAdjusterTest.java index 8cc6a8f275..d6cbd3fc53 100644 --- a/libraries/common/src/test/java/androidx/media3/common/util/TimestampAdjusterTest.java +++ b/libraries/common/src/test/java/androidx/media3/common/util/TimestampAdjusterTest.java @@ -240,4 +240,10 @@ public class TimestampAdjusterTest { assertThat(secondAdjustedTimestampUs - firstAdjustedTimestampUs).isGreaterThan(0x100000000L); } + + // https://github.com/androidx/media/issues/1763 + @Test + public void usToWrappedPts_usTimestampCloseToOverflow_doesntOverflow() { + assertThat(TimestampAdjuster.usToNonWrappedPts(1L << 52)).isEqualTo(405323966463344L); + } }