@remotion/media-parser 4.0.333 → 4.0.334

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.
@@ -11,7 +11,6 @@ const may_skip_video_data_1 = require("../../../state/may-skip-video-data");
11
11
  const video_section_1 = require("../../../state/video-section");
12
12
  const webcodecs_timescale_1 = require("../../../webcodecs-timescale");
13
13
  const get_moov_atom_1 = require("../get-moov-atom");
14
- const calculate_jump_marks_1 = require("./calculate-jump-marks");
15
14
  const postprocess_bytes_1 = require("./postprocess-bytes");
16
15
  const parseMdatSection = async (state) => {
17
16
  const mediaSection = (0, video_section_1.getCurrentMediaSection)({
@@ -57,63 +56,60 @@ const parseMdatSection = async (state) => {
57
56
  endOfMdat,
58
57
  state,
59
58
  });
59
+ const tracksFromMoov = (0, get_tracks_1.getTracksFromMoovBox)(moov);
60
60
  state.iso.moov.setMoovBox({
61
61
  moovBox: moov,
62
62
  precomputed: false,
63
63
  });
64
+ const existingTracks = state.callbacks.tracks.getTracks();
65
+ for (const trackFromMoov of tracksFromMoov) {
66
+ if (existingTracks.find((t) => t.trackId === trackFromMoov.trackId)) {
67
+ continue;
68
+ }
69
+ if (trackFromMoov.type === 'other') {
70
+ continue;
71
+ }
72
+ state.callbacks.tracks.addTrack(trackFromMoov);
73
+ }
64
74
  state.callbacks.tracks.setIsDone(state.logLevel);
65
75
  state.structure.getIsoStructure().boxes.push(moov);
66
76
  return (0, exports.parseMdatSection)(state);
67
77
  }
78
+ const tracks = state.callbacks.tracks.getTracks();
68
79
  if (!state.iso.flatSamples.getSamples(mediaSection.start)) {
69
- const { flatSamples: flatSamplesMap, offsets, trackIds, } = (0, cached_sample_positions_1.calculateFlatSamples)({
80
+ const samplePosition = (0, cached_sample_positions_1.calculateSamplePositions)({
70
81
  state,
71
82
  mediaSectionStart: mediaSection.start,
83
+ trackIds: tracks.map((t) => t.trackId),
72
84
  });
73
- const calcedJumpMarks = (0, calculate_jump_marks_1.calculateJumpMarks)({
74
- sampleMap: flatSamplesMap,
75
- offsetsSorted: offsets,
76
- trackIds,
77
- endOfMdat,
78
- });
79
- state.iso.flatSamples.setJumpMarks(mediaSection.start, calcedJumpMarks);
80
- state.iso.flatSamples.setSamples(mediaSection.start, flatSamplesMap);
85
+ state.iso.flatSamples.setSamples(mediaSection.start, samplePosition);
81
86
  }
82
- const flatSamples = state.iso.flatSamples.getSamples(mediaSection.start);
83
- const jumpMarks = state.iso.flatSamples.getJumpMarks(mediaSection.start);
84
- const { iterator } = state;
85
- const samplesWithIndex = flatSamples.get(iterator.counter.getOffset());
86
- if (!samplesWithIndex) {
87
- // There are various reasons why in mdat we find weird stuff:
88
- // - iphonevideo.hevc has a fake hoov atom which is not mapped
89
- // - corrupted.mp4 has a corrupt table
90
- const offsets = Array.from(flatSamples.keys());
91
- const nextSample_ = offsets
92
- .filter((s) => s > iterator.counter.getOffset())
93
- .sort((a, b) => a - b)[0];
94
- if (nextSample_) {
95
- iterator.discard(nextSample_ - iterator.counter.getOffset());
96
- return null;
97
- }
98
- // guess we reached the end!
99
- // iphonevideo.mov has extra padding here, so let's make sure to jump ahead
100
- log_1.Log.verbose(state.logLevel, 'Could not find sample at offset', iterator.counter.getOffset(), 'skipping to end of mdat');
87
+ const samplePositions = state.iso.flatSamples.getSamples(mediaSection.start);
88
+ const sampleIndices = state.iso.flatSamples.getCurrentSampleIndices(mediaSection.start);
89
+ const nextSampleArray = (0, cached_sample_positions_1.getSampleWithLowestDts)(samplePositions, sampleIndices);
90
+ if (nextSampleArray.length === 0) {
91
+ log_1.Log.verbose(state.logLevel, 'Iterated over all samples.', endOfMdat);
101
92
  return (0, skip_1.makeSkip)(endOfMdat);
102
93
  }
94
+ const exactMatch = nextSampleArray.find((s) => s.samplePosition.offset === state.iterator.counter.getOffset());
95
+ const nextSample = exactMatch !== null && exactMatch !== void 0 ? exactMatch : nextSampleArray[0];
96
+ if (nextSample.samplePosition.offset !== state.iterator.counter.getOffset()) {
97
+ return (0, skip_1.makeSkip)(nextSample.samplePosition.offset);
98
+ }
103
99
  // Corrupt file: Sample is beyond the end of the file. Don't process it.
104
- if (samplesWithIndex.samplePosition.offset +
105
- samplesWithIndex.samplePosition.size >
100
+ if (nextSample.samplePosition.offset + nextSample.samplePosition.size >
106
101
  state.contentLength) {
107
- log_1.Log.verbose(state.logLevel, "Sample is beyond the end of the file. Don't process it.", samplesWithIndex.samplePosition.offset +
108
- samplesWithIndex.samplePosition.size, endOfMdat);
102
+ log_1.Log.verbose(state.logLevel, "Sample is beyond the end of the file. Don't process it.", nextSample.samplePosition.offset + nextSample.samplePosition.size, endOfMdat);
109
103
  return (0, skip_1.makeSkip)(endOfMdat);
110
104
  }
105
+ const { iterator } = state;
111
106
  // Need to fetch more data
112
- if (iterator.bytesRemaining() < samplesWithIndex.samplePosition.size) {
113
- return (0, skip_1.makeFetchMoreData)(samplesWithIndex.samplePosition.size - iterator.bytesRemaining());
107
+ if (iterator.bytesRemaining() < nextSample.samplePosition.size) {
108
+ return (0, skip_1.makeFetchMoreData)(nextSample.samplePosition.size - iterator.bytesRemaining());
114
109
  }
115
- const { timestamp: rawCts, decodingTimestamp: rawDts, duration, isKeyframe, offset, bigEndian, chunkSize, } = samplesWithIndex.samplePosition;
116
- const { originalTimescale, startInSeconds, trackMediaTimeOffsetInTrackTimescale, timescale: trackTimescale, } = samplesWithIndex.track;
110
+ const { timestamp: rawCts, decodingTimestamp: rawDts, duration, isKeyframe, offset, bigEndian, chunkSize, } = nextSample.samplePosition;
111
+ const track = tracks.find((t) => t.trackId === nextSample.trackId);
112
+ const { originalTimescale, startInSeconds, trackMediaTimeOffsetInTrackTimescale, timescale: trackTimescale, } = track;
117
113
  const cts = rawCts +
118
114
  startInSeconds * originalTimescale -
119
115
  (trackMediaTimeOffsetInTrackTimescale / trackTimescale) *
@@ -123,11 +119,11 @@ const parseMdatSection = async (state) => {
123
119
  (trackMediaTimeOffsetInTrackTimescale / trackTimescale) *
124
120
  webcodecs_timescale_1.WEBCODECS_TIMESCALE;
125
121
  const bytes = (0, postprocess_bytes_1.postprocessBytes)({
126
- bytes: iterator.getSlice(samplesWithIndex.samplePosition.size),
122
+ bytes: iterator.getSlice(nextSample.samplePosition.size),
127
123
  bigEndian,
128
124
  chunkSize,
129
125
  });
130
- if (samplesWithIndex.track.type === 'audio') {
126
+ if (track.type === 'audio') {
131
127
  const audioSample = (0, convert_audio_or_video_sample_1.convertAudioOrVideoSampleToWebCodecsTimestamps)({
132
128
  sample: {
133
129
  data: bytes,
@@ -141,10 +137,10 @@ const parseMdatSection = async (state) => {
141
137
  });
142
138
  await state.callbacks.onAudioSample({
143
139
  audioSample,
144
- trackId: samplesWithIndex.track.trackId,
140
+ trackId: track.trackId,
145
141
  });
146
142
  }
147
- if (samplesWithIndex.track.type === 'video') {
143
+ if (track.type === 'video') {
148
144
  // https://pub-646d808d9cb240cea53bedc76dd3cd0c.r2.dev/sei_checkpoint.mp4
149
145
  // Position in file 0x0001aba615
150
146
  // https://github.com/remotion-dev/remotion/issues/4680
@@ -170,14 +166,10 @@ const parseMdatSection = async (state) => {
170
166
  });
171
167
  await state.callbacks.onVideoSample({
172
168
  videoSample,
173
- trackId: samplesWithIndex.track.trackId,
169
+ trackId: track.trackId,
174
170
  });
175
171
  }
176
- const jump = jumpMarks.find((j) => j.afterSampleWithOffset === offset);
177
- if (jump) {
178
- log_1.Log.verbose(state.logLevel, 'Found jump mark', jump.jumpToOffset, 'skipping to jump mark');
179
- return (0, skip_1.makeSkip)(jump.jumpToOffset);
180
- }
172
+ state.iso.flatSamples.setCurrentSampleIndex(mediaSection.start, nextSample.trackId, nextSample.index + 1);
181
173
  return null;
182
174
  };
183
175
  exports.parseMdatSection = parseMdatSection;
@@ -10035,7 +10035,8 @@ var performSeek = async ({
10035
10035
  src,
10036
10036
  discardReadBytes,
10037
10037
  fields,
10038
- prefetchCache
10038
+ prefetchCache,
10039
+ isoState
10039
10040
  }) => {
10040
10041
  const byteInMediaSection = isByteInMediaSection({
10041
10042
  position: seekTo,
@@ -10099,6 +10100,9 @@ var performSeek = async ({
10099
10100
  prefetchCache
10100
10101
  });
10101
10102
  }
10103
+ if (userInitiated) {
10104
+ isoState.flatSamples.updateAfterSeek(seekTo);
10105
+ }
10102
10106
  await controller._internals.checkForAbortAndPause();
10103
10107
  };
10104
10108
 
@@ -10277,7 +10281,8 @@ var workOnSeekRequest = async (options) => {
10277
10281
  src,
10278
10282
  discardReadBytes,
10279
10283
  fields,
10280
- prefetchCache
10284
+ prefetchCache,
10285
+ isoState
10281
10286
  });
10282
10287
  return;
10283
10288
  }
@@ -10297,7 +10302,8 @@ var workOnSeekRequest = async (options) => {
10297
10302
  src,
10298
10303
  discardReadBytes,
10299
10304
  fields,
10300
- prefetchCache
10305
+ prefetchCache,
10306
+ isoState
10301
10307
  });
10302
10308
  const { hasChanged } = controller._internals.seekSignal.clearSeekIfStillSame(seek2);
10303
10309
  if (hasChanged) {
@@ -11397,9 +11403,10 @@ var parseFlac = ({
11397
11403
  };
11398
11404
 
11399
11405
  // src/state/iso-base-media/cached-sample-positions.ts
11400
- var calculateFlatSamples = ({
11406
+ var calculateSamplePositions = ({
11401
11407
  state,
11402
- mediaSectionStart
11408
+ mediaSectionStart,
11409
+ trackIds
11403
11410
  }) => {
11404
11411
  const tracks2 = getTracks(state, true);
11405
11412
  const moofBoxes = getMoofBoxes(state.structure.getIsoStructure().boxes);
@@ -11421,11 +11428,13 @@ var calculateFlatSamples = ({
11421
11428
  if (!moov) {
11422
11429
  throw new Error("No moov box found");
11423
11430
  }
11424
- const offsets = [];
11425
- const trackIds = [];
11426
- const map = new Map;
11431
+ const trackIdAndSamplePositions = [];
11427
11432
  for (const track of tracks2) {
11428
11433
  const trakBox = getTrakBoxByTrackId(moov, track.trackId);
11434
+ if (!trackIds.includes(track.trackId)) {
11435
+ Log.verbose(state.logLevel, "Skipping calculating sample positions for track", track.trackId);
11436
+ continue;
11437
+ }
11429
11438
  if (!trakBox) {
11430
11439
  throw new Error("No trak box found");
11431
11440
  }
@@ -11435,36 +11444,88 @@ var calculateFlatSamples = ({
11435
11444
  moofComplete,
11436
11445
  trexBoxes: getTrexBoxes(moov)
11437
11446
  });
11438
- trackIds.push(track.trackId);
11439
- for (const samplePosition of samplePositions) {
11440
- offsets.push(samplePosition.offset);
11441
- map.set(samplePosition.offset, {
11442
- track,
11443
- samplePosition
11444
- });
11447
+ trackIdAndSamplePositions.push({
11448
+ trackId: track.trackId,
11449
+ samplePositions
11450
+ });
11451
+ }
11452
+ return trackIdAndSamplePositions;
11453
+ };
11454
+ var updateSampleIndicesAfterSeek = ({
11455
+ samplePositionsForMdatStart,
11456
+ seekedByte
11457
+ }) => {
11458
+ const currentSampleIndices = {};
11459
+ const keys = Object.keys(samplePositionsForMdatStart).map(Number).sort();
11460
+ const mdat = keys.find((key) => seekedByte >= key);
11461
+ if (!mdat) {
11462
+ return currentSampleIndices;
11463
+ }
11464
+ const samplePositions = samplePositionsForMdatStart[mdat];
11465
+ if (!samplePositions) {
11466
+ return currentSampleIndices;
11467
+ }
11468
+ for (const track of samplePositions) {
11469
+ const currentSampleIndex = track.samplePositions.findIndex((sample) => sample.offset >= seekedByte);
11470
+ if (!currentSampleIndices[mdat]) {
11471
+ currentSampleIndices[mdat] = {};
11472
+ }
11473
+ if (!currentSampleIndices[mdat][track.trackId]) {
11474
+ currentSampleIndices[mdat][track.trackId] = 0;
11475
+ }
11476
+ if (currentSampleIndex === -1) {
11477
+ currentSampleIndices[mdat][track.trackId] = track.samplePositions.length;
11478
+ } else {
11479
+ currentSampleIndices[mdat][track.trackId] = currentSampleIndex;
11445
11480
  }
11446
11481
  }
11447
- offsets.sort((a, b) => a - b);
11448
- return { flatSamples: map, offsets, trackIds };
11482
+ return currentSampleIndices;
11449
11483
  };
11450
11484
  var cachedSamplePositionsState = () => {
11451
- const cachedForMdatStart = {};
11452
- const jumpMarksForMdatStart = {};
11485
+ const samplePositionsForMdatStart = {};
11486
+ let currentSampleIndex = {};
11453
11487
  return {
11454
11488
  getSamples: (mdatStart) => {
11455
- return cachedForMdatStart[mdatStart] ?? null;
11489
+ return samplePositionsForMdatStart[mdatStart] ?? null;
11456
11490
  },
11457
11491
  setSamples: (mdatStart, samples) => {
11458
- cachedForMdatStart[mdatStart] = samples;
11492
+ samplePositionsForMdatStart[mdatStart] = samples;
11459
11493
  },
11460
- setJumpMarks: (mdatStart, marks) => {
11461
- jumpMarksForMdatStart[mdatStart] = marks;
11494
+ setCurrentSampleIndex: (mdatStart, trackId, index) => {
11495
+ if (!currentSampleIndex[mdatStart]) {
11496
+ currentSampleIndex[mdatStart] = {};
11497
+ }
11498
+ if (!currentSampleIndex[mdatStart][trackId]) {
11499
+ currentSampleIndex[mdatStart][trackId] = 0;
11500
+ }
11501
+ currentSampleIndex[mdatStart][trackId] = index;
11462
11502
  },
11463
- getJumpMarks: (mdatStart) => {
11464
- return jumpMarksForMdatStart[mdatStart];
11503
+ getCurrentSampleIndices: (mdatStart) => {
11504
+ return currentSampleIndex[mdatStart] ?? {};
11505
+ },
11506
+ updateAfterSeek: (seekedByte) => {
11507
+ currentSampleIndex = updateSampleIndicesAfterSeek({
11508
+ samplePositionsForMdatStart,
11509
+ seekedByte
11510
+ });
11465
11511
  }
11466
11512
  };
11467
11513
  };
11514
+ var getSampleWithLowestDts = (samplePositions, currentSampleIndexMap) => {
11515
+ const lowestDts = [];
11516
+ for (const track of samplePositions) {
11517
+ const currentSampleIndex = currentSampleIndexMap[track.trackId] ?? 0;
11518
+ const currentSample = track.samplePositions[currentSampleIndex];
11519
+ if (currentSample && (lowestDts.length === 0 || currentSample.decodingTimestamp <= lowestDts[0].samplePosition.decodingTimestamp)) {
11520
+ lowestDts.push({
11521
+ samplePosition: currentSample,
11522
+ trackId: track.trackId,
11523
+ index: currentSampleIndex
11524
+ });
11525
+ }
11526
+ }
11527
+ return lowestDts;
11528
+ };
11468
11529
 
11469
11530
  // src/state/iso-base-media/last-moof-box.ts
11470
11531
  var getLastMoofBox = (boxes) => {
@@ -11745,118 +11806,6 @@ var getMoovAtom = async ({
11745
11806
  return moov;
11746
11807
  };
11747
11808
 
11748
- // src/containers/iso-base-media/mdat/calculate-jump-marks.ts
11749
- var MAX_SPREAD_IN_SECONDS = 8;
11750
- var getKey = (samplePositionTrack) => {
11751
- return `${samplePositionTrack.track.trackId}-${samplePositionTrack.samplePosition.decodingTimestamp}.${samplePositionTrack.samplePosition.offset}`;
11752
- };
11753
- var findBestJump = ({
11754
- sampleMap,
11755
- offsetsSorted,
11756
- visited,
11757
- progresses
11758
- }) => {
11759
- const minProgress = Math.min(...Object.values(progresses));
11760
- const trackNumberWithLowestProgress = Object.entries(progresses).find(([, progress]) => progress === minProgress)?.[0];
11761
- const firstSampleAboveMinProgress = offsetsSorted.findIndex((offset) => sampleMap.get(offset).track.trackId === Number(trackNumberWithLowestProgress) && !visited.has(getKey(sampleMap.get(offset))));
11762
- if (firstSampleAboveMinProgress === -1) {
11763
- const backup = offsetsSorted.findIndex((offset) => !visited.has(getKey(sampleMap.get(offset))));
11764
- if (backup === -1) {
11765
- throw new Error("this should not happen");
11766
- }
11767
- return backup;
11768
- }
11769
- return firstSampleAboveMinProgress;
11770
- };
11771
- var calculateJumpMarks = ({
11772
- sampleMap,
11773
- offsetsSorted,
11774
- trackIds,
11775
- endOfMdat
11776
- }) => {
11777
- const progresses = {};
11778
- for (const trackId of trackIds) {
11779
- progresses[trackId] = 0;
11780
- }
11781
- const jumpMarks = [];
11782
- let indexToVisit = 0;
11783
- const visited = new Set;
11784
- const increaseIndex = () => {
11785
- indexToVisit++;
11786
- if (indexToVisit >= offsetsSorted.length) {
11787
- throw new Error("should not roll over, should jump");
11788
- }
11789
- };
11790
- let lastVisitedSample = null;
11791
- const addJumpMark = ({
11792
- firstSampleAboveMinProgress
11793
- }) => {
11794
- if (!lastVisitedSample) {
11795
- throw new Error("no last visited sample");
11796
- }
11797
- const jumpMark = {
11798
- afterSampleWithOffset: lastVisitedSample.samplePosition.offset,
11799
- jumpToOffset: offsetsSorted[firstSampleAboveMinProgress]
11800
- };
11801
- if (firstSampleAboveMinProgress === offsetsSorted.indexOf(lastVisitedSample.samplePosition.offset) + 1) {
11802
- indexToVisit = firstSampleAboveMinProgress;
11803
- return;
11804
- }
11805
- indexToVisit = firstSampleAboveMinProgress;
11806
- jumpMarks.push(jumpMark);
11807
- };
11808
- const addFinalJumpIfNecessary = () => {
11809
- if (indexToVisit === offsetsSorted.length - 1) {
11810
- return;
11811
- }
11812
- jumpMarks.push({
11813
- afterSampleWithOffset: offsetsSorted[indexToVisit],
11814
- jumpToOffset: endOfMdat
11815
- });
11816
- };
11817
- const considerJump = () => {
11818
- const firstSampleAboveMinProgress = findBestJump({
11819
- sampleMap,
11820
- offsetsSorted,
11821
- visited,
11822
- progresses
11823
- });
11824
- addJumpMark({ firstSampleAboveMinProgress });
11825
- };
11826
- while (true) {
11827
- const currentSamplePosition = sampleMap.get(offsetsSorted[indexToVisit]);
11828
- const sampleKey = getKey(currentSamplePosition);
11829
- if (visited.has(sampleKey)) {
11830
- considerJump();
11831
- continue;
11832
- }
11833
- visited.add(sampleKey);
11834
- lastVisitedSample = currentSamplePosition;
11835
- if (visited.size === offsetsSorted.length) {
11836
- addFinalJumpIfNecessary();
11837
- break;
11838
- }
11839
- const timestamp = currentSamplePosition.samplePosition.decodingTimestamp / currentSamplePosition.track.originalTimescale;
11840
- progresses[currentSamplePosition.track.trackId] = timestamp;
11841
- const progressValues = Object.values(progresses);
11842
- const maxProgress = Math.max(...progressValues);
11843
- const minProgress = Math.min(...progressValues);
11844
- const spread = maxProgress - minProgress;
11845
- if (visited.size === offsetsSorted.length) {
11846
- addFinalJumpIfNecessary();
11847
- break;
11848
- }
11849
- if (spread > MAX_SPREAD_IN_SECONDS) {
11850
- considerJump();
11851
- } else if (indexToVisit === offsetsSorted.length - 1) {
11852
- considerJump();
11853
- } else {
11854
- increaseIndex();
11855
- }
11856
- }
11857
- return jumpMarks;
11858
- };
11859
-
11860
11809
  // src/containers/iso-base-media/mdat/postprocess-bytes.ts
11861
11810
  var postprocessBytes = ({
11862
11811
  bytes,
@@ -11917,52 +11866,53 @@ var parseMdatSection = async (state) => {
11917
11866
  endOfMdat,
11918
11867
  state
11919
11868
  });
11869
+ const tracksFromMoov = getTracksFromMoovBox(moov);
11920
11870
  state.iso.moov.setMoovBox({
11921
11871
  moovBox: moov,
11922
11872
  precomputed: false
11923
11873
  });
11874
+ const existingTracks = state.callbacks.tracks.getTracks();
11875
+ for (const trackFromMoov of tracksFromMoov) {
11876
+ if (existingTracks.find((t) => t.trackId === trackFromMoov.trackId)) {
11877
+ continue;
11878
+ }
11879
+ if (trackFromMoov.type === "other") {
11880
+ continue;
11881
+ }
11882
+ state.callbacks.tracks.addTrack(trackFromMoov);
11883
+ }
11924
11884
  state.callbacks.tracks.setIsDone(state.logLevel);
11925
11885
  state.structure.getIsoStructure().boxes.push(moov);
11926
11886
  return parseMdatSection(state);
11927
11887
  }
11888
+ const tracks2 = state.callbacks.tracks.getTracks();
11928
11889
  if (!state.iso.flatSamples.getSamples(mediaSection.start)) {
11929
- const {
11930
- flatSamples: flatSamplesMap,
11931
- offsets,
11932
- trackIds
11933
- } = calculateFlatSamples({
11890
+ const samplePosition = calculateSamplePositions({
11934
11891
  state,
11935
- mediaSectionStart: mediaSection.start
11936
- });
11937
- const calcedJumpMarks = calculateJumpMarks({
11938
- sampleMap: flatSamplesMap,
11939
- offsetsSorted: offsets,
11940
- trackIds,
11941
- endOfMdat
11892
+ mediaSectionStart: mediaSection.start,
11893
+ trackIds: tracks2.map((t) => t.trackId)
11942
11894
  });
11943
- state.iso.flatSamples.setJumpMarks(mediaSection.start, calcedJumpMarks);
11944
- state.iso.flatSamples.setSamples(mediaSection.start, flatSamplesMap);
11895
+ state.iso.flatSamples.setSamples(mediaSection.start, samplePosition);
11945
11896
  }
11946
- const flatSamples = state.iso.flatSamples.getSamples(mediaSection.start);
11947
- const jumpMarks = state.iso.flatSamples.getJumpMarks(mediaSection.start);
11948
- const { iterator } = state;
11949
- const samplesWithIndex = flatSamples.get(iterator.counter.getOffset());
11950
- if (!samplesWithIndex) {
11951
- const offsets = Array.from(flatSamples.keys());
11952
- const nextSample_ = offsets.filter((s) => s > iterator.counter.getOffset()).sort((a, b) => a - b)[0];
11953
- if (nextSample_) {
11954
- iterator.discard(nextSample_ - iterator.counter.getOffset());
11955
- return null;
11956
- }
11957
- Log.verbose(state.logLevel, "Could not find sample at offset", iterator.counter.getOffset(), "skipping to end of mdat");
11897
+ const samplePositions = state.iso.flatSamples.getSamples(mediaSection.start);
11898
+ const sampleIndices = state.iso.flatSamples.getCurrentSampleIndices(mediaSection.start);
11899
+ const nextSampleArray = getSampleWithLowestDts(samplePositions, sampleIndices);
11900
+ if (nextSampleArray.length === 0) {
11901
+ Log.verbose(state.logLevel, "Iterated over all samples.", endOfMdat);
11958
11902
  return makeSkip(endOfMdat);
11959
11903
  }
11960
- if (samplesWithIndex.samplePosition.offset + samplesWithIndex.samplePosition.size > state.contentLength) {
11961
- Log.verbose(state.logLevel, "Sample is beyond the end of the file. Don't process it.", samplesWithIndex.samplePosition.offset + samplesWithIndex.samplePosition.size, endOfMdat);
11904
+ const exactMatch = nextSampleArray.find((s) => s.samplePosition.offset === state.iterator.counter.getOffset());
11905
+ const nextSample = exactMatch ?? nextSampleArray[0];
11906
+ if (nextSample.samplePosition.offset !== state.iterator.counter.getOffset()) {
11907
+ return makeSkip(nextSample.samplePosition.offset);
11908
+ }
11909
+ if (nextSample.samplePosition.offset + nextSample.samplePosition.size > state.contentLength) {
11910
+ Log.verbose(state.logLevel, "Sample is beyond the end of the file. Don't process it.", nextSample.samplePosition.offset + nextSample.samplePosition.size, endOfMdat);
11962
11911
  return makeSkip(endOfMdat);
11963
11912
  }
11964
- if (iterator.bytesRemaining() < samplesWithIndex.samplePosition.size) {
11965
- return makeFetchMoreData(samplesWithIndex.samplePosition.size - iterator.bytesRemaining());
11913
+ const { iterator } = state;
11914
+ if (iterator.bytesRemaining() < nextSample.samplePosition.size) {
11915
+ return makeFetchMoreData(nextSample.samplePosition.size - iterator.bytesRemaining());
11966
11916
  }
11967
11917
  const {
11968
11918
  timestamp: rawCts,
@@ -11972,21 +11922,22 @@ var parseMdatSection = async (state) => {
11972
11922
  offset,
11973
11923
  bigEndian,
11974
11924
  chunkSize
11975
- } = samplesWithIndex.samplePosition;
11925
+ } = nextSample.samplePosition;
11926
+ const track = tracks2.find((t) => t.trackId === nextSample.trackId);
11976
11927
  const {
11977
11928
  originalTimescale,
11978
11929
  startInSeconds,
11979
11930
  trackMediaTimeOffsetInTrackTimescale,
11980
11931
  timescale: trackTimescale
11981
- } = samplesWithIndex.track;
11932
+ } = track;
11982
11933
  const cts = rawCts + startInSeconds * originalTimescale - trackMediaTimeOffsetInTrackTimescale / trackTimescale * WEBCODECS_TIMESCALE;
11983
11934
  const dts = rawDts + startInSeconds * originalTimescale - trackMediaTimeOffsetInTrackTimescale / trackTimescale * WEBCODECS_TIMESCALE;
11984
11935
  const bytes = postprocessBytes({
11985
- bytes: iterator.getSlice(samplesWithIndex.samplePosition.size),
11936
+ bytes: iterator.getSlice(nextSample.samplePosition.size),
11986
11937
  bigEndian,
11987
11938
  chunkSize
11988
11939
  });
11989
- if (samplesWithIndex.track.type === "audio") {
11940
+ if (track.type === "audio") {
11990
11941
  const audioSample = convertAudioOrVideoSampleToWebCodecsTimestamps({
11991
11942
  sample: {
11992
11943
  data: bytes,
@@ -12000,10 +11951,10 @@ var parseMdatSection = async (state) => {
12000
11951
  });
12001
11952
  await state.callbacks.onAudioSample({
12002
11953
  audioSample,
12003
- trackId: samplesWithIndex.track.trackId
11954
+ trackId: track.trackId
12004
11955
  });
12005
11956
  }
12006
- if (samplesWithIndex.track.type === "video") {
11957
+ if (track.type === "video") {
12007
11958
  const nalUnitType = bytes[4] & 31;
12008
11959
  let isRecoveryPoint = false;
12009
11960
  if (nalUnitType === 6) {
@@ -12023,14 +11974,10 @@ var parseMdatSection = async (state) => {
12023
11974
  });
12024
11975
  await state.callbacks.onVideoSample({
12025
11976
  videoSample,
12026
- trackId: samplesWithIndex.track.trackId
11977
+ trackId: track.trackId
12027
11978
  });
12028
11979
  }
12029
- const jump = jumpMarks.find((j) => j.afterSampleWithOffset === offset);
12030
- if (jump) {
12031
- Log.verbose(state.logLevel, "Found jump mark", jump.jumpToOffset, "skipping to jump mark");
12032
- return makeSkip(jump.jumpToOffset);
12033
- }
11980
+ state.iso.flatSamples.setCurrentSampleIndex(mediaSection.start, nextSample.trackId, nextSample.index + 1);
12034
11981
  return null;
12035
11982
  };
12036
11983
 
@@ -16075,7 +16022,8 @@ var parseLoop = async ({
16075
16022
  fields: state.fields,
16076
16023
  src: state.src,
16077
16024
  discardReadBytes: state.discardReadBytes,
16078
- prefetchCache: state.prefetchCache
16025
+ prefetchCache: state.prefetchCache,
16026
+ isoState: state.iso
16079
16027
  });
16080
16028
  state.timings.timeSeeking += Date.now() - seekStart;
16081
16029
  }
@@ -18237,7 +18185,7 @@ var downloadAndParseMedia = async (options) => {
18237
18185
  return returnValue;
18238
18186
  };
18239
18187
  // src/version.ts
18240
- var VERSION = "4.0.333";
18188
+ var VERSION = "4.0.334";
18241
18189
 
18242
18190
  // src/index.ts
18243
18191
  var MediaParserInternals = {