diff --git a/src/isobmff/isobmff-demuxer.ts b/src/isobmff/isobmff-demuxer.ts index 6f5fd59..5e4fbf5 100644 --- a/src/isobmff/isobmff-demuxer.ts +++ b/src/isobmff/isobmff-demuxer.ts @@ -2196,6 +2196,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking { private findSampleInFragmentsForTimestamp(timestampInTimescale: number) { const fragmentIndex = binarySearchLessOrEqual( + // This array is technically not sorted by start timestamp, but for any reasonable file, it basically is. this.internalTrack.fragments, timestampInTimescale, x => x.trackData.get(this.internalTrack.id)!.startTimestamp, @@ -2223,6 +2224,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking { private findKeySampleInFragmentsForTimestamp(timestampInTimescale: number) { const fragmentIndex = binarySearchLessOrEqual( + // This array is technically not sorted by start timestamp, but for any reasonable file, it basically is. this.internalTrack.fragments, timestampInTimescale, x => x.trackData.get(this.internalTrack.id)!.startTimestamp, diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index 64d9d9d..074dbaa 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -507,16 +507,16 @@ export class MatroskaDemuxer extends Demuxer { if (track) { const insertionIndex = binarySearchLessOrEqual( track.clusters, - cluster.timestamp, - x => x.timestamp, + cluster.elementStartPos, + x => x.elementStartPos, ); track.clusters.splice(insertionIndex + 1, 0, cluster); if (hasKeyFrame) { const insertionIndex = binarySearchLessOrEqual( track.clustersWithKeyFrame, - cluster.timestamp, - x => x.timestamp, + cluster.elementStartPos, + x => x.elementStartPos, ); track.clustersWithKeyFrame.splice(insertionIndex + 1, 0, cluster); } @@ -1268,6 +1268,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking { private findBlockInClustersForTimestamp(timestampInTimescale: number) { const clusterIndex = binarySearchLessOrEqual( + // This array is technically not sorted by start timestamp, but for any reasonable file, it basically is. this.internalTrack.clusters, timestampInTimescale, x => x.trackData.get(this.internalTrack.id)!.startTimestamp, @@ -1295,6 +1296,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking { private findKeyBlockInClustersForTimestamp(timestampInTimescale: number) { const indexInKeyFrameClusters = binarySearchLessOrEqual( + // This array is technically not sorted by start timestamp, but for any reasonable file, it basically is. this.internalTrack.clustersWithKeyFrame, timestampInTimescale, x => x.trackData.get(this.internalTrack.id)!.firstKeyFrameTimestamp!, diff --git a/src/misc.ts b/src/misc.ts index 854f4f2..9b07f4b 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -233,17 +233,18 @@ export const reverseBitsU32 = (x: number): number => { return x >>> 0; // Ensure it's treated as an unsigned 32-bit integer }; +/** Returns the smallest index i such that val[i] === key, or -1 if no such index exists. */ export const binarySearchExact = (arr: T[], key: number, valueGetter: (x: T) => number): number => { let low = 0; let high = arr.length - 1; - let res = -1; + let ans = -1; while (low <= high) { const mid = (low + high) >> 1; const midVal = valueGetter(arr[mid]!); if (midVal === key) { - res = mid; + ans = mid; high = mid - 1; // Continue searching left to find the lowest index } else if (midVal < key) { low = mid + 1; @@ -252,13 +253,14 @@ export const binarySearchExact = (arr: T[], key: number, valueGetter: (x: T) } } - return res; + return ans; }; +/** Returns the largest index i such that val[i] <= key, or -1 if no such index exists. */ export const binarySearchLessOrEqual = (arr: T[], key: number, valueGetter: (x: T) => number) => { - let ans = -1; let low = 0; let high = arr.length - 1; + let ans = -1; while (low <= high) { const mid = (low + (high - low + 1) / 2) | 0;