@ahmedrowaihi/mediabunny 1.65.2-beta.320 → 1.65.2-beta.321

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2823,7 +2823,7 @@ var Mediabunny = (() => {
2823
2823
  var TRUEHD_MAJOR_SYNC_WORD = 4168249274;
2824
2824
 
2825
2825
  // src/version.ts
2826
- var VERSION = "1.65.1";
2826
+ var VERSION = "1.65.2";
2827
2827
  var VERSIONED_NAME = `Mediabunny v${VERSION}`;
2828
2828
 
2829
2829
  // src/codec-data.ts
@@ -7303,50 +7303,62 @@ var Mediabunny = (() => {
7303
7303
  };
7304
7304
  var createAes128CbcDecryptStream = (reader, getInit, close) => {
7305
7305
  let initted = false;
7306
+ let closed = false;
7306
7307
  let pos = 0;
7307
7308
  const CHUNK_SIZE = 2 ** 16;
7308
7309
  const BLOCK_SIZE = 16;
7309
7310
  const aesContext = new Aes128CbcContext();
7311
+ const closeOnce = () => {
7312
+ if (!closed) {
7313
+ closed = true;
7314
+ close();
7315
+ }
7316
+ };
7310
7317
  return new ReadableStream({
7311
7318
  pull: async (controller) => {
7312
- if (!initted) {
7313
- aesContext.init(await getInit());
7314
- initted = true;
7315
- }
7316
- const requestedLength = CHUNK_SIZE + BLOCK_SIZE;
7317
- let nextSlice = reader.requestSliceRange(pos, 0, requestedLength);
7318
- if (isThenable(nextSlice)) nextSlice = await nextSlice;
7319
- if (!nextSlice || nextSlice.length === 0) {
7320
- throw new Error("Invalid ciphertext.");
7321
- }
7322
- const sliceLength = nextSlice.length;
7323
- if (sliceLength % 16 !== 0) {
7324
- throw new Error("Invalid ciphertext.");
7325
- }
7326
- const bytesToRead = sliceLength === requestedLength ? sliceLength - BLOCK_SIZE : sliceLength;
7327
- const input = readBytes(nextSlice, bytesToRead);
7328
- const output = new Uint8Array(bytesToRead);
7329
- for (let i = 0; i < bytesToRead; i += 16) {
7330
- aesContext.in.set(input.subarray(i, i + 16));
7331
- aesContext.decrypt();
7332
- output.set(aesContext.out, i);
7333
- }
7334
- if (bytesToRead < sliceLength) {
7335
- controller.enqueue(output);
7336
- pos += bytesToRead;
7337
- } else {
7338
- const paddingLength = output[bytesToRead - 1];
7339
- if (paddingLength === 0 || paddingLength > 16) {
7340
- throw new Error("Invalid PKCS#7 padding. Incorrect key or corrupted data.");
7319
+ try {
7320
+ if (!initted) {
7321
+ aesContext.init(await getInit());
7322
+ initted = true;
7323
+ }
7324
+ const requestedLength = CHUNK_SIZE + BLOCK_SIZE;
7325
+ let nextSlice = reader.requestSliceRange(pos, 0, requestedLength);
7326
+ if (isThenable(nextSlice)) nextSlice = await nextSlice;
7327
+ if (!nextSlice || nextSlice.length === 0) {
7328
+ throw new Error("Invalid ciphertext.");
7329
+ }
7330
+ const sliceLength = nextSlice.length;
7331
+ if (sliceLength % 16 !== 0) {
7332
+ throw new Error("Invalid ciphertext.");
7333
+ }
7334
+ const bytesToRead = sliceLength === requestedLength ? sliceLength - BLOCK_SIZE : sliceLength;
7335
+ const input = readBytes(nextSlice, bytesToRead);
7336
+ const output = new Uint8Array(bytesToRead);
7337
+ for (let i = 0; i < bytesToRead; i += 16) {
7338
+ aesContext.in.set(input.subarray(i, i + 16));
7339
+ aesContext.decrypt();
7340
+ output.set(aesContext.out, i);
7341
+ }
7342
+ if (bytesToRead < sliceLength) {
7343
+ controller.enqueue(output);
7344
+ pos += bytesToRead;
7345
+ } else {
7346
+ const paddingLength = output[bytesToRead - 1];
7347
+ if (paddingLength === 0 || paddingLength > 16) {
7348
+ throw new Error("Invalid PKCS#7 padding. Incorrect key or corrupted data.");
7349
+ }
7350
+ const trimmedOutput = output.subarray(0, bytesToRead - paddingLength);
7351
+ controller.enqueue(trimmedOutput);
7352
+ controller.close();
7353
+ closeOnce();
7341
7354
  }
7342
- const trimmedOutput = output.subarray(0, bytesToRead - paddingLength);
7343
- controller.enqueue(trimmedOutput);
7344
- controller.close();
7345
- close();
7355
+ } catch (error) {
7356
+ closeOnce();
7357
+ throw error;
7346
7358
  }
7347
7359
  },
7348
7360
  cancel: () => {
7349
- close();
7361
+ closeOnce();
7350
7362
  }
7351
7363
  });
7352
7364
  };
@@ -8059,7 +8071,8 @@ var Mediabunny = (() => {
8059
8071
  fragmentPositionCache.splice(insertionIndex + 1, 0, {
8060
8072
  moofOffset: fragment.moofOffset,
8061
8073
  startTimestamp: trackData.startTimestamp,
8062
- endTimestamp: trackData.endTimestamp
8074
+ endTimestamp: trackData.endTimestamp,
8075
+ hasKeyFrame: trackData.firstKeyFrameTimestamp !== null
8063
8076
  });
8064
8077
  }
8065
8078
  if (trackData.encryptionAuxInfo && track.encryptionInfo) {
@@ -10374,7 +10387,8 @@ var Mediabunny = (() => {
10374
10387
  },
10375
10388
  timestampInTimescale,
10376
10389
  timestampInTimescale,
10377
- options
10390
+ options,
10391
+ true
10378
10392
  );
10379
10393
  }
10380
10394
  async getNextKeyPacket(packet, options) {
@@ -10521,10 +10535,8 @@ var Mediabunny = (() => {
10521
10535
  return packet;
10522
10536
  }
10523
10537
  /** Looks for a packet in the fragments while trying to load as few fragments as possible to retrieve it. */
10524
- async performFragmentedLookup(startFragment, getMatchInFragment, searchTimestamp, latestTimestamp, options, stopPos = Infinity, lookupRetryCount = 0) {
10525
- const demuxer = this.internalTrack.demuxer;
10526
- let currentFragment = null;
10527
- let precedingFragment = null;
10538
+ async performFragmentedLookup(startFragment, getMatchInFragment, searchTimestamp, latestTimestamp, options, requireKeyFrame = false) {
10539
+ const { demuxer, fragmentLookupTable, fragmentPositionCache } = this.internalTrack;
10528
10540
  let bestFragment = null;
10529
10541
  let bestSampleIndex = -1;
10530
10542
  if (startFragment) {
@@ -10537,89 +10549,88 @@ var Mediabunny = (() => {
10537
10549
  bestSampleIndex = sampleIndex;
10538
10550
  }
10539
10551
  }
10540
- const lookupEntryIndex = binarySearchLessOrEqual(
10541
- this.internalTrack.fragmentLookupTable,
10542
- searchTimestamp,
10543
- (x) => x.timestamp
10544
- );
10545
- const lookupEntry = lookupEntryIndex !== -1 ? this.internalTrack.fragmentLookupTable[lookupEntryIndex] : null;
10546
- const positionCacheIndex = binarySearchLessOrEqual(
10547
- this.internalTrack.fragmentPositionCache,
10548
- searchTimestamp,
10549
- (x) => x.startTimestamp
10550
- );
10551
- const positionCacheEntry = positionCacheIndex !== -1 ? this.internalTrack.fragmentPositionCache[positionCacheIndex] : null;
10552
- const lookupEntryPosition = Math.max(
10553
- lookupEntry?.moofOffset ?? 0,
10554
- positionCacheEntry?.moofOffset ?? 0
10555
- ) || null;
10556
- const lookupTableWins = !!lookupEntry && lookupEntry.moofOffset >= (positionCacheEntry?.moofOffset ?? 0);
10557
- let currentPos;
10558
- if (!startFragment) {
10559
- currentPos = lookupEntryPosition ?? 0;
10560
- } else {
10561
- if (lookupEntryPosition === null || startFragment.moofOffset >= lookupEntryPosition) {
10562
- currentPos = startFragment.moofOffset + startFragment.moofSize;
10563
- currentFragment = startFragment;
10552
+ let lookupEntryIndex = binarySearchLessOrEqual(fragmentLookupTable, searchTimestamp, (x) => x.timestamp);
10553
+ let positionCacheIndex = binarySearchLessOrEqual(fragmentPositionCache, searchTimestamp, (x) => x.startTimestamp);
10554
+ let stopPos = Infinity;
10555
+ while (true) {
10556
+ while (lookupEntryIndex !== -1 && fragmentLookupTable[lookupEntryIndex].moofOffset >= stopPos) {
10557
+ lookupEntryIndex--;
10558
+ }
10559
+ while (positionCacheIndex !== -1 && (fragmentPositionCache[positionCacheIndex].moofOffset >= stopPos || requireKeyFrame && !fragmentPositionCache[positionCacheIndex].hasKeyFrame)) {
10560
+ positionCacheIndex--;
10561
+ }
10562
+ const lookupEntryPosition = Math.max(
10563
+ fragmentLookupTable[lookupEntryIndex]?.moofOffset ?? 0,
10564
+ fragmentPositionCache[positionCacheIndex]?.moofOffset ?? 0
10565
+ ) || null;
10566
+ let currentPos;
10567
+ let currentFragment = null;
10568
+ let precedingFragment = null;
10569
+ let scanReachedFragment = false;
10570
+ if (!startFragment) {
10571
+ currentPos = lookupEntryPosition ?? 0;
10564
10572
  } else {
10565
- currentPos = lookupEntryPosition;
10573
+ if (lookupEntryPosition === null || startFragment.moofOffset >= lookupEntryPosition) {
10574
+ currentPos = startFragment.moofOffset + startFragment.moofSize;
10575
+ currentFragment = startFragment;
10576
+ } else {
10577
+ currentPos = lookupEntryPosition;
10578
+ }
10566
10579
  }
10567
- }
10568
- const scanStartPos = currentFragment ? currentFragment.moofOffset : currentPos;
10569
- let scanReachedFragment = false;
10570
- while (currentPos < stopPos) {
10571
- if (currentFragment) {
10572
- const trackData = currentFragment.trackData.get(this.internalTrack.id);
10573
- if (trackData && trackData.startTimestamp > latestTimestamp) {
10580
+ const scanStartPos = currentFragment ? currentFragment.moofOffset : currentPos;
10581
+ while (currentPos < stopPos) {
10582
+ if (currentFragment) {
10583
+ const trackData = currentFragment.trackData.get(this.internalTrack.id);
10584
+ if (trackData && trackData.startTimestamp > latestTimestamp) {
10585
+ break;
10586
+ }
10587
+ precedingFragment = currentFragment;
10588
+ currentFragment = null;
10589
+ }
10590
+ const summary = demuxer.fragmentSummaries.get(currentPos);
10591
+ if (summary && !summary.trackIds.has(this.internalTrack.id)) {
10592
+ currentPos += summary.moofSize;
10593
+ continue;
10594
+ }
10595
+ let slice = demuxer.reader.requestSliceRange(currentPos, MIN_BOX_HEADER_SIZE, MAX_BOX_HEADER_SIZE);
10596
+ if (isThenable(slice)) slice = await slice;
10597
+ if (!slice) break;
10598
+ const boxStartPos = currentPos;
10599
+ const boxInfo = readBoxHeader(slice);
10600
+ if (!boxInfo) {
10574
10601
  break;
10575
10602
  }
10576
- precedingFragment = currentFragment;
10577
- currentFragment = null;
10578
- }
10579
- const summary = demuxer.fragmentSummaries.get(currentPos);
10580
- if (summary && !summary.trackIds.has(this.internalTrack.id)) {
10581
- currentPos += summary.moofSize;
10582
- continue;
10603
+ if (boxInfo.name === "moof") {
10604
+ scanReachedFragment = true;
10605
+ currentFragment = await demuxer.readFragment(boxStartPos, precedingFragment);
10606
+ if (!currentFragment) {
10607
+ break;
10608
+ }
10609
+ const { sampleIndex, correctSampleFound } = getMatchInFragment(currentFragment);
10610
+ if (correctSampleFound) {
10611
+ return this.fetchPacketInFragment(currentFragment, sampleIndex, options);
10612
+ }
10613
+ if (sampleIndex !== -1) {
10614
+ bestFragment = currentFragment;
10615
+ bestSampleIndex = sampleIndex;
10616
+ }
10617
+ }
10618
+ currentPos = boxStartPos + boxInfo.totalSize;
10583
10619
  }
10584
- let slice = demuxer.reader.requestSliceRange(currentPos, MIN_BOX_HEADER_SIZE, MAX_BOX_HEADER_SIZE);
10585
- if (isThenable(slice)) slice = await slice;
10586
- if (!slice) break;
10587
- const boxStartPos = currentPos;
10588
- const boxInfo = readBoxHeader(slice);
10589
- if (!boxInfo) {
10620
+ if (lookupEntryPosition === null || bestFragment && bestFragment.moofOffset >= lookupEntryPosition) {
10590
10621
  break;
10591
10622
  }
10592
- if (boxInfo.name === "moof") {
10593
- scanReachedFragment = true;
10594
- currentFragment = await demuxer.readFragment(boxStartPos, precedingFragment);
10595
- if (!currentFragment) {
10596
- break;
10623
+ if (scanReachedFragment) {
10624
+ stopPos = scanStartPos;
10625
+ } else {
10626
+ if (fragmentLookupTable[lookupEntryIndex]?.moofOffset === lookupEntryPosition) {
10627
+ lookupEntryIndex--;
10597
10628
  }
10598
- const { sampleIndex, correctSampleFound } = getMatchInFragment(currentFragment);
10599
- if (correctSampleFound) {
10600
- return this.fetchPacketInFragment(currentFragment, sampleIndex, options);
10601
- }
10602
- if (sampleIndex !== -1) {
10603
- bestFragment = currentFragment;
10604
- bestSampleIndex = sampleIndex;
10605
- }
10606
- }
10607
- currentPos = boxStartPos + boxInfo.totalSize;
10608
- }
10609
- if (lookupEntryPosition !== null && (!bestFragment || bestFragment.moofOffset < lookupEntryPosition)) {
10610
- const step = 1 << lookupRetryCount;
10611
- const previousEntryTimestamp = lookupTableWins ? this.internalTrack.fragmentLookupTable[lookupEntryIndex - step]?.timestamp : this.internalTrack.fragmentPositionCache[positionCacheIndex - step]?.startTimestamp;
10612
- const newSearchTimestamp = previousEntryTimestamp ?? -Infinity;
10613
- return this.performFragmentedLookup(
10614
- null,
10615
- getMatchInFragment,
10616
- newSearchTimestamp,
10617
- latestTimestamp,
10618
- options,
10619
- // Only cap when the scan reached a fragment; capping a bogus offset hides the rest of the file
10620
- scanReachedFragment ? scanStartPos : stopPos,
10621
- lookupRetryCount + 1
10622
- );
10629
+ if (fragmentPositionCache[positionCacheIndex]?.moofOffset === lookupEntryPosition) {
10630
+ positionCacheIndex--;
10631
+ }
10632
+ }
10633
+ startFragment = null;
10623
10634
  }
10624
10635
  if (bestFragment) {
10625
10636
  return this.fetchPacketInFragment(bestFragment, bestSampleIndex, options);
@@ -12253,7 +12264,8 @@ var Mediabunny = (() => {
12253
12264
  if ((!previousEntry || previousEntry.elementStartPos < elementStartPos) && (!nextEntry || nextEntry.elementStartPos > elementStartPos)) {
12254
12265
  track.clusterPositionCache.splice(insertionIndex + 1, 0, {
12255
12266
  elementStartPos: cluster.elementStartPos,
12256
- startTimestamp: trackData.startTimestamp
12267
+ startTimestamp: trackData.startTimestamp,
12268
+ hasKeyFrame: trackData.firstKeyFrameTimestamp !== null
12257
12269
  });
12258
12270
  }
12259
12271
  }
@@ -13747,7 +13759,8 @@ var Mediabunny = (() => {
13747
13759
  },
13748
13760
  timestampInTimescale,
13749
13761
  timestampInTimescale,
13750
- options
13762
+ options,
13763
+ true
13751
13764
  );
13752
13765
  }
13753
13766
  async getNextKeyPacket(packet, options) {
@@ -13840,9 +13853,8 @@ var Mediabunny = (() => {
13840
13853
  return packet;
13841
13854
  }
13842
13855
  /** Looks for a packet in the clusters while trying to load as few clusters as possible to retrieve it. */
13843
- async performClusterLookup(startCluster, getMatchInCluster, searchTimestamp, latestTimestamp, options, stopPos = Infinity, lookupRetryCount = 0) {
13844
- const { demuxer, segment } = this.internalTrack;
13845
- let currentCluster = null;
13856
+ async performClusterLookup(startCluster, getMatchInCluster, searchTimestamp, latestTimestamp, options, requireKeyFrame = false) {
13857
+ const { demuxer, segment, cuePoints, clusterPositionCache } = this.internalTrack;
13846
13858
  let bestCluster = null;
13847
13859
  let bestBlockIndex = -1;
13848
13860
  if (startCluster) {
@@ -13855,119 +13867,108 @@ var Mediabunny = (() => {
13855
13867
  bestBlockIndex = blockIndex;
13856
13868
  }
13857
13869
  }
13858
- const cuePointIndex = binarySearchLessOrEqual(
13859
- this.internalTrack.cuePoints,
13860
- searchTimestamp,
13861
- (x) => x.time
13862
- );
13863
- const cuePoint = cuePointIndex !== -1 ? this.internalTrack.cuePoints[cuePointIndex] : null;
13864
- const positionCacheIndex = binarySearchLessOrEqual(
13865
- this.internalTrack.clusterPositionCache,
13866
- searchTimestamp,
13867
- (x) => x.startTimestamp
13868
- );
13869
- const positionCacheEntry = positionCacheIndex !== -1 ? this.internalTrack.clusterPositionCache[positionCacheIndex] : null;
13870
- const lookupEntryPosition = Math.max(
13871
- cuePoint?.clusterPosition ?? 0,
13872
- positionCacheEntry?.elementStartPos ?? 0
13873
- ) || null;
13874
- const cuePointWins = !!cuePoint && cuePoint.clusterPosition >= (positionCacheEntry?.elementStartPos ?? 0);
13875
- let currentPos;
13876
- if (!startCluster) {
13877
- currentPos = lookupEntryPosition ?? segment.clusterSeekStartPos;
13878
- } else {
13879
- if (lookupEntryPosition === null || startCluster.elementStartPos >= lookupEntryPosition) {
13880
- currentPos = startCluster.elementEndPos;
13881
- currentCluster = startCluster;
13870
+ let cuePointIndex = binarySearchLessOrEqual(cuePoints, searchTimestamp, (x) => x.time);
13871
+ let positionCacheIndex = binarySearchLessOrEqual(clusterPositionCache, searchTimestamp, (x) => x.startTimestamp);
13872
+ let stopPos = Infinity;
13873
+ while (true) {
13874
+ while (cuePointIndex !== -1 && cuePoints[cuePointIndex].clusterPosition >= stopPos) {
13875
+ cuePointIndex--;
13876
+ }
13877
+ while (positionCacheIndex !== -1 && (clusterPositionCache[positionCacheIndex].elementStartPos >= stopPos || requireKeyFrame && !clusterPositionCache[positionCacheIndex].hasKeyFrame)) {
13878
+ positionCacheIndex--;
13879
+ }
13880
+ const lookupEntryPosition = Math.max(
13881
+ cuePoints[cuePointIndex]?.clusterPosition ?? 0,
13882
+ clusterPositionCache[positionCacheIndex]?.elementStartPos ?? 0
13883
+ ) || null;
13884
+ let currentPos;
13885
+ let currentCluster = null;
13886
+ if (!startCluster) {
13887
+ currentPos = lookupEntryPosition ?? segment.clusterSeekStartPos;
13882
13888
  } else {
13883
- currentPos = lookupEntryPosition;
13884
- }
13885
- }
13886
- const scanStartPos = currentCluster ? currentCluster.elementStartPos : currentPos;
13887
- while ((segment.elementEndPos === null || currentPos <= segment.elementEndPos - MIN_HEADER_SIZE) && currentPos < stopPos) {
13888
- if (currentCluster) {
13889
- const trackData = currentCluster.trackData.get(this.internalTrack.id);
13890
- if (trackData && trackData.startTimestamp > latestTimestamp) {
13891
- break;
13889
+ if (lookupEntryPosition === null || startCluster.elementStartPos >= lookupEntryPosition) {
13890
+ currentPos = startCluster.elementEndPos;
13891
+ currentCluster = startCluster;
13892
+ } else {
13893
+ currentPos = lookupEntryPosition;
13892
13894
  }
13893
- currentCluster = null;
13894
13895
  }
13895
- const summary = segment.clusterSummaries.get(currentPos);
13896
- if (summary && !summary.trackIds.has(this.internalTrack.id)) {
13897
- currentPos = summary.elementEndPos;
13898
- continue;
13899
- }
13900
- let slice = demuxer.reader.requestSliceRange(currentPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
13901
- if (isThenable(slice)) slice = await slice;
13902
- if (!slice) break;
13903
- const elementStartPos = currentPos;
13904
- const elementHeader = readElementHeader(slice);
13905
- if (!elementHeader || !LEVEL_1_EBML_IDS.includes(elementHeader.id) && elementHeader.id !== 236 /* Void */) {
13906
- const nextPos = await resync(
13907
- demuxer.reader,
13908
- elementStartPos + 1,
13909
- LEVEL_1_EBML_IDS,
13910
- Math.min(segment.elementEndPos ?? Infinity, elementStartPos + MAX_RESYNC_LENGTH)
13911
- );
13912
- if (nextPos) {
13913
- currentPos = nextPos;
13896
+ const scanStartPos = currentCluster ? currentCluster.elementStartPos : currentPos;
13897
+ while ((segment.elementEndPos === null || currentPos <= segment.elementEndPos - MIN_HEADER_SIZE) && currentPos < stopPos) {
13898
+ if (currentCluster) {
13899
+ const trackData = currentCluster.trackData.get(this.internalTrack.id);
13900
+ if (trackData && trackData.startTimestamp > latestTimestamp) {
13901
+ break;
13902
+ }
13903
+ currentCluster = null;
13904
+ }
13905
+ const summary = segment.clusterSummaries.get(currentPos);
13906
+ if (summary && !summary.trackIds.has(this.internalTrack.id)) {
13907
+ currentPos = summary.elementEndPos;
13914
13908
  continue;
13915
- } else {
13916
- break;
13917
13909
  }
13918
- }
13919
- const id = elementHeader.id;
13920
- let size = elementHeader.size;
13921
- const dataStartPos = slice.filePos;
13922
- if (id === 524531317 /* Cluster */) {
13923
- currentCluster = await demuxer.readCluster(elementStartPos, segment);
13924
- size = currentCluster.elementEndPos - dataStartPos;
13925
- const { blockIndex, correctBlockFound } = getMatchInCluster(currentCluster);
13926
- if (correctBlockFound) {
13927
- return this.fetchPacketInCluster(currentCluster, blockIndex, options);
13910
+ let slice = demuxer.reader.requestSliceRange(currentPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
13911
+ if (isThenable(slice)) slice = await slice;
13912
+ if (!slice) break;
13913
+ const elementStartPos = currentPos;
13914
+ const elementHeader = readElementHeader(slice);
13915
+ if (!elementHeader || !LEVEL_1_EBML_IDS.includes(elementHeader.id) && elementHeader.id !== 236 /* Void */) {
13916
+ const nextPos = await resync(
13917
+ demuxer.reader,
13918
+ elementStartPos + 1,
13919
+ LEVEL_1_EBML_IDS,
13920
+ Math.min(segment.elementEndPos ?? Infinity, elementStartPos + MAX_RESYNC_LENGTH)
13921
+ );
13922
+ if (nextPos) {
13923
+ currentPos = nextPos;
13924
+ continue;
13925
+ } else {
13926
+ break;
13927
+ }
13928
13928
  }
13929
- if (blockIndex !== -1) {
13930
- bestCluster = currentCluster;
13931
- bestBlockIndex = blockIndex;
13929
+ const id = elementHeader.id;
13930
+ let size = elementHeader.size;
13931
+ const dataStartPos = slice.filePos;
13932
+ if (id === 524531317 /* Cluster */) {
13933
+ currentCluster = await demuxer.readCluster(elementStartPos, segment);
13934
+ size = currentCluster.elementEndPos - dataStartPos;
13935
+ const { blockIndex, correctBlockFound } = getMatchInCluster(currentCluster);
13936
+ if (correctBlockFound) {
13937
+ return this.fetchPacketInCluster(currentCluster, blockIndex, options);
13938
+ }
13939
+ if (blockIndex !== -1) {
13940
+ bestCluster = currentCluster;
13941
+ bestBlockIndex = blockIndex;
13942
+ }
13943
+ }
13944
+ if (size === void 0) {
13945
+ assert(id !== 524531317 /* Cluster */);
13946
+ const nextElementPos = await searchForNextElementId(
13947
+ demuxer.reader,
13948
+ dataStartPos,
13949
+ LEVEL_0_AND_1_EBML_IDS,
13950
+ segment.elementEndPos
13951
+ );
13952
+ size = nextElementPos.pos - dataStartPos;
13932
13953
  }
13933
- }
13934
- if (size === void 0) {
13935
- assert(id !== 524531317 /* Cluster */);
13936
- const nextElementPos = await searchForNextElementId(
13937
- demuxer.reader,
13938
- dataStartPos,
13939
- LEVEL_0_AND_1_EBML_IDS,
13940
- segment.elementEndPos
13941
- );
13942
- size = nextElementPos.pos - dataStartPos;
13943
- }
13944
- const endPos = dataStartPos + size;
13945
- if (segment.elementEndPos === null) {
13946
- let slice2 = demuxer.reader.requestSliceRange(endPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
13947
- if (isThenable(slice2)) slice2 = await slice2;
13948
- if (!slice2) break;
13949
- const elementId = readElementId(slice2);
13950
- if (elementId === 408125543 /* Segment */) {
13951
- segment.elementEndPos = endPos;
13952
- break;
13954
+ const endPos = dataStartPos + size;
13955
+ if (segment.elementEndPos === null) {
13956
+ let slice2 = demuxer.reader.requestSliceRange(endPos, MIN_HEADER_SIZE, MAX_HEADER_SIZE);
13957
+ if (isThenable(slice2)) slice2 = await slice2;
13958
+ if (!slice2) break;
13959
+ const elementId = readElementId(slice2);
13960
+ if (elementId === 408125543 /* Segment */) {
13961
+ segment.elementEndPos = endPos;
13962
+ break;
13963
+ }
13953
13964
  }
13965
+ currentPos = endPos;
13954
13966
  }
13955
- currentPos = endPos;
13956
- }
13957
- if (lookupEntryPosition !== null && (!bestCluster || bestCluster.elementStartPos < lookupEntryPosition)) {
13958
- const step = 1 << lookupRetryCount;
13959
- const previousEntryTimestamp = cuePointWins ? this.internalTrack.cuePoints[cuePointIndex - step]?.time : this.internalTrack.clusterPositionCache[positionCacheIndex - step]?.startTimestamp;
13960
- const newSearchTimestamp = previousEntryTimestamp ?? -Infinity;
13961
- return this.performClusterLookup(
13962
- null,
13963
- getMatchInCluster,
13964
- newSearchTimestamp,
13965
- latestTimestamp,
13966
- options,
13967
- scanStartPos,
13968
- // So we don't read the same clusters again
13969
- lookupRetryCount + 1
13970
- );
13967
+ if (lookupEntryPosition === null || bestCluster && bestCluster.elementStartPos >= lookupEntryPosition) {
13968
+ break;
13969
+ }
13970
+ stopPos = scanStartPos;
13971
+ startCluster = null;
13971
13972
  }
13972
13973
  if (bestCluster) {
13973
13974
  return this.fetchPacketInCluster(bestCluster, bestBlockIndex, options);
@@ -40726,7 +40727,7 @@ var Mediabunny = (() => {
40726
40727
  const uniqueSampleSizes = new Set(allSampleSizes);
40727
40728
  const uniqueSampleFlags = new Set(allSampleFlags);
40728
40729
  const uniqueSampleCompositionTimeOffsets = new Set(allSampleCompositionTimeOffsets);
40729
- const firstSampleFlagsPresent = uniqueSampleFlags.size === 2 && allSampleFlags[0] !== allSampleFlags[1];
40730
+ const firstSampleFlagsPresent = uniqueSampleFlags.size === 2 && findLastIndex(allSampleFlags, (x) => x === allSampleFlags[0]) === 0;
40730
40731
  const sampleDurationPresent = uniqueSampleDurations.size > 1;
40731
40732
  const sampleSizePresent = uniqueSampleSizes.size > 1;
40732
40733
  const sampleFlagsPresent = !firstSampleFlagsPresent && uniqueSampleFlags.size > 1;