@remotion/media-parser 4.0.237 → 4.0.240

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.
Files changed (111) hide show
  1. package/dist/aac-codecprivate.d.ts +2 -9
  2. package/dist/aac-codecprivate.js +69 -34
  3. package/dist/add-avc-profile-to-track.js +4 -23
  4. package/dist/boxes/avc/codec-private.d.ts +2 -0
  5. package/dist/boxes/avc/codec-private.js +28 -0
  6. package/dist/boxes/avc/codec-string.d.ts +2 -0
  7. package/dist/boxes/avc/codec-string.js +7 -0
  8. package/dist/boxes/avc/color.d.ts +6 -0
  9. package/dist/boxes/avc/color.js +39 -0
  10. package/dist/boxes/avc/interpret-sps.d.ts +11 -0
  11. package/dist/boxes/avc/interpret-sps.js +44 -0
  12. package/dist/boxes/avc/key.d.ts +2 -0
  13. package/dist/boxes/avc/key.js +11 -0
  14. package/dist/boxes/avc/parse-avc.d.ts +36 -3
  15. package/dist/boxes/avc/parse-avc.js +161 -4
  16. package/dist/boxes/avc/sps-and-pps.d.ts +3 -0
  17. package/dist/boxes/avc/sps-and-pps.js +12 -0
  18. package/dist/boxes/iso-base-media/get-video-codec-from-iso-track.d.ts +2 -0
  19. package/dist/boxes/iso-base-media/get-video-codec-from-iso-track.js +55 -0
  20. package/dist/boxes/iso-base-media/make-track.js +2 -1
  21. package/dist/boxes/iso-base-media/mdat/mdat.js +8 -14
  22. package/dist/boxes/iso-base-media/process-box.js +1 -1
  23. package/dist/boxes/riff/parse-box.js +2 -2
  24. package/dist/boxes/riff/parse-movi.js +12 -14
  25. package/dist/boxes/transport-stream/adts-header.d.ts +7 -0
  26. package/dist/boxes/transport-stream/adts-header.js +56 -0
  27. package/dist/boxes/transport-stream/boxes.d.ts +41 -0
  28. package/dist/boxes/transport-stream/boxes.js +2 -0
  29. package/dist/boxes/transport-stream/discard-rest-of-packet.d.ts +3 -0
  30. package/dist/boxes/transport-stream/discard-rest-of-packet.js +13 -0
  31. package/dist/boxes/transport-stream/find-separator.d.ts +2 -0
  32. package/dist/boxes/transport-stream/find-separator.js +30 -0
  33. package/dist/boxes/transport-stream/get-tracks.d.ts +5 -0
  34. package/dist/boxes/transport-stream/get-tracks.js +33 -0
  35. package/dist/boxes/transport-stream/handle-aac-packet.d.ts +7 -0
  36. package/dist/boxes/transport-stream/handle-aac-packet.js +50 -0
  37. package/dist/boxes/transport-stream/handle-avc-packet.d.ts +8 -0
  38. package/dist/boxes/transport-stream/handle-avc-packet.js +60 -0
  39. package/dist/boxes/transport-stream/next-pes-header-store.d.ts +6 -0
  40. package/dist/boxes/transport-stream/next-pes-header-store.js +18 -0
  41. package/dist/boxes/transport-stream/parse-packet.d.ts +13 -0
  42. package/dist/boxes/transport-stream/parse-packet.js +80 -0
  43. package/dist/boxes/transport-stream/parse-pat.d.ts +8 -0
  44. package/dist/boxes/transport-stream/parse-pat.js +49 -0
  45. package/dist/boxes/transport-stream/parse-pes.d.ts +8 -0
  46. package/dist/boxes/transport-stream/parse-pes.js +76 -0
  47. package/dist/boxes/transport-stream/parse-pmt.d.ts +11 -0
  48. package/dist/boxes/transport-stream/parse-pmt.js +64 -0
  49. package/dist/boxes/transport-stream/parse-stream-packet.d.ts +15 -0
  50. package/dist/boxes/transport-stream/parse-stream-packet.js +107 -0
  51. package/dist/boxes/transport-stream/parse-transport-stream.d.ts +14 -0
  52. package/dist/boxes/transport-stream/parse-transport-stream.js +72 -0
  53. package/dist/boxes/transport-stream/process-stream-buffers.d.ts +19 -0
  54. package/dist/boxes/transport-stream/process-stream-buffers.js +42 -0
  55. package/dist/boxes/transport-stream/traversal.d.ts +6 -0
  56. package/dist/boxes/transport-stream/traversal.js +30 -0
  57. package/dist/boxes/webm/ebml.d.ts +1 -1
  58. package/dist/boxes/webm/parse-ebml.js +1 -1
  59. package/dist/buffer-iterator.d.ts +2 -0
  60. package/dist/buffer-iterator.js +25 -0
  61. package/dist/convert-audio-or-video-sample.d.ts +2 -0
  62. package/dist/convert-audio-or-video-sample.js +17 -0
  63. package/dist/create/iso-base-media/create-iso-base-media.js +38 -19
  64. package/dist/create/iso-base-media/trak/mdia/minf/create-stbl.js +7 -1
  65. package/dist/create/iso-base-media/trak/mdia/minf/stbl/create-stts.js +3 -0
  66. package/dist/create/media-fn.d.ts +0 -1
  67. package/dist/create/progress-tracker.d.ts +2 -0
  68. package/dist/create/progress-tracker.js +32 -8
  69. package/dist/emit-available-info.js +13 -2
  70. package/dist/esm/index.mjs +1325 -247
  71. package/dist/get-container.d.ts +1 -1
  72. package/dist/get-container.js +3 -0
  73. package/dist/get-duration.js +4 -1
  74. package/dist/get-fps.js +8 -2
  75. package/dist/get-location.d.ts +13 -0
  76. package/dist/get-location.js +40 -0
  77. package/dist/get-tracks.d.ts +4 -3
  78. package/dist/get-tracks.js +9 -2
  79. package/dist/get-video-codec.d.ts +1 -2
  80. package/dist/get-video-codec.js +9 -148
  81. package/dist/has-all-info.js +1 -1
  82. package/dist/index.d.ts +3 -0
  83. package/dist/metadata/get-metadata.js +3 -0
  84. package/dist/options.d.ts +11 -3
  85. package/dist/parse-media.js +3 -3
  86. package/dist/parse-result.d.ts +7 -2
  87. package/dist/parse-video.js +15 -0
  88. package/dist/register-track.d.ts +5 -5
  89. package/dist/register-track.js +16 -10
  90. package/dist/state/can-skip-tracks.js +1 -0
  91. package/dist/state/has-tracks-section.d.ts +3 -0
  92. package/dist/state/has-tracks-section.js +5 -0
  93. package/dist/state/parser-state.d.ts +2 -0
  94. package/dist/version.d.ts +1 -1
  95. package/dist/version.js +1 -1
  96. package/dist/webcodec-sample-types.d.ts +9 -2
  97. package/package.json +3 -3
  98. package/dist/add-new-matroska-tracks.d.ts +0 -13
  99. package/dist/add-new-matroska-tracks.js +0 -29
  100. package/dist/boxes/iso-base-media/meta/keys.d.ts +0 -10
  101. package/dist/boxes/iso-base-media/meta/keys.js +0 -17
  102. package/dist/boxes/iso-base-media/meta/list.d.ts +0 -12
  103. package/dist/boxes/iso-base-media/meta/list.js +0 -33
  104. package/dist/boxes/riff/strf.d.ts +0 -7
  105. package/dist/boxes/riff/strf.js +0 -67
  106. package/dist/create/mp3/create-mp3.d.ts +0 -2
  107. package/dist/create/mp3/create-mp3.js +0 -49
  108. package/dist/get-metadata.d.ts +0 -7
  109. package/dist/get-metadata.js +0 -63
  110. package/dist/parser-state.d.ts +0 -33
  111. package/dist/parser-state.js +0 -162
@@ -106,6 +106,38 @@ var fetchReader = {
106
106
  };
107
107
 
108
108
  // src/aac-codecprivate.ts
