diff --git a/src/isobmff/isobmff-demuxer.ts b/src/isobmff/isobmff-demuxer.ts index 124c7b1..35e90ae 100644 --- a/src/isobmff/isobmff-demuxer.ts +++ b/src/isobmff/isobmff-demuxer.ts @@ -51,13 +51,13 @@ import { MATRIX_COEFFICIENTS_MAP_INVERSE, normalizeRotation, roundToMultiple, - roundToPrecision, Rotation, textDecoder, TransformationMatrix, TRANSFER_CHARACTERISTICS_MAP_INVERSE, UNDETERMINED_LANGUAGE, toDataView, + roundIfAlmostInteger, } from '../misc'; import { EncodedPacket, PLACEHOLDER_DATA } from '../packet'; import { buildIsobmffMimeType } from './isobmff-misc'; @@ -2388,7 +2388,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking { // Do a little rounding to catch cases where the result is very close to an integer. If it is, it's likely // that the number was originally an integer divided by the timescale. For stability, it's best // to return the integer in this case. - return roundToPrecision(timestamp * this.internalTrack.timescale, 14) + this.internalTrack.editListOffset; + return roundIfAlmostInteger(timestamp * this.internalTrack.timescale) + this.internalTrack.editListOffset; } async getPacket(timestamp: number, options: PacketRetrievalOptions) { diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index 9af38db..4c69c35 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -43,7 +43,7 @@ import { MATRIX_COEFFICIENTS_MAP_INVERSE, normalizeRotation, Rotation, - roundToPrecision, + roundIfAlmostInteger, TRANSFER_CHARACTERISTICS_MAP_INVERSE, UNDETERMINED_LANGUAGE, } from '../misc'; @@ -1874,7 +1874,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking { // Do a little rounding to catch cases where the result is very close to an integer. If it is, it's likely // that the number was originally an integer divided by the timescale. For stability, it's best // to return the integer in this case. - return roundToPrecision(timestamp * this.internalTrack.segment.timestampFactor, 14); + return roundIfAlmostInteger(timestamp * this.internalTrack.segment.timestampFactor); } async getPacket(timestamp: number, options: PacketRetrievalOptions) { diff --git a/src/misc.ts b/src/misc.ts index 2f91ed0..68cb687 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -486,9 +486,14 @@ export const clamp = (value: number, min: number, max: number) => { export const UNDETERMINED_LANGUAGE = 'und'; -export const roundToPrecision = (value: number, digits: number) => { - const factor = 10 ** digits; - return Math.round(value * factor) / factor; +export const roundIfAlmostInteger = (value: number) => { + const rounded = Math.round(value); + + if (Math.abs(value / rounded - 1) < 10 * Number.EPSILON) { + return rounded; + } else { + return value; + } }; export const roundToMultiple = (value: number, multiple: number) => { diff --git a/src/ogg/ogg-demuxer.ts b/src/ogg/ogg-demuxer.ts index 495865d..556e3af 100644 --- a/src/ogg/ogg-demuxer.ts +++ b/src/ogg/ogg-demuxer.ts @@ -19,7 +19,7 @@ import { binarySearchLessOrEqual, findLast, last, - roundToPrecision, + roundIfAlmostInteger, toDataView, UNDETERMINED_LANGUAGE, } from '../misc'; @@ -577,7 +577,7 @@ class OggAudioTrackBacking implements InputAudioTrackBacking { return this.getPacketSequential(timestamp, options); } - const timestampInSamples = roundToPrecision(timestamp * this.internalSampleRate, 14); + const timestampInSamples = roundIfAlmostInteger(timestamp * this.internalSampleRate); if (timestampInSamples === 0) { // Fast path for timestamp 0 - avoids binary search when playing back from the start return this.getFirstPacket(options); @@ -910,7 +910,7 @@ class OggAudioTrackBacking implements InputAudioTrackBacking { const release = await this.sequentialScanMutex.acquire(); // Requires exclusivity because we write to a cache try { - const timestampInSamples = roundToPrecision(timestamp * this.internalSampleRate, 14); + const timestampInSamples = roundIfAlmostInteger(timestamp * this.internalSampleRate); timestamp = timestampInSamples / this.internalSampleRate; const index = binarySearchLessOrEqual(