109
+ var getSampleRateFromSampleFrequencyIndex = (samplingFrequencyIndex) => {
110
+ switch (samplingFrequencyIndex) {
111
+ case 0:
112
+ return 96000;
113
+ case 1:
114
+ return 88200;
115
+ case 2:
116
+ return 64000;
117
+ case 3:
118
+ return 48000;
119
+ case 4:
120
+ return 44100;
121
+ case 5:
122
+ return 32000;
123
+ case 6:
124
+ return 24000;
125
+ case 7:
126
+ return 22050;
127
+ case 8:
128
+ return 16000;
129
+ case 9:
130
+ return 12000;
131
+ case 10:
132
+ return 11025;
133
+ case 11:
134
+ return 8000;
135
+ case 12:
136
+ return 7350;
137
+ default:
138
+ throw new Error(`Unexpected sampling frequency index ${samplingFrequencyIndex}`);
139
+ }
140
+ };
109
141
  var getConfigForSampleRate = (sampleRate) => {
110
142
  if (sampleRate === 96000) {
111
143
  return 0;
@@ -175,44 +207,35 @@ var parseAacCodecPrivate = (bytes) => {
175
207
  const audioObjectType = parseInt(bits.slice(0, 5), 2);
176
208
  const samplingFrequencyIndex = parseInt(bits.slice(5, 9), 2);
177
209
  const channelConfiguration = parseInt(bits.slice(9, 13), 2);
178
- const sampleRate = (() => {
179
- switch (samplingFrequencyIndex) {
180
- case 0:
181
- return 96000;
182
- case 1:
183
- return 88200;
184
- case 2:
185
- return 64000;
186
- case 3:
187
- return 48000;
188
- case 4:
189
- return 44100;
190
- case 5:
191
- return 32000;
192
- case 6:
193
- return 24000;
194
- case 7:
195
- return 22050;
196
- case 8:
197
- return 16000;
198
- case 9:
199
- return 12000;
200
- case 10:
201
- return 11025;
202
- case 11:
203
- return 8000;
204
- case 12:
205
- return 7350;
206
- default:
207
- throw new Error(`Unexpected sampling frequency index ${samplingFrequencyIndex}`);
208
- }
209
- })();
210
+ const sampleRate = getSampleRateFromSampleFrequencyIndex(samplingFrequencyIndex);
210
211
  return {
211
212
  audioObjectType,
212
213
  sampleRate,
213
214
  channelConfiguration
214
215
  };
215
216
  };
217
+ var mapAudioObjectTypeToCodecString = (audioObjectType) => {
218
+ switch (audioObjectType) {
219
+ case 1:
220
+ return "mp4a.40.2";
221
+ case 2:
222
+ return "mp4a.40.5";
223
+ case 3:
224
+ return "mp4a.40.29";
225
+ case 4:
226
+ return "mp4a.40.1";
227
+ case 5:
228
+ return "mp4a.40.3";
229
+ case 6:
230
+ return "mp4a.40.4";
231
+ case 17:
232
+ return "mp4a.40.17";
233
+ case 23:
234
+ return "mp4a.40.23";
235
+ default:
236
+ throw new Error(`Unexpected audio object type ${audioObjectType}`);
237
+ }
238
+ };
216
239
 
217
240
  // src/create/event-emitter.ts
218
241
  class IoEventEmitter {
@@ -1343,7 +1366,7 @@ var createIsoBaseMediaFtyp = ({
1343
1366
  };
1344
1367
 
1345
1368
  // src/version.ts
1346
- var VERSION = "4.0.237";
1369
+ var VERSION = "4.0.240";
1347
1370
 
1348
1371
  // src/create/iso-base-media/create-ilst.ts
1349
1372
  var createIlst = (items) => {
@@ -1872,6 +1895,9 @@ var createStsz = (samplePositions) => {
1872
1895
 
1873
1896
  // src/create/iso-base-media/trak/mdia/minf/stbl/create-stts.ts
1874
1897
  var makeEntry2 = (entry) => {
1898
+ if (entry.sampleOffset < 0) {
1899
+ throw new Error("negative sample offset in stts " + entry.sampleOffset);
1900
+ }
1875
1901
  return combineUint8Arrays([
1876
1902
  numberTo32BitUIntOrInt(entry.sampleCount),
1877
1903
  numberTo32BitUIntOrInt(entry.sampleOffset)
@@ -1923,10 +1949,11 @@ var createStbl = ({
1923
1949
  codecSpecificData,
1924
1950
  isVideo
1925
1951
  }) => {
1952
+ const sorted = samplePositions.slice().sort((a, b) => a.dts - b.dts);
1926
1953
  return addSize(combineUint8Arrays([
1927
1954
  stringsToUint8Array("stbl"),
1928
1955
  createStsdData(codecSpecificData),
1929
- createSttsAtom(samplePositions),
1956
+ createSttsAtom(sorted),
1930
1957
  isVideo ? createStss(samplePositions) : null,
1931
1958
  createCttsBox(samplePositions),
1932
1959
  createStsc(samplePositions),
@@ -2119,6 +2146,7 @@ var createPaddedMoovAtom = ({
2119
2146
  };
2120
2147
 
2121
2148
  // src/create/iso-base-media/create-iso-base-media.ts
2149
+ var CONTAINER_TIMESCALE = 1000;
2122
2150
  var createIsoBaseMedia = async ({
2123
2151
  writer,
2124
2152
  onBytesProgress,
@@ -2134,23 +2162,25 @@ var createIsoBaseMedia = async ({
2134
2162
  });
2135
2163
  const w = await writer.createContent({ filename, mimeType: "video/mp4" });
2136
2164
  await w.write(header);
2137
- let durationInUnits = 0;
2165
+ let globalDurationInUnits = 0;
2166
+ const lowestTrackTimestamps = {};
2167
+ const trackDurations = {};
2138
2168
  const currentTracks = [];
2139
2169
  const samplePositions = [];
2140
2170
  const sampleChunkIndices = [];
2141
2171
  const moovOffset = w.getWrittenByteCount();
2142
2172
  const getPaddedMoovAtom = () => {
2143
2173
  return createPaddedMoovAtom({
2144
- durationInUnits,
2174
+ durationInUnits: globalDurationInUnits,
2145
2175
  trackInfo: currentTracks.map((track) => {
2146
2176
  return {
2147
2177
  track,
2148
- durationInUnits,
2178
+ durationInUnits: trackDurations[track.trackNumber] ?? 0,
2149
2179
  samplePositions: samplePositions[track.trackNumber] ?? [],
2150
2180
  timescale: track.timescale
2151
2181
  };
2152
2182
  }),
2153
- timescale: 1000
2183
+ timescale: CONTAINER_TIMESCALE
2154
2184
  });
2155
2185
  };
2156
2186
  await w.write(getPaddedMoovAtom());
@@ -2169,10 +2199,6 @@ var createIsoBaseMedia = async ({
2169
2199
  await w.updateDataAt(moovOffset, getPaddedMoovAtom());
2170
2200
  onBytesProgress(w.getWrittenByteCount());
2171
2201
  };
2172
- const updateDuration = (newDuration) => {
2173
- durationInUnits = newDuration;
2174
- onMillisecondsProgress(newDuration);
2175
- };
2176
2202
  const addCodecPrivateToTrack = ({
2177
2203
  trackNumber: trackNumber2,
2178
2204
  codecPrivate: codecPrivate2
@@ -2188,19 +2214,35 @@ var createIsoBaseMedia = async ({
2188
2214
  chunk,
2189
2215
  trackNumber: trackNumber2,
2190
2216
  isVideo,
2191
- timescale,
2192
2217
  codecPrivate: codecPrivate2
2193
2218
  }) => {
2194
2219
  const position = w.getWrittenByteCount();
2195
2220
  await w.write(chunk.data);
2196
2221
  mdatSize += chunk.data.length;
2197
2222
  onBytesProgress(w.getWrittenByteCount());
2223
+ progressTracker.setPossibleLowestTimestamp(Math.min(chunk.timestamp, chunk.cts ?? Infinity, chunk.dts ?? Infinity));
2198
2224
  progressTracker.updateTrackProgress(trackNumber2, chunk.timestamp);
2199
2225
  if (codecPrivate2) {
2200
2226
  addCodecPrivateToTrack({ trackNumber: trackNumber2, codecPrivate: codecPrivate2 });
2201
2227
  }
2202
- const newDuration = Math.round((chunk.timestamp + (chunk.duration ?? 0)) / 1000);
2203
- updateDuration(newDuration);
2228
+ const currentTrack = currentTracks.find((t) => t.trackNumber === trackNumber2);
2229
+ if (!currentTrack) {
2230
+ throw new Error(`Tried to add sample to track ${trackNumber2}, but it doesn't exist`);
2231
+ }
2232
+ if (!lowestTrackTimestamps[trackNumber2] || chunk.timestamp < lowestTrackTimestamps[trackNumber2]) {
2233
+ lowestTrackTimestamps[trackNumber2] = chunk.timestamp;
2234
+ }
2235
+ if (typeof lowestTrackTimestamps[trackNumber2] !== "number") {
2236
+ throw new Error(`Tried to add sample to track ${trackNumber2}, but it has no timestamp`);
2237
+ }
2238
+ const newDurationInMicroSeconds = chunk.timestamp + (chunk.duration ?? 0) - lowestTrackTimestamps[trackNumber2];
2239
+ const newDurationInTrackTimeUnits = Math.round(newDurationInMicroSeconds / (1e6 / currentTrack.timescale));
2240
+ trackDurations[trackNumber2] = newDurationInTrackTimeUnits;
2241
+ const newDurationInMilliseconds = Math.round(newDurationInMicroSeconds / 1e6 * CONTAINER_TIMESCALE);
2242
+ if (newDurationInMilliseconds > globalDurationInUnits) {
2243
+ globalDurationInUnits = newDurationInMilliseconds;
2244
+ onMillisecondsProgress(newDurationInMilliseconds);
2245
+ }
2204
2246
  if (!samplePositions[trackNumber2]) {
2205
2247
  samplePositions[trackNumber2] = [];
2206
2248
  }
@@ -2218,9 +2260,9 @@ var createIsoBaseMedia = async ({
2218
2260
  isKeyframe: chunk.type === "key",
2219
2261
  offset: position,
2220
2262
  chunk: sampleChunkIndices[trackNumber2],
2221
- cts: Math.round(chunk.cts / (1e6 / timescale)),
2222
- dts: Math.round(chunk.dts / (1e6 / timescale)),
2223
- duration: Math.round((chunk.duration ?? 0) / (1e6 / timescale)),
2263
+ cts: Math.round(chunk.cts / 1e6 * currentTrack.timescale),
2264
+ dts: Math.round(chunk.dts / 1e6 * currentTrack.timescale),
2265
+ duration: Math.round((chunk.duration ?? 0) / 1e6 * currentTrack.timescale),
2224
2266
  size: chunk.data.length
2225
2267
  };
2226
2268
  lastChunkWasVideo = isVideo;
@@ -2240,13 +2282,12 @@ var createIsoBaseMedia = async ({
2240
2282
  remove: async () => {
2241
2283
  await w.remove();
2242
2284
  },
2243
- addSample: ({ chunk, trackNumber: trackNumber2, isVideo, timescale, codecPrivate: codecPrivate2 }) => {
2285
+ addSample: ({ chunk, trackNumber: trackNumber2, isVideo, codecPrivate: codecPrivate2 }) => {
2244
2286
  operationProm.current = operationProm.current.then(() => {
2245
2287
  return addSample({
2246
2288
  chunk,
2247
2289
  trackNumber: trackNumber2,
2248
2290
  isVideo,
2249
- timescale,
2250
2291
  codecPrivate: codecPrivate2
2251
2292
  });
2252
2293
  });
@@ -3318,20 +3359,37 @@ var withResolversAndWaitForReturn = () => {
3318
3359
  var makeProgressTracker = () => {
3319
3360
  const trackNumberProgresses = {};
3320
3361
  const eventEmitter = new IoEventEmitter;
3321
- const calculateSmallestProgress = () => {
3322
- const progressValues = Object.values(trackNumberProgresses);
3323
- if (progressValues.length === 0) {
3324
- return 0;
3362
+ let startingTimestamp = null;
3363
+ const setPossibleLowestTimestamp = (timestamp) => {
3364
+ if (startingTimestamp === null) {
3365
+ startingTimestamp = timestamp;
3366
+ } else {
3367
+ startingTimestamp = Math.min(startingTimestamp, timestamp);
3325
3368
  }
3369
+ };
3370
+ const getStartingTimestamp = () => {
3371
+ if (startingTimestamp === null) {
3372
+ throw new Error("No starting timestamp");
3373
+ }
3374
+ return startingTimestamp;
3375
+ };
3376
+ const calculateSmallestProgress = () => {
3377
+ const progressValues = Object.values(trackNumberProgresses).map((p) => {
3378
+ if (p !== null) {
3379
+ return p;
3380
+ }
3381
+ if (startingTimestamp === null) {
3382
+ throw new Error("No progress values to calculate smallest progress from");
3383
+ }
3384
+ return startingTimestamp;
3385
+ });
3326
3386
  return Math.min(...progressValues);
3327
3387
  };
3328
3388
  return {
3329
3389
  registerTrack: (trackNumber2) => {
3330
- trackNumberProgresses[trackNumber2] = 0;
3331
- },
3332
- getSmallestProgress: () => {
3333
- return calculateSmallestProgress();
3390
+ trackNumberProgresses[trackNumber2] = null;
3334
3391
  },
3392
+ getSmallestProgress: calculateSmallestProgress,
3335
3393
  updateTrackProgress: (trackNumber2, progress) => {
3336
3394
  if (trackNumberProgresses[trackNumber2] === undefined) {
3337
3395
  throw new Error(`Tried to update progress for a track that was not registered: ${trackNumber2}`);
@@ -3349,7 +3407,9 @@ var makeProgressTracker = () => {
3349
3407
  };
3350
3408
  eventEmitter.addEventListener("processed", on);
3351
3409
  return promise;
3352
- }
3410
+ },
3411
+ getStartingTimestamp,
3412
+ setPossibleLowestTimestamp
3353
3413
  };
3354
3414
  };
3355
3415
 
@@ -3819,6 +3879,9 @@ var getMetadata = (structure) => {
3819
3879
  if (structure.type === "riff") {
3820
3880
  return getMetadataFromRiff(structure);
3821
3881
  }
3882
+ if (structure.type === "transport-stream") {
3883
+ return [];
3884
+ }
3822
3885
  return getMetadataFromIsoBase(structure);
3823
3886
  };
3824
3887
 
@@ -3944,6 +4007,9 @@ var getFps = (segments) => {
3944
4007
  if (segments.type === "matroska") {
3945
4008
  return null;
3946
4009
  }
4010
+ if (segments.type === "transport-stream") {
4011
+ return null;
4012
+ }
3947
4013
  throw new Error("Cannot get fps, not implemented");
3948
4014
  };
3949
4015
  var hasFps = (boxes) => {
@@ -3951,6 +4017,9 @@ var hasFps = (boxes) => {
3951
4017
  if (boxes.type === "matroska") {
3952
4018
  return true;
3953
4019
  }
4020
+ if (boxes.type === "transport-stream") {
4021
+ return true;
4022
+ }
3954
4023
  return getFps(boxes) !== null;
3955
4024
  } catch {
3956
4025
  return false;
@@ -4278,6 +4347,17 @@ var getDisplayAspectRatio = ({
4278
4347
  return reduceFraction(num, den);
4279
4348
  };
4280
4349
 
4350
+ // src/boxes/avc/color.ts
4351
+ var getMatrixCoefficientsFromIndex = (index) => {
4352
+ return index === 1 ? "bt709" : index === 5 ? "bt470bg" : index === 6 ? "smpte170m" : index === 9 ? "bt2020" : null;
4353
+ };
4354
+ var getTransferCharacteristicsFromIndex = (index) => {
4355
+ return index === 1 ? "bt709" : index === 6 ? "smpte170m" : index === 13 ? "iec61966-2-1" : index === 18 ? "arib-std-b67" : null;
4356
+ };
4357
+ var getPrimariesFromIndex = (index) => {
4358
+ return index === 1 ? "bt709" : index === 5 ? "bt470bg" : index === 6 ? "smpte170m" : index === 9 ? "bt2020" : null;
4359
+ };
4360
+
4281
4361
  // src/buffer-iterator.ts
4282
4362
  class OffsetCounter {
4283
4363
  #offset;
@@ -4474,6 +4554,9 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
4474
4554
  const isMp3 = () => {
4475
4555
  return matchesPattern(mpegPattern)(data.subarray(0, 4));
4476
4556
  };
4557
+ const isTransportStream = () => {
4558
+ return data[0] === 71;
4559
+ };
4477
4560
  const removeBytesRead = () => {
4478
4561
  if (!discardAllowed) {
4479
4562
  return;
@@ -4510,6 +4593,20 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
4510
4593
  removeBytesRead();
4511
4594
  }
4512
4595
  };
4596
+ const readExpGolomb = () => {
4597
+ if (!bitReadingMode) {
4598
+ throw new Error("Not in bit reading mode");
4599
+ }
4600
+ let zerosCount = 0;
4601
+ while (getBits(1) === 0) {
4602
+ zerosCount++;
4603
+ }
4604
+ let suffix = 0;
4605
+ for (let i = 0;i < zerosCount; i++) {
4606
+ suffix = suffix << 1 | getBits(1);
4607
+ }
4608
+ return (1 << zerosCount) - 1 + suffix;
4609
+ };
4513
4610
  const peekB = (length) => {
4514
4611
  console.log([...getSlice(length)].map((b) => b.toString(16).padStart(2, "0")));
4515
4612
  counter.decrement(length);
@@ -4532,9 +4629,12 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
4532
4629
  let bitIndex = 0;
4533
4630
  const stopReadingBits = () => {
4534
4631
  bitIndex = 0;
4632
+ bitReadingMode = false;
4535
4633
  };
4536
4634
  let byteToShift = 0;
4635
+ let bitReadingMode = false;
4537
4636
  const startReadingBits = () => {
4637
+ bitReadingMode = true;
4538
4638
  byteToShift = getUint8();
4539
4639
  };
4540
4640
  const getBits = (bits) => {
@@ -4739,7 +4839,9 @@ var getArrayBufferIterator = (initialData, maxBytes) => {
4739
4839
  isMp3,
4740
4840
  disallowDiscard,
4741
4841
  allowDiscard,
4742
- startBox
4842
+ startBox,
4843
+ isTransportStream,
4844
+ readExpGolomb
4743
4845
  };
4744
4846
  };
4745
4847
 
@@ -4806,114 +4908,9 @@ var parseAv1PrivateData = (data, colrAtom) => {
4806
4908
  };
4807
4909
 
4808
4910
  // src/get-video-codec.ts
4809
- var getVideoCodecFromIsoTrak = (trakBox) => {
4810
- const stsdBox = getStsdBox(trakBox);
4811
- if (stsdBox && stsdBox.type === "stsd-box") {
4812
- const videoSample = stsdBox.samples.find((s) => s.type === "video");
4813
- if (videoSample && videoSample.type === "video") {
4814
- if (videoSample.format === "hvc1") {
4815
- return "h265";
4816
- }
4817
- if (videoSample.format === "avc1") {
4818
- return "h264";
4819
- }
4820
- if (videoSample.format === "av01") {
4821
- return "av1";
4822
- }
4823
- if (videoSample.format === "ap4h") {
4824
- return "prores";
4825
- }
4826
- if (videoSample.format === "ap4x") {
4827
- return "prores";
4828
- }
4829
- if (videoSample.format === "apch") {
4830
- return "prores";
4831
- }
4832
- if (videoSample.format === "apcn") {
4833
- return "prores";
4834
- }
4835
- if (videoSample.format === "apcs") {
4836
- return "prores";
4837
- }
4838
- if (videoSample.format === "apco") {
4839
- return "prores";
4840
- }
4841
- if (videoSample.format === "aprh") {
4842
- return "prores";
4843
- }
4844
- if (videoSample.format === "aprn") {
4845
- return "prores";
4846
- }
4847
- }
4848
- }
4849
- throw new Error("Could not find video codec");
4850
- };
4851
- var getVideoCodecFromMatroska = (boxes) => {
4852
- const mainSegment = boxes.find((b) => b.type === "Segment");
4853
- if (!mainSegment || mainSegment.type !== "Segment") {
4854
- return null;
4855
- }
4856
- const tracksSegment = mainSegment.value.find((b) => b.type === "Tracks");
4857
- if (!tracksSegment || tracksSegment.type !== "Tracks") {
4858
- return null;
4859
- }
4860
- for (const track of tracksSegment.value) {
4861
- if (track.type === "TrackEntry") {
4862
- const trackType2 = track.value.find((b) => b.type === "CodecID");
4863
- if (trackType2 && trackType2.type === "CodecID") {
4864
- if (trackType2.value === "V_VP8") {
4865
- return "vp8";
4866
- }
4867
- if (trackType2.value === "V_VP9") {
4868
- return "vp9";
4869
- }
4870
- if (trackType2.value === "V_AV1") {
4871
- return "av1";
4872
- }
4873
- if (trackType2.value === "V_MPEG4/ISO/AVC") {
4874
- return "h264";
4875
- }
4876
- if (trackType2.value === "V_MPEGH/ISO/HEVC") {
4877
- return "h265";
4878
- }
4879
- }
4880
- }
4881
- }
4882
- throw new Error("Could not find video codec");
4883
- };
4884
- var getVideoCodecFromAvi = (structure) => {
4885
- const strl = getStrlBoxes(structure);
4886
- for (const s of strl) {
4887
- const strh = getStrhBox(s.children);
4888
- if (!strh) {
4889
- throw new Error("No strh box");
4890
- }
4891
- if (strh.fccType === "auds") {
4892
- continue;
4893
- }
4894
- if (strh.handler === "H264") {
4895
- return "h264";
4896
- }
4897
- }
4898
- throw new Error("Unsupported codec");
4899
- };
4900
- var getVideoCodec = (boxes) => {
4901
- if (boxes.type === "iso-base-media") {
4902
- const moovBox = getMoovBox(boxes.boxes);
4903
- if (moovBox) {
4904
- const trakBox = getTraks(moovBox).filter((t) => trakBoxContainsVideo(t))[0];
4905
- if (trakBox) {
4906
- return getVideoCodecFromIsoTrak(trakBox);
4907
- }
4908
- }
4909
- }
4910
- if (boxes.type === "riff") {
4911
- return getVideoCodecFromAvi(boxes);
4912
- }
4913
- if (boxes.type === "matroska") {
4914
- return getVideoCodecFromMatroska(boxes.boxes);
4915
- }
4916
- return null;
4911
+ var getVideoCodec = (boxes, state) => {
4912
+ const track = getTracks(boxes, state);
4913
+ return track.videoTracks[0]?.codecWithoutConfig ?? null;
4917
4914
  };
4918
4915
  var hasVideoCodec = (boxes, state) => {
4919
4916
  return hasTracks(boxes, state);
@@ -4951,9 +4948,9 @@ var getIsoBmColrConfig = (trakBox) => {
4951
4948
  }
4952
4949
  return {
4953
4950
  fullRange: colrAtom.fullRangeFlag,
4954
- matrixCoefficients: colrAtom.matrixIndex === 1 ? "bt709" : colrAtom.matrixIndex === 5 ? "bt470bg" : colrAtom.matrixIndex === 6 ? "smpte170m" : colrAtom.matrixIndex === 9 ? "bt2020" : null,
4955
- primaries: colrAtom.primaries === 1 ? "bt709" : colrAtom.primaries === 5 ? "bt470bg" : colrAtom.primaries === 6 ? "smpte170m" : colrAtom.primaries === 9 ? "bt2020" : null,
4956
- transferCharacteristics: colrAtom.transfer === 1 ? "bt709" : colrAtom.transfer === 6 ? "smpte170m" : colrAtom.transfer === 13 ? "iec61966-2-1" : colrAtom.transfer === 18 ? "arib-std-b67" : null
4951
+ matrixCoefficients: getMatrixCoefficientsFromIndex(colrAtom.matrixIndex),
4952
+ primaries: getPrimariesFromIndex(colrAtom.primaries),
4953
+ transferCharacteristics: getTransferCharacteristicsFromIndex(colrAtom.transfer)
4957
4954
  };
4958
4955
  };
4959
4956
  var getVideoCodecString = (trakBox) => {
@@ -4998,6 +4995,50 @@ var getActualDecoderParameters = ({
4998
4995
  };
4999
4996
  };
5000
4997
 
4998
+ // src/boxes/iso-base-media/get-video-codec-from-iso-track.ts
4999
+ var getVideoCodecFromIsoTrak = (trakBox) => {
5000
+ const stsdBox = getStsdBox(trakBox);
5001
+ if (stsdBox && stsdBox.type === "stsd-box") {
5002
+ const videoSample = stsdBox.samples.find((s) => s.type === "video");
5003
+ if (videoSample && videoSample.type === "video") {
5004
+ if (videoSample.format === "hvc1") {
5005
+ return "h265";
5006
+ }
5007
+ if (videoSample.format === "avc1") {
5008
+ return "h264";
5009
+ }
5010
+ if (videoSample.format === "av01") {
5011
+ return "av1";
5012
+ }
5013
+ if (videoSample.format === "ap4h") {
5014
+ return "prores";
5015
+ }
5016
+ if (videoSample.format === "ap4x") {
5017
+ return "prores";
5018
+ }
5019
+ if (videoSample.format === "apch") {
5020
+ return "prores";
5021
+ }
5022
+ if (videoSample.format === "apcn") {
5023
+ return "prores";
5024
+ }
5025
+ if (videoSample.format === "apcs") {
5026
+ return "prores";
5027
+ }
5028
+ if (videoSample.format === "apco") {
5029
+ return "prores";
5030
+ }
5031
+ if (videoSample.format === "aprh") {
5032
+ return "prores";
5033
+ }
5034
+ if (videoSample.format === "aprn") {
5035
+ return "prores";
5036
+ }
5037
+ }
5038
+ }
5039
+ throw new Error("Could not find video codec");
5040
+ };
5041
+
5001
5042
  // src/boxes/iso-base-media/make-track.ts
5002
5043
  var makeBaseMediaTrack = (trakBox) => {
5003
5044
  const tkhdBox = getTkhdBox(trakBox);
@@ -5095,6 +5136,30 @@ var makeBaseMediaTrack = (trakBox) => {
5095
5136
  return track;
5096
5137
  };
5097
5138
 
5139
+ // src/boxes/avc/codec-private.ts
5140
+ var getAvccBoxContent = (avc1Profile) => {
5141
+ return combineUint8Arrays([
5142
+ new Uint8Array([
5143
+ 1,
5144
+ avc1Profile.sps.spsData.level,
5145
+ avc1Profile.sps.spsData.compatibility,
5146
+ avc1Profile.sps.spsData.profile,
5147
+ 255,
5148
+ 225
5149
+ ]),
5150
+ serializeUint16(avc1Profile.sps.sps.length),
5151
+ avc1Profile.sps.sps,
5152
+ new Uint8Array([1]),
5153
+ serializeUint16(avc1Profile.pps.pps.length),
5154
+ avc1Profile.pps.pps
5155
+ ]);
5156
+ };
5157
+
5158
+ // src/boxes/avc/codec-string.ts
5159
+ var getCodecStringFromSpsAndPps = (sps) => {
5160
+ return `avc1.${sps.spsData.profile.toString(16).padStart(2, "0")}${sps.spsData.compatibility.toString(16).padStart(2, "0")}${sps.spsData.level.toString(16).padStart(2, "0")}`;
5161
+ };
5162
+
5098
5163
  // src/add-avc-profile-to-track.ts
5099
5164
  var addAvcProfileToTrack = (track, avc1Profile) => {
5100
5165
  if (avc1Profile === null) {
@@ -5102,22 +5167,8 @@ var addAvcProfileToTrack = (track, avc1Profile) => {
5102
5167
  }
5103
5168
  return {
5104
5169
  ...track,
5105
- codec: `avc1.${avc1Profile.sps.profile.toString(16).padStart(2, "0")}${avc1Profile.sps.compatibility.toString(16).padStart(2, "0")}${avc1Profile.sps.level.toString(16).padStart(2, "0")}`,
5106
- codecPrivate: combineUint8Arrays([
5107
- new Uint8Array([
5108
- 1,
5109
- avc1Profile.sps.level,
5110
- avc1Profile.sps.compatibility,
5111
- avc1Profile.sps.profile,
5112
- 255,
5113
- 225
5114
- ]),
5115
- serializeUint16(avc1Profile.sps.sps.length),
5116
- avc1Profile.sps.sps,
5117
- new Uint8Array([1]),
5118
- serializeUint16(avc1Profile.pps.pps.length),
5119
- avc1Profile.pps.pps
5120
- ])
5170
+ codec: getCodecStringFromSpsAndPps(avc1Profile.sps),
5171
+ codecPrivate: getAvccBoxContent(avc1Profile)
5121
5172
  };
5122
5173
  };
5123
5174
 
@@ -5229,6 +5280,57 @@ var hasAllTracksFromAvi = (structure, state) => {
5229
5280
  }
5230
5281
  };
5231
5282
 
5283
+ // src/boxes/transport-stream/traversal.ts
5284
+ var findProgramAssociationTableOrThrow = (structure) => {
5285
+ const box = structure.boxes.find((b) => b.type === "transport-stream-pat-box");
5286
+ if (!box) {
5287
+ throw new Error("No PAT box found");
5288
+ }
5289
+ return box;
5290
+ };
5291
+ var findProgramMapTableOrThrow = (structure) => {
5292
+ const box = structure.boxes.find((b) => b.type === "transport-stream-pmt-box");
5293
+ if (!box) {
5294
+ throw new Error("No PMT box found");
5295
+ }
5296
+ return box;
5297
+ };
5298
+ var getProgramForId = (structure, packetIdentifier) => {
5299
+ const box = findProgramAssociationTableOrThrow(structure);
5300
+ const entry = box.pat.find((e) => e.programMapIdentifier === packetIdentifier);
5301
+ return entry ?? null;
5302
+ };
5303
+ var getStreamForId = (structure, packetIdentifier) => {
5304
+ const box = findProgramMapTableOrThrow(structure);
5305
+ const entry = box.streams.find((e) => e.pid === packetIdentifier);
5306
+ return entry ?? null;
5307
+ };
5308
+
5309
+ // src/boxes/transport-stream/get-tracks.ts
5310
+ var getTracksFromTransportStream = (structure, parserState) => {
5311
+ const programMapTable = findProgramMapTableOrThrow(structure);
5312
+ const parserTracks = parserState.tracks.getTracks();
5313
+ const mapped = programMapTable.streams.map((stream) => {
5314
+ return parserTracks.find((track) => track.trackId === stream.pid);
5315
+ }).filter(truthy);
5316
+ if (mapped.length !== programMapTable.streams.length) {
5317
+ throw new Error("Not all tracks found");
5318
+ }
5319
+ return {
5320
+ videoTracks: mapped.filter((track) => track.type === "video"),
5321
+ audioTracks: mapped.filter((track) => track.type === "audio"),
5322
+ otherTracks: []
5323
+ };
5324
+ };
5325
+ var hasAllTracksFromTransportStream = (structure, parserState) => {
5326
+ try {
5327
+ getTracksFromTransportStream(structure, parserState);
5328
+ return true;
5329
+ } catch {
5330
+ return false;
5331
+ }
5332
+ };
5333
+
5232
5334
  // src/make-hvc1-codec-strings.ts
5233
5335
  var getHvc1CodecString = (data) => {
5234
5336
  const configurationVersion = data.getUint8();
@@ -5629,7 +5731,10 @@ var hasTracks = (structure, state) => {
5629
5731
  if (structure.type === "riff") {
5630
5732
  return hasAllTracksFromAvi(structure, state);
5631
5733
  }
5632
- throw new Error("Unknown container");
5734
+ if (structure.type === "transport-stream") {
5735
+ return hasAllTracksFromTransportStream(structure, state);
5736
+ }
5737
+ throw new Error("Unknown container " + structure);
5633
5738
  };
5634
5739
  var getTracksFromMa = (segments, state) => {
5635
5740
  const videoTracks = [];
@@ -5697,7 +5802,10 @@ var getTracks = (segments, state) => {
5697
5802
  if (segments.type === "riff") {
5698
5803
  return getTracksFromAvi(segments, state);
5699
5804
  }
5700
- throw new Error("Unknown container");
5805
+ if (segments.type === "transport-stream") {
5806
+ return getTracksFromTransportStream(segments, state);
5807
+ }
5808
+ throw new Error(`Unknown container${segments}`);
5701
5809
  };
5702
5810
 
5703
5811
  // src/get-container.ts
@@ -5708,6 +5816,9 @@ var getContainer = (segments) => {
5708
5816
  if (segments.type === "matroska") {
5709
5817
  return "webm";
5710
5818
  }
5819
+ if (segments.type === "transport-stream") {
5820
+ return "transport-stream";
5821
+ }
5711
5822
  if (segments.type === "riff") {
5712
5823
  if (isRiffAvi(segments)) {
5713
5824
  return "avi";
@@ -6036,7 +6147,10 @@ var getDuration = (structure, parserState) => {
6036
6147
  if (structure.type === "riff") {
6037
6148
  return getDurationFromAvi(structure);
6038
6149
  }
6039
- throw new Error("Has no duration");
6150
+ if (structure.type === "transport-stream") {
6151
+ return null;
6152
+ }
6153
+ throw new Error("Has no duration " + structure);
6040
6154
  };
6041
6155
  var hasDuration = (structure, parserState) => {
6042
6156
  return hasTracks(structure, parserState);
@@ -6054,6 +6168,39 @@ var hasHdr = (boxes, state) => {
6054
6168
  return hasTracks(boxes, state);
6055
6169
  };
6056
6170
 
6171
+ // src/get-location.ts
6172
+ function parseLocation(locationString) {
6173
+ const locationPattern = /^([+-]\d{2}\.?\d{0,10})([+-]\d{3}\.?\d{0,10})([+-]\d+(\.\d+)?)?\/$/;
6174
+ const match = locationString.match(locationPattern);
6175
+ if (!match) {
6176
+ return null;
6177
+ }
6178
+ const latitude = parseFloat(match[1]);
6179
+ const longitude = parseFloat(match[2]);
6180
+ const altitude = match[3] ? parseFloat(match[3]) : null;
6181
+ return {
6182
+ latitude,
6183
+ longitude,
6184
+ altitude
6185
+ };
6186
+ }
6187
+ var getLocation = (structure) => {
6188
+ const metadata = getMetadata(structure);
6189
+ const locationEntry = metadata.find((entry) => entry.key === "com.apple.quicktime.location.ISO6709");
6190
+ const horizontalAccuracy = metadata.find((entry) => entry.key === "com.apple.quicktime.location.accuracy.horizontal");
6191
+ if (locationEntry) {
6192
+ const parsed = parseLocation(locationEntry.value);
6193
+ if (parsed === null) {
6194
+ return null;
6195
+ }
6196
+ return {
6197
+ ...parsed,
6198
+ horizontalAccuracy: horizontalAccuracy?.value ? parseFloat(String(horizontalAccuracy.value)) : null
6199
+ };
6200
+ }
6201
+ return null;
6202
+ };
6203
+
6057
6204
  // src/emit-available-info.ts
6058
6205
  var emitAvailableInfo = ({
6059
6206
  hasInfo,
@@ -6124,7 +6271,7 @@ var emitAvailableInfo = ({
6124
6271
  }
6125
6272
  if (key === "videoCodec") {
6126
6273
  if (returnValue.videoCodec === undefined && hasInfo.videoCodec && parseResult) {
6127
- const videoCodec = getVideoCodec(parseResult.segments);
6274
+ const videoCodec = getVideoCodec(parseResult.segments, state);
6128
6275
  moreFields.onVideoCodec?.(videoCodec);
6129
6276
  returnValue.videoCodec = videoCodec;
6130
6277
  }
@@ -6192,6 +6339,14 @@ var emitAvailableInfo = ({
6192
6339
  }
6193
6340
  continue;
6194
6341
  }
6342
+ if (key === "location") {
6343
+ if (returnValue.location === undefined && hasInfo.location && parseResult) {
6344
+ const location = getLocation(parseResult.segments);
6345
+ moreFields.onLocation?.(location);
6346
+ returnValue.location = location;
6347
+ }
6348
+ continue;
6349
+ }
6195
6350
  throw new Error(`Unhandled key: ${key}`);
6196
6351
  }
6197
6352
  };
@@ -6237,7 +6392,7 @@ var getAvailableInfo = (options, structure, state) => {
6237
6392
  if (key === "container") {
6238
6393
  return Boolean(structure && hasContainer(structure));
6239
6394
  }
6240
- if (key === "metadata") {
6395
+ if (key === "metadata" || key === "location") {
6241
6396
  return false;
6242
6397
  }
6243
6398
  throw new Error(`Unknown key: ${key}`);
@@ -6260,29 +6415,35 @@ var hasAllInfo = ({
6260
6415
 
6261
6416
  // src/register-track.ts
6262
6417
  var registerTrack = async ({
6263
- state,
6264
6418
  options,
6265
- track
6419
+ track,
6420
+ container
6266
6421
  }) => {
6267
- if (track.type === "video" && options.onVideoTrack) {
6268
- const callback = await options.onVideoTrack(track);
6269
- await state.registerVideoSampleCallback(track.trackId, callback ?? null);
6422
+ if (track.type === "video") {
6423
+ options.parserState.tracks.addTrack(track);
6424
+ if (options.onVideoTrack) {
6425
+ const callback = await options.onVideoTrack({ track, container });
6426
+ await options.parserState.registerVideoSampleCallback(track.trackId, callback ?? null);
6427
+ }
6270
6428
  }
6271
- if (track.type === "audio" && options.onAudioTrack) {
6272
- const callback = await options.onAudioTrack(track);
6273
- await state.registerAudioSampleCallback(track.trackId, callback ?? null);
6429
+ if (track.type === "audio") {
6430
+ options.parserState.tracks.addTrack(track);
6431
+ if (options.onAudioTrack) {
6432
+ const callback = await options.onAudioTrack({ track, container });
6433
+ await options.parserState.registerAudioSampleCallback(track.trackId, callback ?? null);
6434
+ }
6274
6435
  }
6275
6436
  };
6276
6437
  var registerVideoTrackWhenProfileIsAvailable = ({
6277
6438
  options,
6278
- state,
6279
- track
6439
+ track,
6440
+ container
6280
6441
  }) => {
6281
- state.registerOnAvcProfileCallback(async (profile) => {
6442
+ options.parserState.registerOnAvcProfileCallback(async (profile) => {
6282
6443
  await registerTrack({
6283
6444
  options,
6284
- state,
6285
- track: addAvcProfileToTrack(track, profile)
6445
+ track: addAvcProfileToTrack(track, profile),
6446
+ container
6286
6447
  });
6287
6448
  });
6288
6449
  };
@@ -6445,6 +6606,20 @@ var parseFtyp = ({
6445
6606
  };
6446
6607
  };
6447
6608
 
6609
+ // src/convert-audio-or-video-sample.ts
6610
+ var convertAudioOrVideoSampleToWebCodecsTimestamps = (sample, timescale2) => {
6611
+ const { cts, dts, timestamp } = sample;
6612
+ return {
6613
+ cts: cts * 1e6 / timescale2,
6614
+ dts: dts * 1e6 / timescale2,
6615
+ timestamp: timestamp * 1e6 / timescale2,
6616
+ duration: (sample.duration ?? 0) * 1e6 / timescale2,
6617
+ data: sample.data,
6618
+ trackId: sample.trackId,
6619
+ type: sample.type
6620
+ };
6621
+ };
6622
+
6448
6623
  // src/boxes/iso-base-media/mdat/mdat.ts
6449
6624
  var parseMdat = async ({
6450
6625
  data,
@@ -6518,31 +6693,28 @@ var parseMdat = async ({
6518
6693
  break;
6519
6694
  }
6520
6695
  const bytes = data.getSlice(samplesWithIndex.samplePosition.size);
6521
- const timestamp = samplesWithIndex.samplePosition.cts * 1e6 / samplesWithIndex.track.timescale;
6522
- const duration2 = samplesWithIndex.samplePosition.duration * 1e6 / samplesWithIndex.track.timescale;
6523
- const cts = samplesWithIndex.samplePosition.cts * 1e6 / samplesWithIndex.track.timescale;
6524
- const dts = samplesWithIndex.samplePosition.dts * 1e6 / samplesWithIndex.track.timescale;
6696
+ const { cts, dts, duration: duration2 } = samplesWithIndex.samplePosition;
6525
6697
  if (samplesWithIndex.track.type === "audio") {
6526
- await options.parserState.onAudioSample(samplesWithIndex.track.trackId, {
6698
+ await options.parserState.onAudioSample(samplesWithIndex.track.trackId, convertAudioOrVideoSampleToWebCodecsTimestamps({
6527
6699
  data: bytes,
6528
- timestamp,
6700
+ timestamp: cts,
6529
6701
  duration: duration2,
6530
6702
  cts,
6531
6703
  dts,
6532
6704
  trackId: samplesWithIndex.track.trackId,
6533
6705
  type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta"
6534
- });
6706
+ }, samplesWithIndex.track.timescale));
6535
6707
  }
6536
6708
  if (samplesWithIndex.track.type === "video") {
6537
- await options.parserState.onVideoSample(samplesWithIndex.track.trackId, {
6709
+ await options.parserState.onVideoSample(samplesWithIndex.track.trackId, convertAudioOrVideoSampleToWebCodecsTimestamps({
6538
6710
  data: bytes,
6539
- timestamp,
6711
+ timestamp: cts,
6540
6712
  duration: duration2,
6541
6713
  cts,
6542
6714
  dts,
6543
6715
  trackId: samplesWithIndex.track.trackId,
6544
6716
  type: samplesWithIndex.samplePosition.isKeyframe ? "key" : "delta"
6545
- });
6717
+ }, samplesWithIndex.track.timescale));
6546
6718
  }
6547
6719
  const remaining = size - (data.counter.getOffset() - fileOffset);
6548
6720
  data.removeBytesRead();
@@ -8230,8 +8402,8 @@ var processBox = async ({
8230
8402
  if (transformedTrack) {
8231
8403
  await registerTrack({
8232
8404
  options,
8233
- state: options.parserState,
8234
- track: transformedTrack
8405
+ track: transformedTrack,
8406
+ container: "mp4"
8235
8407
  });
8236
8408
  }
8237
8409
  return {
@@ -8554,15 +8726,164 @@ var isMoviAtom = (iterator, ckId) => {
8554
8726
  return listType === "movi";
8555
8727
  };
8556
8728
 
8729
+ // src/boxes/avc/key.ts
8730
+ var getKeyFrameOrDeltaFromAvcInfo = (infos) => {
8731
+ const keyOrDelta = infos.find((i) => i.type === "keyframe" || i.type === "delta-frame");
8732
+ if (!keyOrDelta) {
8733
+ throw new Error("expected avc to contain info about key or delta");
8734
+ }
8735
+ return keyOrDelta.type === "keyframe" ? "key" : "delta";
8736
+ };
8737
+
8557
8738
  // src/boxes/avc/parse-avc.ts
8739
+ var Extended_SAR = 255;
8740
+ var readVuiParameters = (iterator) => {
8741
+ let sar_width = null;
8742
+ let sar_height = null;
8743
+ let overscan_appropriate_flag = null;
8744
+ let video_format = null;
8745
+ let video_full_range_flag = null;
8746
+ let colour_primaries = null;
8747
+ let transfer_characteristics = null;
8748
+ let matrix_coefficients = null;
8749
+ let chroma_sample_loc_type_top_field = null;
8750
+ let chroma_sample_loc_type_bottom_field = null;
8751
+ const aspect_ratio_info_present_flag = iterator.getBits(1);
8752
+ if (aspect_ratio_info_present_flag) {
8753
+ const aspect_ratio_idc = iterator.getBits(8);
8754
+ if (aspect_ratio_idc === Extended_SAR) {
8755
+ sar_width = iterator.getBits(16);
8756
+ sar_height = iterator.getBits(16);
8757
+ }
8758
+ }
8759
+ const overscan_info_present_flag = iterator.getBits(1);
8760
+ if (overscan_info_present_flag) {
8761
+ overscan_appropriate_flag = iterator.getBits(1);
8762
+ }
8763
+ const video_signal_type_present_flag = iterator.getBits(1);
8764
+ if (video_signal_type_present_flag) {
8765
+ video_format = iterator.getBits(3);
8766
+ video_full_range_flag = Boolean(iterator.getBits(1));
8767
+ const colour_description_present_flag = iterator.getBits(1);
8768
+ if (colour_description_present_flag) {
8769
+ colour_primaries = iterator.getBits(8);
8770
+ transfer_characteristics = iterator.getBits(8);
8771
+ matrix_coefficients = iterator.getBits(8);
8772
+ }
8773
+ }
8774
+ const chroma_loc_info_present_flag = iterator.getBits(1);
8775
+ if (chroma_loc_info_present_flag) {
8776
+ chroma_sample_loc_type_top_field = iterator.readExpGolomb();
8777
+ chroma_sample_loc_type_bottom_field = iterator.readExpGolomb();
8778
+ }
8779
+ return {
8780
+ sar_width,
8781
+ sar_height,
8782
+ overscan_appropriate_flag,
8783
+ chroma_sample_loc_type_bottom_field,
8784
+ chroma_sample_loc_type_top_field,
8785
+ colour_primaries,
8786
+ matrix_coefficients,
8787
+ transfer_characteristics,
8788
+ video_format,
8789
+ video_full_range_flag
8790
+ };
8791
+ };
8558
8792
  var readSps = (iterator) => {
8559
8793
  const profile = iterator.getUint8();
8560
8794
  const compatibility = iterator.getUint8();
8561
8795
  const level = iterator.getUint8();
8562
- return {
8563
- profile,
8796
+ iterator.startReadingBits();
8797
+ const seq_parameter_set_id = iterator.readExpGolomb();
8798
+ let separate_colour_plane_flag = null;
8799
+ let bit_depth_luma_minus8 = null;
8800
+ let bit_depth_chroma_minus8 = null;
8801
+ let qpprime_y_zero_transform_bypass_flag = null;
8802
+ let log2_max_frame_num_minus4 = null;
8803
+ let log2_max_pic_order_cnt_lsb_minus4 = null;
8804
+ let max_num_ref_frames = null;
8805
+ let gaps_in_frame_num_value_allowed_flag = null;
8806
+ let mb_adaptive_frame_field_flag = null;
8807
+ let direct_8x8_inference_flag = null;
8808
+ let frame_crop_left_offset = null;
8809
+ let frame_crop_right_offset = null;
8810
+ let frame_crop_top_offset = null;
8811
+ let frame_crop_bottom_offset = null;
8812
+ let vui_parameters = null;
8813
+ if (!(profile === 100 || profile === 110 || profile === 122 || profile === 244 || profile === 44 || profile === 83 || profile === 86 || profile === 118 || profile === 128 || profile === 138 || profile === 139 || profile === 134 || profile === 135)) {
8814
+ throw new Error("Invalid profile");
8815
+ }
8816
+ const chromaFormat = iterator.readExpGolomb();
8817
+ if (chromaFormat === 3) {
8818
+ separate_colour_plane_flag = iterator.getBits(1);
8819
+ }
8820
+ bit_depth_luma_minus8 = iterator.readExpGolomb();
8821
+ bit_depth_chroma_minus8 = iterator.readExpGolomb();
8822
+ qpprime_y_zero_transform_bypass_flag = iterator.getBits(1);
8823
+ const seq_scaling_matrix_present_flag = iterator.getBits(1);
8824
+ const seq_scaling_list_present_flag = [];
8825
+ if (seq_scaling_matrix_present_flag) {
8826
+ for (let i = 0;i < (chromaFormat !== 3 ? 8 : 12); i++) {
8827
+ seq_scaling_list_present_flag[i] = iterator.getBits(1);
8828
+ if (seq_scaling_list_present_flag[i]) {
8829
+ if (i < 6) {
8830
+ throw new Error("Not implemented");
8831
+ } else {
8832
+ throw new Error("Not implemented");
8833
+ }
8834
+ }
8835
+ }
8836
+ }
8837
+ log2_max_frame_num_minus4 = iterator.readExpGolomb();
8838
+ const pic_order_cnt_type = iterator.readExpGolomb();
8839
+ if (pic_order_cnt_type === 0) {
8840
+ log2_max_pic_order_cnt_lsb_minus4 = iterator.readExpGolomb();
8841
+ } else if (pic_order_cnt_type === 1) {
8842
+ throw new Error("pic_order_cnt_type = 1 not implemented");
8843
+ }
8844
+ max_num_ref_frames = iterator.readExpGolomb();
8845
+ gaps_in_frame_num_value_allowed_flag = iterator.getBits(1);
8846
+ const pic_width_in_mbs_minus1 = iterator.readExpGolomb();
8847
+ const pic_height_in_map_units_minus1 = iterator.readExpGolomb();
8848
+ const frame_mbs_only_flag = iterator.getBits(1);
8849
+ if (!frame_mbs_only_flag) {
8850
+ mb_adaptive_frame_field_flag = iterator.getBits(1);
8851
+ }
8852
+ direct_8x8_inference_flag = iterator.getBits(1);
8853
+ const frame_cropping_flag = iterator.getBits(1);
8854
+ if (frame_cropping_flag) {
8855
+ frame_crop_left_offset = iterator.readExpGolomb();
8856
+ frame_crop_right_offset = iterator.readExpGolomb();
8857
+ frame_crop_top_offset = iterator.readExpGolomb();
8858
+ frame_crop_bottom_offset = iterator.readExpGolomb();
8859
+ }
8860
+ const vui_parameters_present_flag = iterator.getBits(1);
8861
+ if (vui_parameters_present_flag) {
8862
+ vui_parameters = readVuiParameters(iterator);
8863
+ }
8864
+ iterator.stopReadingBits();
8865
+ return {
8866
+ profile,
8564
8867
  compatibility,
8565
- level
8868
+ level,
8869
+ bit_depth_chroma_minus8,
8870
+ bit_depth_luma_minus8,
8871
+ gaps_in_frame_num_value_allowed_flag,
8872
+ log2_max_frame_num_minus4,
8873
+ log2_max_pic_order_cnt_lsb_minus4,
8874
+ max_num_ref_frames,
8875
+ pic_height_in_map_units_minus1,
8876
+ pic_width_in_mbs_minus1,
8877
+ qpprime_y_zero_transform_bypass_flag,
8878
+ separate_colour_plane_flag,
8879
+ seq_parameter_set_id,
8880
+ direct_8x8_inference_flag,
8881
+ frame_crop_bottom_offset,
8882
+ frame_crop_left_offset,
8883
+ frame_crop_right_offset,
8884
+ frame_crop_top_offset,
8885
+ mb_adaptive_frame_field_flag,
8886
+ vui_parameters
8566
8887
  };
8567
8888
  };
8568
8889
  var findEnd = (buffer) => {
@@ -8590,11 +8911,9 @@ var inspect = (buffer) => {
8590
8911
  if (type === 7) {
8591
8912
  const end = findEnd(buffer);
8592
8913
  const data = readSps(iterator);
8593
- const sps = buffer.slice(1, end === null ? Infinity : end);
8914
+ const sps = buffer.slice(0, end === null ? Infinity : end);
8594
8915
  return {
8595
- level: data.level,
8596
- profile: data.profile,
8597
- compatibility: data.compatibility,
8916
+ spsData: data,
8598
8917
  sps,
8599
8918
  type: "avc-profile"
8600
8919
  };
@@ -8673,29 +8992,26 @@ var handleChunk = async ({
8673
8992
  const samplesPerSecond = strh.rate / strh.scale;
8674
8993
  const nthSample = options.parserState.getSamplesForTrack(trackId);
8675
8994
  const timeInSec = nthSample / samplesPerSecond;
8676
- const timestamp = Math.floor(timeInSec * MEDIA_PARSER_RIFF_TIMESCALE);
8677
- const duration2 = Math.floor(1 / samplesPerSecond * MEDIA_PARSER_RIFF_TIMESCALE);
8995
+ const timestamp = Math.floor(timeInSec);
8996
+ const duration2 = Math.floor(1 / samplesPerSecond);
8678
8997
  const data = iterator.getSlice(ckSize);
8679
8998
  const infos = parseAvc(data);
8680
- const keyOrDelta = infos.find((i) => i.type === "keyframe" || i.type === "delta-frame");
8681
- if (!keyOrDelta) {
8682
- throw new Error("expected avc to contain info about key or delta");
8683
- }
8999
+ const keyOrDelta = getKeyFrameOrDeltaFromAvcInfo(infos);
8684
9000
  const avcProfile = infos.find((i) => i.type === "avc-profile");
8685
9001
  const ppsProfile = infos.find((i) => i.type === "avc-pps");
8686
9002
  if (avcProfile && ppsProfile) {
8687
9003
  await options.parserState.onProfile({ pps: ppsProfile, sps: avcProfile });
8688
9004
  options.parserState.tracks.setIsDone();
8689
9005
  }
8690
- await options.parserState.onVideoSample(trackId, {
9006
+ await options.parserState.onVideoSample(trackId, convertAudioOrVideoSampleToWebCodecsTimestamps({
8691
9007
  cts: timestamp,
8692
9008
  dts: timestamp,
8693
9009
  data,
8694
9010
  duration: duration2,
8695
9011
  timestamp,
8696
9012
  trackId,
8697
- type: keyOrDelta.type === "keyframe" ? "key" : "delta"
8698
- });
9013
+ type: keyOrDelta
9014
+ }, 1));
8699
9015
  return;
8700
9016
  }
8701
9017
  const audioChunk = ckId.match(/^([0-9]{2})wb$/);
@@ -8705,9 +9021,9 @@ var handleChunk = async ({
8705
9021
  const samplesPerSecond = strh.rate / strh.scale;
8706
9022
  const nthSample = options.parserState.getSamplesForTrack(trackId);
8707
9023
  const timeInSec = nthSample / samplesPerSecond;
8708
- const timestamp = timeInSec * MEDIA_PARSER_RIFF_TIMESCALE;
8709
- const duration2 = 1 / samplesPerSecond * MEDIA_PARSER_RIFF_TIMESCALE;
8710
- await options.parserState.onAudioSample(trackId, {
9024
+ const timestamp = timeInSec;
9025
+ const duration2 = 1 / samplesPerSecond;
9026
+ await options.parserState.onAudioSample(trackId, convertAudioOrVideoSampleToWebCodecsTimestamps({
8711
9027
  cts: timestamp,
8712
9028
  dts: timestamp,
8713
9029
  data: iterator.getSlice(ckSize),
@@ -8715,7 +9031,7 @@ var handleChunk = async ({
8715
9031
  timestamp,
8716
9032
  trackId,
8717
9033
  type: "key"
8718
- });
9034
+ }, 1));
8719
9035
  }
8720
9036
  };
8721
9037
  var parseMovi = async ({
@@ -9201,8 +9517,8 @@ var parseRiffBody = async ({
9201
9517
  });
9202
9518
  await registerTrack({
9203
9519
  options,
9204
- state: options.parserState,
9205
- track: audioTrack
9520
+ track: audioTrack,
9521
+ container: "avi"
9206
9522
  });
9207
9523
  }
9208
9524
  if (options.onVideoTrack && strf.type === "strf-box-video") {
@@ -9213,8 +9529,8 @@ var parseRiffBody = async ({
9213
9529
  });
9214
9530
  registerVideoTrackWhenProfileIsAvailable({
9215
9531
  options,
9216
- state: options.parserState,
9217
- track: videoTrack
9532
+ track: videoTrack,
9533
+ container: "avi"
9218
9534
  });
9219
9535
  }
9220
9536
  options.nextTrackIndex++;
@@ -9250,6 +9566,749 @@ var parseRiff = ({
9250
9566
  return parseRiffBody({ iterator, structure, maxOffset: Infinity, options });
9251
9567
  };
9252
9568
 
9569
+ // src/boxes/transport-stream/next-pes-header-store.ts
9570
+ var makeNextPesHeaderStore = () => {
9571
+ let nextPesHeader = null;
9572
+ return {
9573
+ setNextPesHeader: (pesHeader) => {
9574
+ nextPesHeader = pesHeader;
9575
+ },
9576
+ getNextPesHeader: () => {
9577
+ if (!nextPesHeader) {
9578
+ throw new Error("No next PES header found");
9579
+ }
9580
+ return nextPesHeader;
9581
+ }
9582
+ };
9583
+ };
9584
+
9585
+ // src/boxes/transport-stream/discard-rest-of-packet.ts
9586
+ var discardRestOfPacket = (iterator) => {
9587
+ const next188 = 188 - iterator.counter.getOffset() % 188;
9588
+ iterator.discard(next188);
9589
+ };
9590
+ var getRestOfPacket = (iterator) => {
9591
+ const next188 = 188 - iterator.counter.getOffset() % 188;
9592
+ return iterator.getSlice(next188);
9593
+ };
9594
+
9595
+ // src/boxes/transport-stream/parse-pat.ts
9596
+ var parsePatTable = (iterator, tableId) => {
9597
+ iterator.getUint16();
9598
+ iterator.startReadingBits();
9599
+ iterator.getBits(7);
9600
+ iterator.getBits(1);
9601
+ const sectionNumber = iterator.getBits(8);
9602
+ const lastSectionNumber = iterator.getBits(8);
9603
+ if (tableId !== 0) {
9604
+ throw new Error("Invalid table ID: " + tableId);
9605
+ }
9606
+ const tables = [];
9607
+ for (let i = sectionNumber;i <= lastSectionNumber; i++) {
9608
+ const programNumber = iterator.getBits(16);
9609
+ iterator.getBits(3);
9610
+ const programMapIdentifier = iterator.getBits(13);
9611
+ tables.push({
9612
+ type: "transport-stream-program-association-table",
9613
+ programNumber,
9614
+ programMapIdentifier
9615
+ });
9616
+ }
9617
+ iterator.stopReadingBits();
9618
+ return {
9619
+ type: "transport-stream-pat-box",
9620
+ tableId: tableId.toString(16),
9621
+ pat: tables
9622
+ };
9623
+ };
9624
+ var parsePat = (iterator) => {
9625
+ iterator.startReadingBits();
9626
+ const tableId = iterator.getBits(8);
9627
+ iterator.getBits(1);
9628
+ iterator.getBits(1);
9629
+ iterator.getBits(4);
9630
+ const sectionLength = iterator.getBits(10);
9631
+ if (sectionLength > 1021) {
9632
+ throw new Error("Invalid section length");
9633
+ }
9634
+ iterator.stopReadingBits();
9635
+ const tables = parsePatTable(iterator, tableId);
9636
+ discardRestOfPacket(iterator);
9637
+ return tables;
9638
+ };
9639
+
9640
+ // src/boxes/transport-stream/parse-pes.ts
9641
+ var parsePes = (iterator) => {
9642
+ const ident = iterator.getUint24();
9643
+ if (ident !== 1) {
9644
+ throw new Error(`Unexpected PES packet start code: ${ident.toString(16)}`);
9645
+ }
9646
+ const streamId = iterator.getUint8();
9647
+ iterator.getUint16();
9648
+ iterator.startReadingBits();
9649
+ const markerBits = iterator.getBits(2);
9650
+ if (markerBits !== 2) {
9651
+ throw new Error(`Invalid marker bits: ${markerBits}`);
9652
+ }
9653
+ const scrambled = iterator.getBits(2);
9654
+ if (scrambled !== 0) {
9655
+ throw new Error(`Only supporting non-scrambled streams`);
9656
+ }
9657
+ const priority = iterator.getBits(1);
9658
+ iterator.getBits(1);
9659
+ iterator.getBits(1);
9660
+ iterator.getBits(1);
9661
+ const ptsPresent = iterator.getBits(1);
9662
+ const dtsPresent = iterator.getBits(1);
9663
+ if (!ptsPresent && dtsPresent) {
9664
+ throw new Error(`DTS is present but not PTS, this is not allowed in the spec`);
9665
+ }
9666
+ iterator.getBits(1);
9667
+ iterator.getBits(1);
9668
+ iterator.getBits(1);
9669
+ iterator.getBits(1);
9670
+ iterator.getBits(1);
9671
+ iterator.getBits(1);
9672
+ const pesHeaderLength = iterator.getBits(8);
9673
+ const offset = iterator.counter.getOffset();
9674
+ let pts = null;
9675
+ if (!ptsPresent) {
9676
+ throw new Error(`PTS is required`);
9677
+ }
9678
+ const fourBits = iterator.getBits(4);
9679
+ if (fourBits !== 3 && fourBits !== 2) {
9680
+ throw new Error(`Invalid PTS marker bits: ${fourBits}`);
9681
+ }
9682
+ const pts1 = iterator.getBits(3);
9683
+ iterator.getBits(1);
9684
+ const pts2 = iterator.getBits(15);
9685
+ iterator.getBits(1);
9686
+ const pts3 = iterator.getBits(15);
9687
+ iterator.getBits(1);
9688
+ pts = pts1 << 30 | pts2 << 15 | pts3;
9689
+ let dts = null;
9690
+ if (dtsPresent) {
9691
+ const _fourBits = iterator.getBits(4);
9692
+ if (_fourBits !== 1) {
9693
+ throw new Error(`Invalid DTS marker bits: ${_fourBits}`);
9694
+ }
9695
+ const dts1 = iterator.getBits(3);
9696
+ iterator.getBits(1);
9697
+ const dts2 = iterator.getBits(15);
9698
+ iterator.getBits(1);
9699
+ const dts3 = iterator.getBits(15);
9700
+ iterator.getBits(1);
9701
+ dts = dts1 << 30 | dts2 << 15 | dts3;
9702
+ }
9703
+ iterator.stopReadingBits();
9704
+ iterator.discard(pesHeaderLength - (iterator.counter.getOffset() - offset));
9705
+ const packet = {
9706
+ dts,
9707
+ pts,
9708
+ streamId,
9709
+ priority
9710
+ };
9711
+ return packet;
9712
+ };
9713
+
9714
+ // src/boxes/transport-stream/parse-pmt.ts
9715
+ var parsePmtTable = ({
9716
+ iterator,
9717
+ tableId,
9718
+ sectionLength
9719
+ }) => {
9720
+ const start = iterator.counter.getOffset();
9721
+ iterator.getUint16();
9722
+ iterator.startReadingBits();
9723
+ iterator.getBits(7);
9724
+ iterator.getBits(1);
9725
+ const sectionNumber = iterator.getBits(8);
9726
+ const lastSectionNumber = iterator.getBits(8);
9727
+ const tables = [];
9728
+ for (let i = sectionNumber;i <= lastSectionNumber; i++) {
9729
+ iterator.getBits(3);
9730
+ iterator.getBits(13);
9731
+ iterator.getBits(4);
9732
+ const programInfoLength = iterator.getBits(12);
9733
+ const streams = [];
9734
+ while (true) {
9735
+ const streamType = iterator.getBits(8);
9736
+ iterator.getBits(3);
9737
+ const elementaryPid = iterator.getBits(13);
9738
+ iterator.getBits(4);
9739
+ const esInfoLength = iterator.getBits(12);
9740
+ iterator.getBits(esInfoLength * 8);
9741
+ streams.push({ streamType, pid: elementaryPid });
9742
+ iterator.getBits(programInfoLength * 8);
9743
+ const remaining = sectionLength - (iterator.counter.getOffset() - start);
9744
+ if (remaining <= 4) {
9745
+ break;
9746
+ }
9747
+ }
9748
+ tables.push({
9749
+ type: "transport-stream-program-map-table",
9750
+ streams
9751
+ });
9752
+ }
9753
+ if (tables.length !== 1) {
9754
+ throw new Error("Does not PMT table with more than 1 entry, uncommon");
9755
+ }
9756
+ iterator.stopReadingBits();
9757
+ return {
9758
+ type: "transport-stream-pmt-box",
9759
+ tableId,
9760
+ streams: tables[0].streams
9761
+ };
9762
+ };
9763
+ var parsePmt = (iterator) => {
9764
+ iterator.startReadingBits();
9765
+ const tableId = iterator.getBits(8);
9766
+ iterator.getBits(1);
9767
+ iterator.getBits(1);
9768
+ iterator.getBits(4);
9769
+ const sectionLength = iterator.getBits(10);
9770
+ if (sectionLength > 1021) {
9771
+ throw new Error("Invalid section length");
9772
+ }
9773
+ iterator.stopReadingBits();
9774
+ const tables = parsePmtTable({ iterator, tableId, sectionLength });
9775
+ discardRestOfPacket(iterator);
9776
+ return tables;
9777
+ };
9778
+
9779
+ // src/boxes/transport-stream/adts-header.ts
9780
+ var readAdtsHeader = (buffer) => {
9781
+ if (buffer.byteLength < 9) {
9782
+ return null;
9783
+ }
9784
+ const iterator = getArrayBufferIterator(buffer, buffer.byteLength);
9785
+ iterator.startReadingBits();
9786
+ const bits = iterator.getBits(12);
9787
+ if (bits !== 4095) {
9788
+ throw new Error("Invalid ADTS header ");
9789
+ }
9790
+ const id = iterator.getBits(1);
9791
+ if (id !== 0) {
9792
+ throw new Error("Only supporting MPEG-4 for .ts");
9793
+ }
9794
+ const layer = iterator.getBits(2);
9795
+ if (layer !== 0) {
9796
+ throw new Error("Only supporting layer 0 for .ts");
9797
+ }
9798
+ const protectionAbsent = iterator.getBits(1);
9799
+ const audioObjectType = iterator.getBits(2);
9800
+ const samplingFrequencyIndex = iterator.getBits(4);
9801
+ const sampleRate = getSampleRateFromSampleFrequencyIndex(samplingFrequencyIndex);
9802
+ iterator.getBits(1);
9803
+ const channelConfiguration = iterator.getBits(3);
9804
+ const codecPrivate2 = createAacCodecPrivate({
9805
+ audioObjectType,
9806
+ sampleRate,
9807
+ channelConfiguration
9808
+ });
9809
+ iterator.getBits(1);
9810
+ iterator.getBits(1);
9811
+ iterator.getBits(1);
9812
+ iterator.getBits(1);
9813
+ const frameLength = iterator.getBits(13);
9814
+ iterator.getBits(11);
9815
+ iterator.getBits(2);
9816
+ if (!protectionAbsent) {
9817
+ iterator.getBits(16);
9818
+ }
9819
+ iterator.stopReadingBits();
9820
+ iterator.destroy();
9821
+ return {
9822
+ frameLength,
9823
+ codecPrivate: codecPrivate2,
9824
+ channelConfiguration,
9825
+ sampleRate,
9826
+ audioObjectType
9827
+ };
9828
+ };
9829
+
9830
+ // src/boxes/transport-stream/find-separator.ts
9831
+ function findSubarrayIndex(array, subarray) {
9832
+ const subarrayLength = subarray.length;
9833
+ const arrayLength = array.length;
9834
+ for (let i = 0;i <= arrayLength - subarrayLength; i++) {
9835
+ let match = true;
9836
+ for (let j = 0;j < subarrayLength; j++) {
9837
+ if (array[i + j] !== subarray[j]) {
9838
+ match = false;
9839
+ break;
9840
+ }
9841
+ }
9842
+ if (match) {
9843
+ if (subarray[i - 1] === 0) {
9844
+ i--;
9845
+ }
9846
+ return i;
9847
+ }
9848
+ }
9849
+ return -1;
9850
+ }
9851
+ var findNextSeparator = (restOfPacket, transportStreamEntry) => {
9852
+ if (transportStreamEntry.streamType === 27) {
9853
+ return findSubarrayIndex(restOfPacket, new Uint8Array([0, 0, 1, 9]));
9854
+ }
9855
+ throw new Error(`Unsupported stream ID ${transportStreamEntry.streamType}`);
9856
+ };
9857
+
9858
+ // src/boxes/avc/interpret-sps.ts
9859
+ var getDimensionsFromSps = (sps) => {
9860
+ const height = sps.pic_height_in_map_units_minus1;
9861
+ const width = sps.pic_width_in_mbs_minus1;
9862
+ return {
9863
+ height: (height + 1) * 16,
9864
+ width: (width + 1) * 16
9865
+ };
9866
+ };
9867
+ var getSampleAspectRatioFromSps = (sps) => {
9868
+ if (sps.vui_parameters?.sar_height && sps.vui_parameters.sar_width) {
9869
+ return {
9870
+ width: sps.vui_parameters.sar_width,
9871
+ height: sps.vui_parameters.sar_height
9872
+ };
9873
+ }
9874
+ return {
9875
+ width: 1,
9876
+ height: 1
9877
+ };
9878
+ };
9879
+ var getVideoColorFromSps = (sps) => {
9880
+ const matrixCoefficients2 = sps.vui_parameters?.matrix_coefficients;
9881
+ const transferCharacteristics2 = sps.vui_parameters?.transfer_characteristics;
9882
+ const colorPrimaries = sps.vui_parameters?.colour_primaries;
9883
+ return {
9884
+ matrixCoefficients: matrixCoefficients2 ? getMatrixCoefficientsFromIndex(matrixCoefficients2) : null,
9885
+ transferCharacteristics: transferCharacteristics2 ? getTransferCharacteristicsFromIndex(transferCharacteristics2) : null,
9886
+ primaries: colorPrimaries ? getPrimariesFromIndex(colorPrimaries) : null,
9887
+ fullRange: sps.vui_parameters?.video_full_range_flag ?? null
9888
+ };
9889
+ };
9890
+
9891
+ // src/boxes/avc/sps-and-pps.ts
9892
+ var getSpsAndPps = (infos) => {
9893
+ const avcProfile = infos.find((i) => i.type === "avc-profile");
9894
+ const ppsProfile = infos.find((i) => i.type === "avc-pps");
9895
+ if (!avcProfile || !ppsProfile) {
9896
+ throw new Error("Expected avcProfile and ppsProfile");
9897
+ }
9898
+ return { pps: ppsProfile, sps: avcProfile };
9899
+ };
9900
+
9901
+ // src/boxes/transport-stream/handle-avc-packet.ts
9902
+ var MPEG_TIMESCALE = 90000;
9903
+ var handleAvcPacket = async ({
9904
+ streamBuffer,
9905
+ programId,
9906
+ options
9907
+ }) => {
9908
+ const avc = parseAvc(streamBuffer.buffer);
9909
+ const isTrackRegistered = options.parserState.tracks.getTracks().find((t) => {
9910
+ return t.trackId === programId;
9911
+ });
9912
+ if (!isTrackRegistered) {
9913
+ const spsAndPps = getSpsAndPps(avc);
9914
+ const dimensions = getDimensionsFromSps(spsAndPps.sps.spsData);
9915
+ const sampleAspectRatio = getSampleAspectRatioFromSps(spsAndPps.sps.spsData);
9916
+ const track = {
9917
+ rotation: 0,
9918
+ trackId: programId,
9919
+ type: "video",
9920
+ timescale: MPEG_TIMESCALE,
9921
+ codec: getCodecStringFromSpsAndPps(spsAndPps.sps),
9922
+ codecPrivate: getAvccBoxContent(spsAndPps),
9923
+ fps: null,
9924
+ codedWidth: dimensions.width,
9925
+ codedHeight: dimensions.height,
9926
+ height: dimensions.height,
9927
+ width: dimensions.width,
9928
+ displayAspectWidth: dimensions.width,
9929
+ displayAspectHeight: dimensions.height,
9930
+ trakBox: null,
9931
+ codecWithoutConfig: "h264",
9932
+ description: undefined,
9933
+ sampleAspectRatio: {
9934
+ denominator: sampleAspectRatio.height,
9935
+ numerator: sampleAspectRatio.width
9936
+ },
9937
+ color: getVideoColorFromSps(spsAndPps.sps.spsData)
9938
+ };
9939
+ await registerTrack({ track, options, container: "transport-stream" });
9940
+ }
9941
+ const sample = {
9942
+ cts: streamBuffer.pesHeader.pts,
9943
+ dts: streamBuffer.pesHeader.dts ?? streamBuffer.pesHeader.pts,
9944
+ timestamp: streamBuffer.pesHeader.pts,
9945
+ duration: undefined,
9946
+ data: new Uint8Array(streamBuffer.buffer),
9947
+ trackId: programId,
9948
+ type: getKeyFrameOrDeltaFromAvcInfo(avc)
9949
+ };
9950
+ await options.parserState.onVideoSample(programId, convertAudioOrVideoSampleToWebCodecsTimestamps(sample, MPEG_TIMESCALE));
9951
+ };
9952
+
9953
+ // src/boxes/transport-stream/handle-aac-packet.ts
9954
+ var handleAacPacket = async ({
9955
+ streamBuffer,
9956
+ options,
9957
+ programId
9958
+ }) => {
9959
+ const adtsHeader = readAdtsHeader(streamBuffer.buffer);
9960
+ if (!adtsHeader) {
9961
+ throw new Error("Invalid ADTS header - too short");
9962
+ }
9963
+ const { channelConfiguration, codecPrivate: codecPrivate2, sampleRate, audioObjectType } = adtsHeader;
9964
+ const isTrackRegistered = options.parserState.tracks.getTracks().find((t) => {
9965
+ return t.trackId === programId;
9966
+ });
9967
+ if (!isTrackRegistered) {
9968
+ const track = {
9969
+ type: "audio",
9970
+ codecPrivate: codecPrivate2,
9971
+ trackId: programId,
9972
+ trakBox: null,
9973
+ timescale: MPEG_TIMESCALE,
9974
+ codecWithoutConfig: "aac",
9975
+ codec: mapAudioObjectTypeToCodecString(audioObjectType),
9976
+ description: undefined,
9977
+ numberOfChannels: channelConfiguration,
9978
+ sampleRate
9979
+ };
9980
+ await registerTrack({
9981
+ track,
9982
+ options,
9983
+ container: "transport-stream"
9984
+ });
9985
+ }
9986
+ const sample = {
9987
+ cts: streamBuffer.pesHeader.pts,
9988
+ dts: streamBuffer.pesHeader.dts ?? streamBuffer.pesHeader.pts,
9989
+ timestamp: streamBuffer.pesHeader.pts,
9990
+ duration: undefined,
9991
+ data: new Uint8Array(streamBuffer.buffer),
9992
+ trackId: programId,
9993
+ type: "key"
9994
+ };
9995
+ await options.parserState.onAudioSample(programId, convertAudioOrVideoSampleToWebCodecsTimestamps(sample, MPEG_TIMESCALE));
9996
+ };
9997
+
9998
+ // src/boxes/transport-stream/process-stream-buffers.ts
9999
+ var processStreamBuffer = async ({
10000
+ streamBuffer,
10001
+ options,
10002
+ programId,
10003
+ structure
10004
+ }) => {
10005
+ const stream = getStreamForId(structure, programId);
10006
+ if (!stream) {
10007
+ throw new Error("No stream found");
10008
+ }
10009
+ if (stream.streamType === 27) {
10010
+ await handleAvcPacket({ programId, streamBuffer, options });
10011
+ } else if (stream.streamType === 15) {
10012
+ await handleAacPacket({ streamBuffer, options, programId });
10013
+ }
10014
+ if (!options.parserState.tracks.hasAllTracks()) {
10015
+ const tracksRegistered = options.parserState.tracks.getTracks().length;
10016
+ const { streams } = findProgramMapTableOrThrow(structure);
10017
+ if (streams.length === tracksRegistered) {
10018
+ options.parserState.tracks.setIsDone();
10019
+ }
10020
+ }
10021
+ };
10022
+ var processFinalStreamBuffers = async ({
10023
+ streamBufferMap,
10024
+ parserContext,
10025
+ structure
10026
+ }) => {
10027
+ for (const [programId, buffer] of streamBufferMap) {
10028
+ if (buffer.buffer.byteLength > 0) {
10029
+ await processStreamBuffer({
10030
+ streamBuffer: buffer,
10031
+ options: parserContext,
10032
+ programId,
10033
+ structure
10034
+ });
10035
+ streamBufferMap.delete(programId);
10036
+ }
10037
+ }
10038
+ };
10039
+
10040
+ // src/boxes/transport-stream/parse-stream-packet.ts
10041
+ var parseAdtsStream = async ({
10042
+ restOfPacket,
10043
+ transportStreamEntry,
10044
+ streamBuffers,
10045
+ nextPesHeader,
10046
+ options,
10047
+ structure
10048
+ }) => {
10049
+ const streamBuffer = streamBuffers.get(transportStreamEntry.pid);
10050
+ if (!streamBuffer) {
10051
+ streamBuffers.set(transportStreamEntry.pid, {
10052
+ buffer: restOfPacket,
10053
+ pesHeader: nextPesHeader
10054
+ });
10055
+ return;
10056
+ }
10057
+ const expectedLength = readAdtsHeader(streamBuffer.buffer)?.frameLength ?? null;
10058
+ const bytesToTake = expectedLength ? Math.min(restOfPacket.length, expectedLength - streamBuffer.buffer.byteLength) : restOfPacket.length;
10059
+ streamBuffer.buffer = combineUint8Arrays([
10060
+ streamBuffer.buffer,
10061
+ restOfPacket.slice(0, bytesToTake)
10062
+ ]);
10063
+ if (expectedLength === streamBuffer.buffer.byteLength) {
10064
+ await processStreamBuffer({
10065
+ streamBuffer,
10066
+ programId: transportStreamEntry.pid,
10067
+ options,
10068
+ structure
10069
+ });
10070
+ const rest = restOfPacket.slice(bytesToTake);
10071
+ streamBuffers.set(transportStreamEntry.pid, {
10072
+ buffer: rest,
10073
+ pesHeader: nextPesHeader
10074
+ });
10075
+ }
10076
+ };
10077
+ var parseAvcStream = async ({
10078
+ restOfPacket,
10079
+ transportStreamEntry,
10080
+ streamBuffers,
10081
+ nextPesHeader,
10082
+ programId,
10083
+ parserContext,
10084
+ structure
10085
+ }) => {
10086
+ const indexOfSeparator = findNextSeparator(restOfPacket, transportStreamEntry);
10087
+ const streamBuffer = streamBuffers.get(transportStreamEntry.pid);
10088
+ if (indexOfSeparator === -1) {
10089
+ if (streamBuffer) {
10090
+ streamBuffer.buffer = combineUint8Arrays([
10091
+ streamBuffer.buffer,
10092
+ restOfPacket
10093
+ ]);
10094
+ return;
10095
+ }
10096
+ streamBuffers.set(programId, {
10097
+ pesHeader: nextPesHeader,
10098
+ buffer: restOfPacket
10099
+ });
10100
+ return;
10101
+ }
10102
+ if (streamBuffer) {
10103
+ const packet = restOfPacket.slice(0, indexOfSeparator);
10104
+ streamBuffer.buffer = combineUint8Arrays([streamBuffer.buffer, packet]);
10105
+ await processStreamBuffer({
10106
+ options: parserContext,
10107
+ streamBuffer,
10108
+ programId,
10109
+ structure
10110
+ });
10111
+ const rest = restOfPacket.slice(indexOfSeparator);
10112
+ streamBuffers.set(programId, {
10113
+ pesHeader: nextPesHeader,
10114
+ buffer: rest
10115
+ });
10116
+ return;
10117
+ }
10118
+ if (indexOfSeparator !== 0) {
10119
+ throw new Error("No stream buffer found but new separator is not at the beginning");
10120
+ }
10121
+ streamBuffers.set(programId, {
10122
+ pesHeader: nextPesHeader,
10123
+ buffer: restOfPacket.slice(indexOfSeparator)
10124
+ });
10125
+ };
10126
+ var parseStream = ({
10127
+ iterator,
10128
+ transportStreamEntry,
10129
+ streamBuffers,
10130
+ parserContext,
10131
+ programId,
10132
+ structure,
10133
+ nextPesHeader
10134
+ }) => {
10135
+ const restOfPacket = getRestOfPacket(iterator);
10136
+ if (transportStreamEntry.streamType === 27) {
10137
+ return parseAvcStream({
10138
+ restOfPacket,
10139
+ transportStreamEntry,
10140
+ streamBuffers,
10141
+ nextPesHeader,
10142
+ parserContext,
10143
+ programId,
10144
+ structure
10145
+ });
10146
+ }
10147
+ if (transportStreamEntry.streamType === 15) {
10148
+ return parseAdtsStream({
10149
+ restOfPacket,
10150
+ transportStreamEntry,
10151
+ streamBuffers,
10152
+ nextPesHeader,
10153
+ options: parserContext,
10154
+ structure
10155
+ });
10156
+ }
10157
+ throw new Error(`Unsupported stream type ${transportStreamEntry.streamType}`);
10158
+ };
10159
+
10160
+ // src/boxes/transport-stream/parse-packet.ts
10161
+ var parsePacket = async ({
10162
+ iterator,
10163
+ structure,
10164
+ streamBuffers,
10165
+ parserContext,
10166
+ nextPesHeaderStore
10167
+ }) => {
10168
+ const offset = iterator.counter.getOffset();
10169
+ const syncByte = iterator.getUint8();
10170
+ if (syncByte !== 71) {
10171
+ throw new Error("Invalid sync byte");
10172
+ }
10173
+ iterator.startReadingBits();
10174
+ iterator.getBits(1);
10175
+ const payloadUnitStartIndicator = iterator.getBits(1);
10176
+ iterator.getBits(1);
10177
+ const programId = iterator.getBits(13);
10178
+ iterator.getBits(2);
10179
+ const adaptationFieldControl1 = iterator.getBits(1);
10180
+ iterator.getBits(1);
10181
+ iterator.getBits(4);
10182
+ iterator.stopReadingBits();
10183
+ if (adaptationFieldControl1 === 1) {
10184
+ iterator.startReadingBits();
10185
+ const adaptationFieldLength = iterator.getBits(8);
10186
+ const headerOffset = iterator.counter.getOffset();
10187
+ if (adaptationFieldLength > 0) {
10188
+ iterator.getBits(1);
10189
+ iterator.getBits(1);
10190
+ iterator.getBits(1);
10191
+ iterator.getBits(1);
10192
+ iterator.getBits(1);
10193
+ iterator.getBits(1);
10194
+ iterator.getBits(1);
10195
+ iterator.getBits(1);
10196
+ }
10197
+ const remaining = adaptationFieldLength - (iterator.counter.getOffset() - headerOffset);
10198
+ iterator.stopReadingBits();
10199
+ const toDiscard = Math.max(0, remaining);
10200
+ iterator.discard(toDiscard);
10201
+ }
10202
+ const read = iterator.counter.getOffset() - offset;
10203
+ if (read === 188) {
10204
+ return Promise.resolve(null);
10205
+ }
10206
+ const pat = structure.boxes.find((b) => b.type === "transport-stream-pmt-box");
10207
+ const isPes = payloadUnitStartIndicator && pat?.streams.find((e) => e.pid === programId);
10208
+ if (isPes) {
10209
+ const packetPes = parsePes(iterator);
10210
+ nextPesHeaderStore.setNextPesHeader(packetPes);
10211
+ } else if (payloadUnitStartIndicator === 1) {
10212
+ iterator.getUint8();
10213
+ }
10214
+ if (programId === 0) {
10215
+ return Promise.resolve(parsePat(iterator));
10216
+ }
10217
+ const program = getProgramForId(structure, programId);
10218
+ if (program) {
10219
+ const pmt = parsePmt(iterator);
10220
+ return Promise.resolve(pmt);
10221
+ }
10222
+ const stream = getStreamForId(structure, programId);
10223
+ if (stream) {
10224
+ await parseStream({
10225
+ iterator,
10226
+ transportStreamEntry: stream,
10227
+ streamBuffers,
10228
+ nextPesHeader: nextPesHeaderStore.getNextPesHeader(),
10229
+ parserContext,
10230
+ programId,
10231
+ structure
10232
+ });
10233
+ return Promise.resolve(null);
10234
+ }
10235
+ throw new Error("Unknown packet identifier");
10236
+ };
10237
+
10238
+ // src/boxes/transport-stream/parse-transport-stream.ts
10239
+ var parseTransportStream = async ({
10240
+ iterator,
10241
+ parserContext,
10242
+ structure,
10243
+ streamBuffers,
10244
+ fields,
10245
+ nextPesHeaderStore
10246
+ }) => {
10247
+ if (iterator.bytesRemaining() === 0) {
10248
+ await processFinalStreamBuffers({
10249
+ streamBufferMap: streamBuffers,
10250
+ parserContext,
10251
+ structure
10252
+ });
10253
+ return Promise.resolve({
10254
+ status: "done",
10255
+ segments: structure
10256
+ });
10257
+ }
10258
+ while (true) {
10259
+ if (hasAllInfo({
10260
+ fields,
10261
+ state: parserContext.parserState,
10262
+ structure
10263
+ })) {
10264
+ break;
10265
+ }
10266
+ if (iterator.bytesRemaining() < 188) {
10267
+ return Promise.resolve({
10268
+ status: "incomplete",
10269
+ segments: structure,
10270
+ skipTo: null,
10271
+ continueParsing: () => {
10272
+ return parseTransportStream({
10273
+ iterator,
10274
+ parserContext,
10275
+ structure,
10276
+ streamBuffers,
10277
+ fields,
10278
+ nextPesHeaderStore
10279
+ });
10280
+ }
10281
+ });
10282
+ }
10283
+ const packet = await parsePacket({
10284
+ iterator,
10285
+ structure,
10286
+ streamBuffers,
10287
+ parserContext,
10288
+ nextPesHeaderStore
10289
+ });
10290
+ if (packet) {
10291
+ structure.boxes.push(packet);
10292
+ break;
10293
+ }
10294
+ }
10295
+ return Promise.resolve({
10296
+ segments: structure,
10297
+ status: "incomplete",
10298
+ continueParsing() {
10299
+ return parseTransportStream({
10300
+ iterator,
10301
+ parserContext,
10302
+ structure,
10303
+ streamBuffers,
10304
+ fields,
10305
+ nextPesHeaderStore
10306
+ });
10307
+ },
10308
+ skipTo: null
10309
+ });
10310
+ };
10311
+
9253
10312
  // src/boxes/webm/segments/block-simple-block-flags.ts
9254
10313
  var parseBlockFlags = (iterator, type) => {
9255
10314
  if (type === matroskaElements.Block) {
@@ -9456,9 +10515,9 @@ var postprocessEbml = async ({
9456
10515
  });
9457
10516
  if (track) {
9458
10517
  await registerTrack({
9459
- state: parserContext.parserState,
9460
10518
  options: parserContext,
9461
- track
10519
+ track,
10520
+ container: "webm"
9462
10521
  });
9463
10522
  }
9464
10523
  }
@@ -9928,6 +10987,19 @@ var parseVideo = ({
9928
10987
  Log.verbose(logLevel, "Detected Matroska container");
9929
10988
  return parseWebm({ counter: iterator, parserContext: options, fields });
9930
10989
  }
10990
+ if (iterator.isTransportStream()) {
10991
+ return parseTransportStream({
10992
+ iterator,
10993
+ parserContext: options,
10994
+ structure: {
10995
+ type: "transport-stream",
10996
+ boxes: []
10997
+ },
10998
+ streamBuffers: new Map,
10999
+ fields,
11000
+ nextPesHeaderStore: makeNextPesHeaderStore()
11001
+ });
11002
+ }
9931
11003
  if (iterator.isMp3()) {
9932
11004
  return Promise.reject(new Error("MP3 files are not yet supported"));
9933
11005
  }
@@ -9950,7 +11022,8 @@ var needsTracksField = {
9950
11022
  tracks: true,
9951
11023
  unrotatedDimensions: true,
9952
11024
  videoCodec: true,
9953
- metadata: true
11025
+ metadata: true,
11026
+ location: true
9954
11027
  };
9955
11028
  var makeCanSkipTracksState = ({
9956
11029
  hasAudioTrackHandlers,
@@ -9971,12 +11044,17 @@ var makeCanSkipTracksState = ({
9971
11044
 
9972
11045
  // src/state/has-tracks-section.ts
9973
11046
  var makeTracksSectionState = (canSkipTracksState) => {
11047
+ const tracks2 = [];
9974
11048
  let doneWithTracks = false;
9975
11049
  return {
9976
11050
  hasAllTracks: () => doneWithTracks,
9977
11051
  setIsDone: () => {
9978
11052
  doneWithTracks = true;
9979
11053
  },
11054
+ addTrack: (track) => {
11055
+ tracks2.push(track);
11056
+ },
11057
+ getTracks: () => tracks2,
9980
11058
  ensureHasTracksAtEnd: () => {
9981
11059
  if (canSkipTracksState.canSkipTracks()) {
9982
11060
  return;
@@ -10199,10 +11277,10 @@ var parseMedia = async ({
10199
11277
  };
10200
11278
  triggerInfoEmit();
10201
11279
  while (parseResult === null || parseResult.status === "incomplete") {
10202
- if (signal?.aborted) {
10203
- throw new Error("Aborted");
10204
- }
10205
11280
  while (true) {
11281
+ if (signal?.aborted) {
11282
+ throw new Error("Aborted");
11283
+ }
10206
11284
  const result = await currentReader.reader.read();
10207
11285
  if (iterator) {
10208
11286
  if (!result.done) {